Ruby on Rails Model Query Language Examples

Prerequisites

Before you can actually go and run the examples, you must have a Rails project created, so that we can leverage from the ActiveRecord and ActiveSupport benefits. Once this is done, please make sure, that you have installed the Dhaka gem as well. The most simple way to achieve this is doing the following from your command line.

gem install dhaka

Once you have everything setup, please make sure, that you have some models in your Rails project defined, so that we can actually query on these models.

Simple Query

This would be one of the most simple examples to create a query on the User model

for $x in User return <user>{$x/name}</user>

And this is the result if we have two users in the database

<user>Grund</user>
<user>Schmidt</user>

As any XML developer knows, this is not a valid XML document, so let's insert a root node, to make everybody happy.

Simple Query with enclosing tags

<users>
  for $x in User return
    <user>{$x/name}</user>
</users>

And this is the result if we have two users in the database

<users>
<user>Grund</user>
<user>Schmidt</user>
</users>

Simple Query with nested Structure

To make this example even more appealing, we do not only want to read the name from the database, but as well the first name and the city where the user is located. The fields we need to query are now: name, first_name and city. The query would now look like this.

<users>
  for $x in User return
    <user>
    <name>{$x/name}</name>
    <first_name>{$x/first_name}</first_name>
    <city>{$x/city}</city>
    </user>
</users>

Of course does the result reflect this structure and would look like this.

<users>
    <user>
    <name>Grund</name>
    <first_name>Martin</first_name>
    <city>Berlin</city>
    </user>
    <user>
    <name>Schmidt</name>
    <first_name>Gregor</first_name>
    <city>Berlin</city>
    </user>
</users>

Simple Query with a simple Subquery

If we look at our iterative desgin we can now deliver almost all data, that users want to read from our application. But models are not always that simple and we may have different relation types specified. For example imagine, that you store fotos for a user. In this case you would have 1:n relation between Users and Foto

If you would query the dynamic fotos method of the model, the RMQL Runtime would call the to_s mehtod on the return value. If it would be an Array the result would be the String representation of this Array.

But since RMQL is able of handling sub selects we can easily solve this problem.

<users>
  for $x in User return
    <user>
    <name>{$x/name}</name>
    <first_name>{$x/first_name}</first_name>
    <city>{$x/city}</city>
    <fotos>
    {
      for $foto in $x/fotos return
       <foto>{$foto/title}</foto>
     }
    </fotos>
    </user>
</users>

According to the Query, the Result may look like this

<users>
    <user>
    <name>Grund</name>
    <first_name>Martin</first_name>
    <city>Berlin</city>
    <fotos>
    <foto>Die Nacht</foto>
    </fotos>
    </user>
    <user>
    <name>Schmidt</name>
    <first_name>Gregor</first_name>
    <fotos></fotos>
    <city>Berlin</city>
    </user>
</users>

Conclusions

As we can see, if we leave the field of simple queries, this can start to be complex. But there is a difference here. Instead of changing the server, we did not touch the server at all. We as the application developer are capable of expressing what we need and how we want to consume it.