rake / rails .save!没有更新数据库

时间:2012-01-02 06:59:21

标签: ruby-on-rails rake

我正在尝试通过rake任务保存对数据库的更改。

在我的佣金任务中,我做了类似的事情:

namespace :parts do
  desc "Update Parts table, swap names in title"
  task :swap => :environment do
    Part.swap
  end
end

在我的Part课程中我做了

def self.swap
  Part.all.each do |part|
    if (part.title =~ REGEX) == 0
      part.title.gsub! REGEX, '\2 \1'
      puts part.title
      part.save!
    end
  end
end

但是,这并不能保存部分。 save!确实返回true。 puts part.title确实返回了我想要的值。

如果我打电话

Part.update(part.id, title: part.title)

数据库正确更新。为什么是这样?我在循环中做错了吗? 我正在使用Rails 3.1.3,Rake 0.9.2.2和MySQL2 0.3.7

1 个答案:

答案 0 :(得分:17)

这是因为ActiveRecord检测到属性被更改的方式是通过setter。因此,如果对属性使用gsub!,则ActiveRecord不知道它需要更新数据库。

您可能必须这样做:

part.title = part.title.gsub REGEX, '\2 \1'

从评论

更新

另外,如果您尝试将标题分配给另一个变量,然后再为gsub!它不会起作用,因为它是同一个对象(来自我的项目的代码,变量名称不同)。

ruby-1.9.3-p0 :020 > t = p.name
 => "test" 
ruby-1.9.3-p0 :023 > t.object_id
 => 70197586207500 
ruby-1.9.3-p0 :024 > p.name.object_id
 => 70197586207500 
ruby-1.9.3-p0 :025 > t.gsub! /test/, 'not a test'
 => "not a test" 
ruby-1.9.3-p0 :037 > p.name = t
 => "not a test" 
ruby-1.9.3-p0 :026 > p.save
   (37.9ms)  BEGIN
** NO CHANGES HERE **
   (23.9ms)  COMMIT
 => true 

在修改之前你必须.dup字符串。

ruby-1.9.3-p0 :043 > t = p.name.dup
 => "test" 
ruby-1.9.3-p0 :044 > t.gsub! /test/, 'not a test'
 => "not a test" 
ruby-1.9.3-p0 :045 > p.name = t
 => "not a test" 
ruby-1.9.3-p0 :046 > p.save
   (21.5ms)  BEGIN
   (20.8ms)  UPDATE "projects" SET "name" = 'not a test', "updated_at" = '2012-01-02 07:17:22.892032' WHERE "projects"."id" = 108
   (21.5ms)  COMMIT
 => true