Active Record Rails 4

1

If I have an Evaluation model and I make avaliacaoes = Avaliacao.all and then avaliacoes.where("score = ?", 3) . In the first command Rails fetches all evaluations, what happens in the second command? Will Rails get the core appraisals or does it use the evaluations that are loaded into memory?

    
asked by anonymous 26.08.2014 / 21:32

2 answers

1

In Rails 4, other than 3, when calling the all method, Active Record does not return a Array , but a child object of ActiveRecord::Relation . Since the queries return this Relation , now we can chain our queries so that they produce only one sql:

Client.all.where("name = ?", "Juliano")
=> Client Load (0.7ms)  SELECT "clients".* FROM "clients" WHERE (name = 'Juliano')

However, doing as you asked, ActiveRecord will generate two queries, since they are not chained. The object evaluations is a Relation, so it will rather make a second call to the bank.

For single-seat access, you must chain both calls together. If it is not possible, you can deal with the result already in memory with the select method:

avaliacaoes = Avaliacao.all
avaliacoes.select {|a| a.score == 3}

Errata

As pointed out by @GuiGS, part of my answer should be corrected. When you use Relation more than once in the same method, it will only be evaluated at the end, so your code will only do a search in the database, even though the calls are not visibly chained (obj.metodo1.metodo2) they will only be evaluated when the data is needed.

It's only important to note that if you have multiple conditions, some conditions can be ignored.

avaliacaoes = Avaliacao.all
avaliacoes.where("score = ?", 3)
avaliacoes.where("score = ?", 2)

It will generate

=> Avaliacao Load (0.7ms)  SELECT "avaliacoes".* FROM "avaliacoes" WHERE (score = 2)

Sorry for the mistake, I fell into this because I tested my answer directly on the console, then every evaluation was done immediately. My bad! ;)

    
26.08.2014 / 23:39
0

In this situation, I think it is more valid to bring the filtered evaluations already, using .where(condition) so that the sql is generated correctly and does a query only, eg:

Avaliacoes.where("score = ?", 3)

For the recommendation case, look at the method .partition of class Enumerable , with it you will receive like return, two arrays, one case the passed condition is true, and another case is false, eg:

(1..6).partition {|v| v.even? }
#=> [[2, 4, 6], [1, 3, 5]]
    
27.08.2014 / 20:45