Ruby on rails 耙子/轨道。保存!不更新数据库

Ruby on rails 耙子/轨道。保存!不更新数据库,ruby-on-rails,rake,Ruby On Rails,Rake,我试图通过rake任务保存对数据库的更改 在我的rake任务中,我会执行以下操作: namespace :parts do desc "Update Parts table, swap names in title" task :swap => :environment do Part.swap end end 在我的班里,我喜欢 def self.swap Part.all.each do |part| if (part.title =~ REGEX)

我试图通过rake任务保存对数据库的更改

在我的rake任务中,我会执行以下操作:

namespace :parts do
  desc "Update Parts table, swap names in title"
  task :swap => :environment do
    Part.swap
  end
end
在我的班里,我喜欢

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
但是,这不会保存零件。
保存返回true。
放置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'
根据评论更新 另外,如果您尝试将title分配给另一个变量,然后是gsub!它也不会工作,因为它是同一个对象(来自项目的代码,变量名不同)

在修改字符串之前,必须
.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 

我试过做
text.gsub然后设置
part.title=text
,但这不起作用。如果这样做,则必须先对变量进行
.dup
操作。您可能需要将
part.title=~REGEX
测试移到数据库中,做
Model.all.each
通常都是一个坏主意。你所说的:将其移动到数据库中是什么意思?我想用一个字段来更新每个记录,该字段与我在该条件下的regex criteriaQuery(
Part.where(…)
)相匹配,并让数据库处理该部分,将整个表拉入Ruby land并测试那里的记录。而且,根据数据库的不同,您可以在数据库中完成整个替换,而无需将任何数据拉入Ruby。这取决于您使用的datZbase和正则表达式的外观。
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