11

我有一个有趣的问题。我正在使用 Ruby 1.9.2 和 Rails 3.1.3。

我有 2 个模型,为简化起见,假设客户和商店。商店有很多顾客,一个顾客属于一个商店。我正在尝试为一家商店收集所有客户,并为更多的客户创建一个地方,以便以后可以填充值。相反,当我不期望它时,会调用 customer.save。

store = Store.find(1)
customers_array = store.customers
random_array = Array.new
customers_count = customers_array.count + 1 

(customers_count..2).each do |i|
  customer = Customer.new
  c.id = "#{i}000000000000"
  random_array << customer # this line doesn't call customer.save
  customers_array << customer # this line calls customer.save when store has customers
end

出于某种原因,当客户被推入数组时,会调用 customer.save。如果您推送的数组是普通数组而不是关系,则不会发生这种情况。

我找到了解决方法,但我仍然想知道为什么会发生这种情况。解决方法:

store = Store.find(1)
initial_customers_array = store.customers
additional_customers_array = Array.new
customers_count = initial_customers_array.count + 1 

(customers_count..2).each do |i|
  customer = Customer.new
  c.id = "#{i}000000000000"
  additional_customers_array << customer 
end
customers_array = initial_customers_array + additional_customers_array
4

2 回答 2

22

<<是一个别名push

ActiveRecord::Associations::CollectionProxy电话中concat

调用concat_records

在那里你可以看到插入发生。

因此,使用现有记录(持久化到数据库中),运行<<.push将记录插入到集合中,必要时将它们持久化到数据库中。调用<<一个数组,而不是记录集合,就像你在做的那样

random_array << customer

调用 Ruby 的<<Array 方法,而不是 AR 等效方法(如您所见,在这种情况下不进行保存)

编辑:需要明确的是,您找到的解决方法或多或少是我通常如何处理您正在处理的情况;我的回答更侧重于为什么 <<会有这种行为。

于 2012-06-15T00:59:56.650 回答
4

解决此问题的另一种方法是将第二行(原始代码)更改为:

customers_array = store.customers.to_a

这会将活动记录关联转换为真正的数组对象,因此该<<方法将是普通的 Array#push 方法。

于 2013-09-15T19:46:32.557 回答