ActiveRecord: treating the has_many list as a simple array

Consider this simple: has_many relation:

class Basket < ActiveRecord::Base has_many :apples ... end class Apple < ActiveRecord::Base belongs_to :basket end 

Now I have a method in the Basket class in which I want to create a temporary copy of the apples array and manipulate the temporary copy. First, I want to add a new item to a temporary copy as follows:

 class Basket < ActiveRecord::Base has_many :apples def do_something #create a temporary working copy of the apples array temp_array = self.apples #create a new Apple object to insert in the temporary array temp_apple = Apple.new #add to my temporary array only temp_array << temp_apple #Problem! temp_apple.validate gets called but I don't want it to. end end 

When I do this, I find that validate routines are called on a temporary Apple object when I try to add it to my temporary array. The whole reason I created a temporary array is to avoid all the behavior that comes with the main array, such as checking, inserting a database, etc.

However, I found brute force to avoid this problem by creating temp_array one object at a time in a for loop, as shown below. It works, but it is ugly. I am wondering if there is a more elegant way to achieve this.

 class Basket < ActiveRecord::Base has_many :apples def do_something #create a temporary working copy of the apples array temp_array = [] for x in self.apples temp_array << x end #create a new Apple object to insert in the temporary array temp_apple = Apple.new #add to my temporary array only temp_array << temp_apple #Yippee! the temp_apple.validate routine doesn't get called this time!. end end 

If anyone has a better solution to this problem than what I heard, I'd love to hear it.

Thanks!

+4
source share
3 answers

The problem is that self.apples is not really an array - it is a relation that will be resolved after applying the Array / Enumerable method to it. So after that: temp_array = self.apples even the SQL query was not running.

A simple solution to force data and get rid of all this relationship behavior is to simply use the all method:

 #create a temporary working copy of the apples array temp_array = self.apples.all 
+9
source
 temp_array = self.apples # => This results in an instance of ActiveRecord::Relation, not an Array 

You can try to clearly assess the attitude

 temp_array = self.apples.all # => This will give you an Array 
+2
source

I find it more logical to use self.apples.to_a (= to_array):

Basically, ActiveRecord::Relation is an object that extends Array itself, that is, it has all the Array skills, but more.

If you need to reduce the skills of ActiveRecord::Relation , convert it to an array, and you're good.

+1
source

Source: https://habr.com/ru/post/1393180/


All Articles