我有一堆character
模型已经在数据库中。每个character has_one :iconfolio
。我迁移数据库以将icon_url
和post_url
属性添加到iconfolio
模型,因此我试图使用rails控制台更新数据库中的所有iconfolio
模型。为现有数据库记录运行before_create的轨道
然而,对于每个现有的记录设置正确的属性是不平凡的,所以我也加入了before_create
到iconfolio
这将正确设置新characters
和iconfolios
的icon_url
和post_url
属性。但是,我如何强制执行此代码已经在数据库中的characters
和iconfolios
?
在控制台中我已经试过:
Character.all.find_each do |char|
char.create_iconfolio
end
,但它不更新数据库。看来要删除的记录:
(0.4ms) COMMIT
Iconfolio Load (0.2ms) SELECT "iconfolios".* FROM "iconfolios" WHERE "iconfolios"."character_id" = $1 LIMIT 1 [["character_id", 46]]
(0.1ms) BEGIN
SQL (0.2ms) DELETE FROM "iconfolios" WHERE "iconfolios"."id" = $1 [["id", 46]]
我也试过:
Character.all.find_each do |char|
Iconfolio.create(character_id: char.id)
end
这产生:
(0.2ms) BEGIN
Character Load (0.6ms) SELECT "characters".* FROM "characters" WHERE "characters"."id" = $1 LIMIT 1 [["id", 2]]
SQL (0.5ms) INSERT INTO "iconfolios" ("character_id", "created_at", "updated_at", "person_url", "followed_url", "icon_url", "post_url") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["character_id", 2], ["created_at", "2017-08-02 13:27:35.897842"], ["updated_at", "2017-08-02 13:27:35.897842"], ["person_url", "/assets/icon1.png"], ["followed_url", "/assets/icon2.png"], ["icon_url", "/assets/icon7.png"], ["post_url", "/assets/icon8.png"]]
(0.4ms) COMMIT
这看起来很有希望,但数据库还没有更新。 (我试过重新启动服务器等)。
我在做什么错?
iconfolio.rb
belongs_to :character
validates :character_id, presence: true
before_create do
if self.character.type.is_a? User
self.icon_url = '/assets/icon5.png'
self.post_url = '/assets/icon6.png'
else
self.icon_url = '/assets/icon7.png'
self.post_url = '/assets/icon8.png'
end
end
ActiveRecord的'has_one'的问题是,当你做'character.iconfolio'时,它会触发一个带有'LIMIT 1'子句的SQL查询。所以你的字符记录实际上可以有许多'iconfolios',但是你定义的关系('has_one')使得Rails只选择其中的一个。如果你做'Iconfolio.where(character_id:2)',你会看到几条记录(如果你没有删除你的例子中插入的数据),但是'Character.find(2).iconfolio'只会返回1条记录。总之,'has_one'不能确保你只有(最多)1条记录相关联,它只需抓住DB返回的第一条记录。 – MrYoshiji
似乎你连续没有犯过什么错误。其中一个由@MrYoshiji描述,另一个 - 由MZaragoza在答案中。 –
如果您想要更新所有现有记录以遵循新的数据库结构,则不应该使用Rails控制台来执行此操作(如果有一天您忘记在'db:migrate'之后执行此操作,或者如果稍后创建的迁移使用这个数据做额外的逻辑?你不能停止迁移,在Rails控制台中运行代码,然后重做迁移)。如果您的数据库结构发生更改并且当前数据需要更新,则必须在同一个迁移文件中执行此操作。 – MrYoshiji