Rails and Arel's where function: Can I call where on objects instead of making a call to the database?

StackOverflow https://stackoverflow.com/questions/21819306

  •  12-10-2022
  •  | 
  •  

Question

Consider the following:

  • budget has many objects in its another_collection.
  • obj has many objects of the same type as object in its another_collection.
  • budget and some_collection are already declared before the following loop they've been previous saved in the database and have primary keys set.
  • some_collection is a collections of objs.

-

some_collection.each do |obj|
  another_obj = obj.another_collection.build
  budget.another_collection << another_obj
end

budget.another_collection.collect {|another_obj| another_obj.another_obj_id}
=> [1, 2, 3, 4]
some_obj_with_pk_1 = some_collection.where(obj_id: obj.id)
some_obj_with_pl_1.id
=> 1
budget.another_collection.where(another_obj_id: some_obj_with_pk_1.id)
=> []

This shouldn't happen. What is happening is that rails queries the database for any items in another_collection with another_obj_id = 1. Since this collection hasn't been saved to the database yet, none of these items are showing up in the results.

Is there a function or something I can pass to Arel's where method that says to use local results only? I know I can just iterate over the items and find it but it would be great if I didn't have to do that and just use a method that does this already.

Was it helpful?

Solution

You could always use Enumeable#select which takes a block and returns only the elements that the block returns true for. You'd want to make sure that you had ActiveRecord retrieve the result set first (by calling to_a on your query).

records = Model.where(some_attribute: value).to_a
filtered_records = records.select { |record| record.something? }

Depending on your result set and your needs, it is possible that a second database query would be faster, as your SQL store is better suited to do these comparisons than Ruby. But if your records have yet to be saved, you would need to do something like the above, since the records aren't persisted yet

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top