paint-brush
Meeting the Query Interface in Ruby on Railsby@guadalupe-rangel
560 reads
560 reads

Meeting the Query Interface in Ruby on Rails

by Guadalupe Rangel June 23rd, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Ruby on Rails has many in built methods, it's in its nature; at some point it can create some sort of stigma due to its, well known, slowness performance, but several of those methods already can help you to write a clean and faster code.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - Meeting the Query Interface in Ruby on Rails
Guadalupe Rangel  HackerNoon profile picture

Ruby on Rails has many in built methods, it's in its nature; at some point it can create some sort of stigma due to its, well known, slowness performance, but several of those methods already can help you to write a clean and faster code.

The so called Query Interface is the result of a mixture between several finder methods provided by Active Record, which access to the database and retrieve the wanted data in the way you asked.

That means that the Active Record interactive interface let's you structure, modify or retrieve your data in Ruby instead in the app's query language, receiving newly instantiated Ruby objects of the model that corresponds with the query. 

The methods that make up the Query Interface will return an instance of ActiveRecord::Relation declared on the ActiveRecord module, (the core of the query syntax in Rails), and will let you to manipulate the amount, the specificity and the way the data is shown.

The query methods only read and / or order the data, falling into the next descriptive categories:

  1. Retrieve single objects.
  2. Retrieve multiple objects.
  3. Use conditions.
  4. Return specific number of objects.
  5. Return a specific categorization of object.
  6. Order data.

To see the full list of methods you can click here. In this article I'll focus in the more common and useful finder methods.

Let's analyze a few methods.

Single objects methods.

One the most recognizable features about the single objects query methods is that they retrieve a row of a database table, in other words, a single object.

The find method accepts a parameter, the id number of the object to find, and returns that only object. In our example image we can see how the number one is being passed, (you can pass any integer number), but this line of code can be easily replaced by the next one, using the first method:

Bot of the methods are one single objects methods, and are equivalent to one another. In a similar way we count with the second and last methods.

Multiple object methods.

The multiple objects methods have the characteristic of retrieving all the data encapsulated inside a database column. Thanks to the big amount of information that this methods manage, some of the most interesting pieces of code inside your data model belongs to this category. Let's see some of them to understand why.

The pluck method is a shortcut that fetch directly one, or more, specific table's columns on the database retrieving a list of objects.

In the example above, the author column inside the Article table, is pointed directly without accessing to all the non necessary information in the table, resulting in a faster response compared with other type of multiple object query methods, such as the all method.

The ids finder method allows you to write even less code when you want to retrieve only a list of ids, you don't even have to use the pluck method.

Conditions in queries.

The query where method filters information following the instructions written inside its parenthesis, (conditions), and fetching the right amount of data asked by the conditions.

The syntax of the image example for the where method shows us an array passed as a parameter, but there are several other class objects that can be passed too, the important thing to notice is the and word, that builds up the condition as a logical one. In fact, what we are passing as a parameter in the first picture is exactly the same as in the picture below, a selection for an strictly existence of the two attributes, the name John AND the surname Doe.

The concept behind the condition is a familiar logical expression for many of us, but it's important to notice that, depending on the type of the parameter passed as the container of the condition, we will write our condition differently. Click here for more information.

Specific number of objects.

The methods that belongs to this category are simple, you can use the limit method to tell the number of records to be fetched, and use offset query method to tell the number of records to skip before starting to return the records.
A code like the one in the picture above will return ten articles starting from the tenth position. If no offset is declared, the retrieved data will include only the limit specified objects starting since the first position stored.

Specific categorization of object.

The interesting thing begins with this method, the scope query allows you to implement several combinations of other query methods by chaining your customized version of them and giving you freedom for applying your database architecture.

The scope differs from a normal class method in it's safety, the first one will always return a relation, whereas our simple class method implementation will not and can break the chain ability, plus, if you have a relation you can access to it's data, directly from the view or the controller, without writing more code.

As it's shown in the image, for declaring a scope you: First of, name your scope, then, write the parameter / attribute to pass and the block that manipulate the passed data.

For invoking your scope / scopes, you chain them to your data table object and pass the parameters that you need. You see? The logic for declaring and invoking a scope is really similar to the one you follow for declaring a class method. For more implementations, let's go to the next section.

Ordering Data.

The order method help us to order the data, obviously. It's one of the most interesting query methods that we have because of the two different implementations that we can use, and the importance that can have at the moment we write our code.

In the first picture we see a simple ordering code, where the order method accepts a parameter, this parameter can be an attribute, a string and a column name. If no direction of order is specified, the ascending order will be applied by default. For specify this order direction you can see the next syntax:

The importance of the order method resides in it's application alongside with other query methods, for example, when you have several objects to be displayed on the screen, the best practice is to do the order action since the data model and not in the controller or in the view. Let's pass to the two pictures below: In the first one we can see the declaration of a default_scope, (it means the default state, that you customize, for your data model and will be present in every action made with it's data), here we are saying the all the objects in the model will be ordered at descent order by default, so, every time that you call your data from the view, like in the second image, the data will be displayed at descent order without any new line of code.

Another alternative is to declaring a named scope and call it from the view, like in the pictures below.

By implementing this logic, you'll reduce the amount of code you write but, so far so good, even when we saw many important shortcuts, that's not all, we learnt before that manipulating the data directly from the model it's a best practice, but it's not a good one assign it in the view.

Why?

Calling the database query it's one of the most expensive parts for Rails, the instance variables are set with all the object's information one and only one time: When they are created in the controller, this means that you are accessing to the database only one time for each object, and compared to the scope called from the view, where the database is invoked every time you use the query method, the assignment in the controller is considerably more optimal. In order to use that already-invoked data you should do all the assignment work in the controller, where you are declaring your instance variable, like in the example below:

This implementations will lead you to optimize your code, to apply the best practices, to be prudent at the moment you plan your Rails app and to built your own Query Interface taking in count the diversity of the query methods that Rails have and the features of your application. Let's go and try it!

P.S.: Finally but not last, you can always pass your customized database variables inside a partial using locals:

Or deciding if you need to use the database:

It always depends on you, choose reasonably.