Mic*_*lle 3 sql activerecord ruby-on-rails database-migration ruby-on-rails-4
我坚持写这个迁移.
目前我有一个建筑物表.它将建筑物的城市列为一列.
(城市列中有重复的城市名称.)
create_table "building", force: true do |t|
t.string "name"
t.string "city"
t.datetime "created_at"
t.datetime "updated_at"
end
Run Code Online (Sandbox Code Playgroud)
我现在已经创建了一个城市模型has_many :buildings.
现在的建筑物belongs_to :city.
我已city_id为belongs_to协会的建筑物添加了一个新列.
create_table "city", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "city", ["name"], name: "index_cities_on_name", unique: true
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写将执行以下操作的迁移:
1.将"城市"列从建筑物表格复制到城市表格中的"名称"列.
2.合并城市名称列中的所有重复城市
3.将建筑物表格中的"city_id"列与正确的城市相匹配
但我完全被卡住了...我已经在ActiveRecords文档中翻了一个小时了,我现在还不太清楚要做什么.任何帮助将非常感谢!谢谢!
注意:对于我来说,我反对编写 SQL 查询来更新迁移中表中的数据。我更喜欢为此使用 rake 任务。您可以将代码放置在您想要的位置下方。
第一。cities使用表编写(并运行)迁移
第二。在 rake 任务或迁移中执行此代码
Building.all.each do |building|
city = City.find_or_create(name: building.city) # http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-find_or_create_by
building.city_id = city.id
building.save!
end
Run Code Online (Sandbox Code Playgroud)
第三。编写删除列的迁移buildings.city
一些注意事项:
find_each http://api.rubyonrails.org/classes/ActiveRecord/Batches.html#method-i-find_eachsave!来确保我会注意到某些建筑物无法保存 - 我可以手动重新检查此项目belongs_to :city在第二步之前添加对 Building 的引用,因为我不确定 Rails 将尝试查找哪个列buildings.city(旧城市名称)或对象city(它将为零,因为city_id此时为零)我不会在ActiveRecord中进行数据迁移.在迁移中直接引用ActiveRecord模型类存在向前兼容性问题.作为一般规则,我试着避免id.所以我会回到SQL.
不确定你正在使用什么数据库,但这样的东西应该适用于MySQL:
execute("INSERT INTO cities(name, created_at, updated_at) SELECT DISTINCT city, NOW(), NOW() FROM buildings;")
execute("UPDATE buildings SET buildings.city_id = (SELECT city_id FROM cities where cities.name = buildings.name);")
Run Code Online (Sandbox Code Playgroud)
第一个语句初始化cities表,没有重复项,而第二个语句设置建筑物上的city_id列.
类似的语句(可能略有不同的语法)适用于其他数据库.
| 归档时间: |
|
| 查看次数: |
3437 次 |
| 最近记录: |