这是我第一次尝试编写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
答案 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任务或其他事情。