Rails遍历模型并改变值并不起作用

时间:2015-06-02 11:55:29

标签: ruby-on-rails activerecord

我有一个PiggyBank模型,其中一个属性是interest_modifier(格式:十进制)。我编写了以下方法将interest_modifier更改为随机数:

  def set_random_interest_modifier(min = 0.5, max = 1)
    self.interest_modifier = rand(min..max).round(2)
    self.save!
  end

有效。现在,我想要一个迭代所有PiggyBanks并更改interest_modifier的方法,所以我写了这个:

  def self.change_interest_modifiers
    find_each do |pb|
      pb.set_random_interest_modifier
    end
  end

它迭代所有记录,但不会更改值。继承人的日志

[12] pry(main)> PiggyBank.change_interest_modifiers
  PiggyBank Load (1.4ms)  SELECT  "piggy_banks".* FROM "piggy_banks"   ORDER BY "piggy_banks"."id" ASC LIMIT 1000
   (0.3ms)  BEGIN
  SQL (1.0ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 7  [["interest_modifier", "0.58"], ["updated_at", "2015-06-02 11:53:33.981262"]]
   (3.1ms)  COMMIT
   (0.4ms)  BEGIN
  SQL (0.7ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 8  [["interest_modifier", "0.53"], ["updated_at", "2015-06-02 11:53:33.990404"]]
   (0.4ms)  COMMIT
   (0.2ms)  BEGIN
  SQL (0.7ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 9  [["interest_modifier", "0.78"], ["updated_at", "2015-06-02 11:53:33.994231"]]
   (0.4ms)  COMMIT
   (0.2ms)  BEGIN
  SQL (0.7ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 10  [["interest_modifier", "0.68"], ["updated_at", "2015-06-02 11:53:33.997966"]]
   (0.5ms)  COMMIT
   (0.2ms)  BEGIN
  SQL (0.7ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 11  [["interest_modifier", "0.71"], ["updated_at", "2015-06-02 11:53:34.002414"]]
   (0.5ms)  COMMIT
   (0.1ms)  BEGIN
   (0.1ms)  COMMIT
   (0.1ms)  BEGIN
  SQL (0.5ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 13  [["interest_modifier", "0.91"], ["updated_at", "2015-06-02 11:53:34.007100"]]
   (0.5ms)  COMMIT
   (0.1ms)  BEGIN
  SQL (0.6ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 14  [["interest_modifier", "0.96"], ["updated_at", "2015-06-02 11:53:34.010488"]]
   (0.4ms)  COMMIT
   (0.2ms)  BEGIN
  SQL (0.6ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 15  [["interest_modifier", "0.8"], ["updated_at", "2015-06-02 11:53:34.014190"]]
   (0.5ms)  COMMIT
   (0.3ms)  BEGIN
  SQL (0.6ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 16  [["interest_modifier", "0.71"], ["updated_at", "2015-06-02 11:53:34.018658"]]
   (0.5ms)  COMMIT
   (0.2ms)  BEGIN
  SQL (0.6ms)  UPDATE "piggy_banks" SET "interest_modifier" = $1, "updated_at" = $2 WHERE "piggy_banks"."id" = 18  [["interest_modifier", "0.67"], ["updated_at", "2015-06-02 11:53:34.023011"]]
   (0.5ms)  COMMIT
=> nil

现在,我不知道为什么会这样。没有错误。请帮助:)

在控制台中重新加载几次实验后:

p = PiggyBank.first
p.interest_modifier.to_s => "0.69"
PiggyBank.change_interest_modifiers
p.interest_modifier.to_s => "0.69"
reload!
p.interest_modifier.to_s => "0.69"

但是,如果我执行以下操作,它可以工作:

p = PiggyBank.first
p.interest_modifier.to_s => "0.69"
PiggyBank.change_interest_modifiers
p.interest_modifier.to_s => "0.69"
p.reload
p.interest_modifier.to_s => "0.57"

为什么会这样?

2 个答案:

答案 0 :(得分:0)

嗯,该方法从一开始就有用,只是忘了重新加载资源:O

答案 1 :(得分:0)

这就是发生的事情:

mysql for beginner | 8
ajax for dummies   | 4

所以我们在内存中创建了一个对象,我们已经创建了一个对象,并且在创建过程中,它将数据从数据库中加载出来。

p = PiggyBank.first
p.interest_modifier.to_s => "0.69"

这将迭代所有PiggyBank记录,为每个记录创建一个对象。这些对象都是您已经完成的不同对象。因此,实际上,有两个不同的对象来自同一记录。如果你愿意,class方法中的对象会将新数据保存到数据库中,隐藏在后面。

这些物品没有" live"连接到数据库 - 也就是说,如果数据库是通过其他方法更改的,则内存中的对象不会使用新数据神奇地更新自己。

所以,当你坐在那里时,其他一些东西改变了数据库中的数据。当您说PiggyBank.change_interest_modifiers 时,您只是访问对象内的实例变量,而您却无法访问数据库。

然后再继续说

p.interest_modifier

你实际做的是这样的:

p.reload

即,重新设置p指针的内容以指向从数据库记录创建的新对象。该对象现在具有数据库中的最新数据。