使用 mongodb/mongoid 更改运行时模型 [英] Runtime changing model with mongodb/mongoid
问题描述
我必须在 mongoid 模型中添加几个字段,我知道 MongoDB 没有迁移,但如果我继续不删除数据库,使 rails 完全重新生成"数据库,它不会显示或使用新领域!
I've to add several fields in a mongoid model, I know there is not migration with MongoDB but if I go on without dropping the DB, making rails to "regenerate" the DB entirely, it doesn't display or use the new fields at all !
去这里最好的方式是什么?有没有比 drop/reopen mongodb 更软的东西?
What's the best way to go here ? Is there something softer than drop/reopen mongodb ?
提前致谢卢卡
推荐答案
一般来说,应该可以在运行时用新字段更新旧文档.在 MongoDB 中不需要迁移.
In general it should be possible to update old documents with the new fields at runtime. There is no need for migrations in MongoDB.
您可能想要编写 rake 任务来使用新字段和默认值更新旧文档.
You maybe want to write rake tasks to update your old documents with the new fields and default values.
您可以通过检查那些默认为 nil 值的新字段来找到这些文档.
You could find out these documents by checking those new fields which have per default a nil value.
更新
简单风格:
如果您使用默认值定义了一个新字段,那么只要您设置了一个新值,就应该始终使用该值:
If you define a new field with a default value, this value should always be used as long as you set a new one:
app/models/my_model.rb
app/models/my_model.rb
class MyModel
include Mongoid::Document
field :name, type: String
field :data, type: String
# NEW FIELD
field :note, type: String, default: "no note given so far!"
end
如果你查询你的数据库,你应该得到在你的扩展之前没有这个字段的文档的默认值:
If you query your database you should get your default value for documents which haven't this field before your extension:
(导轨控制台)
MyModel.first
#=> #<MyModel …other fields…, note: "no note given so far!">
我在 Ruby 1.9.2 上使用带有当前 mongoid 的新 rails 堆栈对此进行了测试 - 也应该与其他堆栈一起使用.
I tested this with a fresh rails stack with a current mongoid on Ruby 1.9.2 - should work with other stacks, too.
更复杂/复杂的风格:
如果您没有设置默认值,则此新字段将为 nil.
If you didn't set a default value, you'll get nil for this new field.
app/models/my_model.rb
app/models/my_model.rb
class MyModel
include Mongoid::Document
field :name, type: String
field :data, type: String
# NEW FIELD
field :note, type: String
end
(导轨控制台)
MyModel.first
#=> #<MyModel …other fields…, note: nil>
然后你可以像这个例子一样设置一个 rake 任务和迁移文件:
Then you could set up a rake task and migration file like in this example:
lib/tasks/my_model_migration.rake:
lib/tasks/my_model_migration.rake:
namespace :mymodel do
desc "MyModel migration task"
task :migrate => :environment do
require "./db/migrate.rb"
end
end
db/migrate.rb:
db/migrate.rb:
olds = MyModel.where(note: nil)
# Enumerator of documents without a valid :note field (= nil)
olds.each do |doc|
doc.note = "(migration) no note given yet"
# or whatever your desired default value should be
doc.save! rescue puts "Could not modify doc #{doc.id}/#{doc.name}"
# the rescue is only a failsafe statement if something goes wrong
end
使用 rake mymodel:migrate
运行此迁移.
这只是一个起点,您可以将其扩展到完整的 mongoid 迁移引擎.
This is only a starting point and you can extend this to a full mongoid migration engine.
任务:migrate =>:environment do ...
是必需的,否则 rake 不会加载模型.
The task :migrate => :environment do …
is necessary, otherwise rake won't load models.
这篇关于使用 mongodb/mongoid 更改运行时模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!