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

我试图通过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! 确实回归真实。 puts part.title确实返回了我想要的值。

如果我打电话

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

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

这是因为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