Ruby:试图" Update_all"但得到" NameError:未初始化的常量"

时间:2014-10-13 11:58:12

标签: ruby-on-rails ruby

这是我第一次尝试编写ruby迁移脚本(我想更新特定行的col值)。

我有一个名为“events”的表,其中包含cols“e_id”和“e_text_en”。我想更新ID为6的行的“e_text_en”值。 在SQL中它将是

update events set e_text_en = 'blabla' where e_id = 6;

我的红宝石方法:(20141013130000_update_broken_event_texts.rb)

class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
  def Events.up
    Events.where('e_id', 6).update_all(e_text_en: "blablabla")
  end
end

但是这给了我错误'NameError:uninitialized constant'

rake aborted!
NameError: uninitialized constant UpdateBrokenTextsEventInEvent::Events
/var/.../20141013130000_update_broken_event_texts.rb:2:in `<class:UpdateBrokenTextsEventInEvent>'
/var/.../20141013130000_update_broken_event_texts.rb:1:in `<top (required)>'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:718:in `load_migration'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:714:in `migration'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:708:in `disable_ddl_transaction'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:1012:in `use_transaction?'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:922:in `rescue in block in migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:919:in `block in migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:916:in `each'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:916:in `migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:764:in `up'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:742:in `migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/railties/databases.rake:42:in `block (2 levels) in <top (required)>'
Tasks: TOP => db:migrate

在我搜索解决方案的过程中,我发现有人建议以单数形式调用表,但即使我尝试Event而不是Events,我也会得到同样的错误。

任何人都可以帮我纠正我的红宝石吗?

使用的版本:

$ rails -v
Rails 4.0.1
$ gem -v
1.8.23.2
$ ruby -v
ruby 1.9.3p545 (2014-02-24) [i686-linux] Brightbox

编辑:Addional infos 我们的Schema是通过sql-File创建的。我们很快就开始使用迁移,这是第一次更新。表格更改的前两次迁移。我们还没有任何'app / model'文件,因为其他迁移没有任何工作,例如:

class AddDeliveriesToEmailQueue < ActiveRecord::Migration
  def change
    add_column :email_queue, :deliveries, :int, :null => false, :default => 0, :after => :error
  end
end

3 个答案:

答案 0 :(得分:3)

首先,您的迁移类名称必须与文件名匹配(rails将加载迁移文件,然后假设它创建了一个相应名称的类)。假设您没有更改文件名,则表示您需要

class UpdateBrokenEventTexts < ActiveRecord::Migration
  ...
end

由于您说您没有模型类,因此您必须使用原始SQL,例如

class UpdateBrokenEventTexts < ActiveRecord::Migration
  def change
    execute "UPDATE events SET e_text_en = 'blablabla'"
  end
end

这与使用ActiveRecord::Base.connection.execute几乎相同,但在输入上节省了一些,并确保Rails明白你正在做出不可逆转的改变。

答案 1 :(得分:2)

当您创建迁移然后希望重命名它时,这是一个常见问题。迁移中的类名应与文件名相同。您已迁移了类UpdateBrokenTextsEventInEvent和文件名20141013130000_update_broken_event_texts.rb,但类名应为UpdateBrokenEventTexts

答案 2 :(得分:1)

创建Event模型:

$ rails g model Event

假设您现在有一个模型类Event(在 app / models / event.rb 中),请更改这些行:

class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
  def Events.up
    Events.where('e_id', 6).update_all(e_text_en: "blablabla")
  end
end

为:

class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
  def self.up
    Event.where('e_id', 6).update_all(e_text_en: "blablabla")
  end
end

另外,我建议您在rake任务中移动此类操作,而不是在迁移文件中移动它们:

namespace :events do
  desc "Update e_text_en field with blablabla"
  task :update_e_text_en => :environment do
    Event.where('e_id', 6).update_all(e_text_en: "blablabla")
  end
end

然后从您的终端:

$ rake events:update_e_text_en

更新:暂时不打算购买模特课程?不用担心,您仍然可以使用SQL查询更新列:

class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
  def self.up
    ActiveRecord::Base.connection.execute("UPDATE events SET e_text_en = 'blablabla'")
  end
end

请注意,这些操作是不可逆转的(因为您不知道您要更新的列中的先前数据是什么),这就是为什么他们不应该在迁移文件。你可能会更好地完成rake任务或其他事情。