我有两个模型:
class RecordProduct < ApplicationRecord
end
class ShopiTagProduct < ApplicationRecord
end
我想在模型之间建立多对多关系。我执行以下命令:
rails g migration CreateJoinTableRecordProductsShopyTagProducts record_products:references:index shopi_tag_products:references:index
此命令创建此迁移:
class CreateJoinTableRecordProductsShopyTagProducts < ActiveRecord::Migration[5.2]
def change
create_join_table :record_products, :shopi_tag_products do |t|
t.references :record_products, foreign_key: true, index: {name: :productId}
t.references :shopi_tag_products, foreign_key: true, index: {name: :tagId}
end
end
end
在执行rake db:migrate时抛出错误:表'name_new_table'上的'name_index_tooooo_long'太长;限制为64个字符。
因此,我将迁移类更改为:
class CreateJoinTableRecordProductsShopyTagProducts < ActiveRecord::Migration[5.2]
def change
create_join_table :record_products, :shopi_tag_products do |t|
t.references :record_products, foreign_key: true, index: {name: :productId}
t.references :shopi_tag_products, foreign_key: true, index: {name: :tagId}
end
end
end
当我执行rake db:migrate时,它会创建表,但要重复列:
record_product_id
shopi_tag_product_id
record_products_id
shopi_tag_products_id
我有两个问题。
首先:重复这些列吗?正确生成列的正确方法是什么?
第二:我应该在模型中手动添加关系(has_and_belongs_to_many)还是自动添加这些关系?
答案 0 :(得分:1)
我不确定是否可以根据您的情况自动将has_many
添加到模型中,在这种情况下我会手动添加。
运行rails g migration CreateJoinTableRecordProductsShopyTagProducts record_products:references:index shopi_tag_products:references:index
会产生以下迁移:
class CreateJoinTableRecordProductsShopyTagProducts < ActiveRecord::Migration[5.2]
def change
create_join_table :record_products, :shopi_tag_products do |t|
t.references :record_products, foreign_key: true
t.references :shopi_tag_products, foreign_key: true
end
end
end
t.references
在这里是多余的,因为您已经在使用create_join_table
rails g migration CreateJoinTableRecordProductsShopyTagProducts record_products shopi_tag_products
将完成工作。
它将生成这样的文件:
class CreateJoinTableRecordProductsShopyTagProducts < ActiveRecord::Migration[5.2]
def change
create_join_table :record_products, :shopi_tag_products do |t|
# t.index [:record_product_id, :shopi_tag_product_id]
# t.index [:shopi_tag_product_id, :record_product_id]
end
end
end
您需要取消注释索引并为它们添加名称,以解决索引名称过长的问题。
您可以选择以下方式:
rails g model record_products_shopi_tag_products record_product:references shopi_tag_product:references
它将生成:
class CreateRecordProductsShopiTagProducts < ActiveRecord::Migration[5.2]
def change
create_table :record_products_shopi_tag_products do |t|
t.references :record_product, foreign_key: true
t.references :shopi_tag_product, foreign_key: true
t.timestamps
end
end
end
请注意,这里使用create_table
代替create_join_table
,因此在这种情况下,您必须编写t.references
。
在此迁移中,您必须添加, index: {name: ...}
才能解决长索引问题。
我已经写过这样的模型:
rails g model RecordProduct name:string
rails g model ShopiTagProduct name:string
record_product.rb
class RecordProduct < ApplicationRecord
# has_and_belongs_to_many :shopi_tag_products
# not needed if you use has_and_belongs_to_many
has_many :record_products_shopi_tag_products, dependent: :destroy
has_many :shopi_tag_products, through: :record_products_shopi_tag_products
validates :name, presence: true
end
shopi_tag_product.rb
class ShopiTagProduct < ApplicationRecord
# has_and_belongs_to_many :record_products
# not needed if you use has_and_belongs_to_many
has_many :record_products_shopi_tag_products, dependent: :destroy
has_many :record_products, through: :record_products_shopi_tag_products
validates :name, presence: true
end
record_products_shopi_tag_product.rb(如果您使用has_and_belongs_to_many,则不需要)
class RecordProductsShopiTagProduct < ApplicationRecord
belongs_to :record_product
belongs_to :shopi_tag_product
end
seeds.rb
RecordProduct.destroy_all
ShopiTagProduct.destroy_all
r = RecordProduct.create!(name: 'foo')
s = ShopiTagProduct.create!(name: 'bar')
r.shopi_tag_products << s
r.save!
p ActiveRecord::Base.connection.execute('select * from record_products_shopi_tag_products')
$ rake db:seed
[{"record_product_id"=>4, "shopi_tag_product_id"=>4}]
我强烈建议使用has_many through
而不是has_and_belongs_to_many
,因为has_and_belongs_to_many
不支持dependent: destroy
(habtm relationship does not support :dependent option)