假设我有一只模型狗,每只狗只有2只猫“敌人”,enemy1
和enemy2
,我如何编写迁移文件,以便我可以调用dog.enemy1
检索第一个敌人并dog.enemy2
检索第二个敌人?
我试过这个:
create_table :dog do |t|
t.string :name
t.timestamps null: false
end
add_index :dog, :name
add_foreign_key :dogs, :cats, column: :enemy1_id
add_foreign_key :dogs, :cats, column: :enemy2_id
end
我也尝试使用t.references
方法,但无法使其正常工作。几个小时以来一直在研究这个问题。它在开发中工作正常但在Heroku Postgres上没有。
我得到的错误是
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:column "enemy1_id" referenced in foreign key constraint does not exist.
有什么想法吗?
答案 0 :(得分:3)
迁移:
Service
狗模型:
create_table :dog do |t|
t.string :name
t.integer :enemy1_id
t.integer :enemy2_id
t.timestamps null: false
end
答案 1 :(得分:0)
我刚刚解决了它,第一个答案进来后2秒...... 最后。
class CreateDogs < ActiveRecord::Migration
def change
create_table :dogs do |t|
t.string :name
t.references :enemy1, index: true
t.references :enemy2, index: true
t.timestamps null: false
end
add_index :dogs, :name
add_foreign_key :dogs, :cats, column: :enemy1_id
add_foreign_key :dogs, :cats, column: :enemy2_id
end
答案 2 :(得分:0)
rails中没有'has_two'关联。所以你应该与has_many协会达成和解。
class Dog < ActiveRecord::Base
has_many :cats, limit: 2
scope :enemy1, Proc.new { |object| object.cats.first }
scope :enemy2, Proc.new { |object| object.cats.last }
end
class Cat < ActiveRecord::Base
belongs_to :dog
end
现在,创建cat的迁移应该有
t.references :dog
您的狗模型中不需要外国字段。这应该可以解决你的问题。
答案 3 :(得分:0)
Rails Way不应该在迁移中这样做。我认为,迁移是一种定义数据将要存在的结构的工具。
Rails Way建议您在Cat的Dog类上建立一个has_many
关联
class Dog < ApplicationRecord
# ... other code ...
has_many :enemies, class_name: Cat
# ... other code ...
end
您还必须在Cat中定义归属关联
class Cat < ApplicationRecord
# ... other code ...
belongs_to :dog
# ... other code ...
end
请注意,cats
表应定义为对dogs
表的引用。因此,您对cats表的迁移应显示为
class CreateCats < ActiveRecord::Migration[5.x]
create_table :cats do |t|
# ... other code ...
t.references :dog
# ... other code ...
end
end
通过这些设置,您应该在Dog类中定义enemy_one
和enemy_two
class Dog < ApplicationRecord
# ... other code ...
def enemy_one
enemies.first
end
def enemy_two
enemies.second
end
# ... other code ...
end
要使事情变得更加严格,您可以决定添加一个验证(创建时),该验证检查每只狗是否只有两个猫被创建为敌人。此外,当狗达到敌人的限制时,您可以隐藏创建按钮(或常规访问权限)。这是我的决定权。
p.s:所有这些限制也可以在数据库层中完成。但是应用程序层在这里将所有内容抽象出来。