Rails 5 - 我有乐队和场地模特。我有一个共同的模型,我想用于乐队和模型之间的共同信息。我似乎无法正确地建立关系。
Band.rb
class Band < ApplicationRecord
has_one :common
accepts_nested_attributes_for :common, allow_destroy: true
end
乐队架构
create_table "bands", force: :cascade do |t|
t.integer "user_id"
t.integer "plan_id"
t.string "band_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "common_id"
t.index ["common_id"], name: "index_bands_on_common_id"
end
common.rb
class Common < ApplicationRecord
belongs_to :band
end
常见架构。注意 - 与band关联没有关键。我很确定我有错。
create_table "commons", force: :cascade do |t|
t.integer "user_id"
t.integer "plan_id"
t.string "name"
t.string "address1"
t.string "address2"
t.string "city"
t.string "state"
t.string "zip"
t.string "website"
t.string "phone1"
t.string "phone1_note"
t.string "phone2"
t.string "phone2_note"
t.string "short_description"
t.text "long_description"
t.integer "main_photo_id"
t.boolean "payment_current"
t.decimal "lat"
t.decimal "lon"
t.text "admin_notes"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
我认为common_id会出现在乐队模型中,但显然我错了。
我在普通模型中没有任何外键。
如何设置模型以便我可以:
乐队 - 普通
地点 - 共同
如果我将band_id的外键放在普通模型中,当我尝试与场地进行相同的关联时会发生什么。我是否在常见模型中添加了venue_id?
答案 0 :(得分:1)
是的,您需要在公共表中添加venue_id和band_id。公共实体将具有多个belongs_to(即belongs_to:Band&amp; belongs_to:venue)
级联将从Band和Venue方面完成,因为belongs_to存在于Common实体中,并且它是many_to_one / one_to_one关系。
答案 1 :(得分:1)
所有我能看到的是,你需要一个多对多的关系,因为一个乐队可以在任意数量的场地播放,场地可以容纳任意数量的乐队,所以像
class Band < ApplicationRecord
has_many :common - make sure you handle the plural
has_many :venues, through: :common
end
class Venue < ApplicationRecord
has_many :common - make sure you handle the plural
has_many :bands, through: :common
end
class Common < ApplicationRecord
belongs_to :band
belongs_to :venue
end
是的,你需要在普通模型中使用band_id和venue_id,我会说你甚至可以将你的共同模型命名为Event,因为它更像是一个真实世界的实体。
答案 2 :(得分:1)
You should probably use a polymorphic association.
So, Common
(bad name, IMO) might look like:
# == Schema Information
#
# Table name: commons
#
# id :integer not null, primary key
# commonable_id :integer
# commonable_type :string
# ... other stuff ...
# created_at :datetime not null
# updated_at :datetime not null
#
class Common < ApplicationRecord
belongs_to :commonable, polymorphic: true
... other stuff ...
end
Notice that you'll have commonable_type
and commonable_id
, which is what allows for the polymorphism.
Then, Band
might look like:
class Band < ApplicationRecord
has_one :common, as: :commonable
... other stuff ...
end
Similarly, Venue
might look like:
class Venue < ApplicationRecord
has_one :common, as: :commonable
... other stuff ...
end
Which will let you do:
@venue.common
@band.common
BTW, Common
seems like a mash up of at least a couple of candidate classes, namely PhysicalAddress
and PhoneNumber
.
So, you might have something like:
# == Schema Information
#
# Table name: phone_numbers
#
# id :integer not null, primary key
# phoneable_id :integer
# phoneable_type :string
# number :string
# note :string
# created_at :datetime not null
# updated_at :datetime not null
#
class PhoneNumber < ApplicationRecord
belongs_to :phoneable, polymorphic: true
end
And
# == Schema Information
#
# Table name: physical_addresses
#
# id :integer not null, primary key
# physical_addressable_id :integer
# physical_addressable_type :string
# address1 :string
# address2 :string
# city :string
# state :string
# zip :string
# created_at :datetime not null
# updated_at :datetime not null
#
class PhysicalAddress < ApplicationRecord
belongs_to :physical_addressable, polymorphic: true
end
And then do:
class Band < ApplicationRecord
has_one :common, as: :commonable
has_one :physical_address, as: :physical_addressable
has_one :phone1, as: :phoneable, class_name: 'PhoneNumber'
has_one :phone2, as: :phoneable, class_name: 'PhoneNumber'
end
You'll need that class_name
since rails won't be able to infer the class name (PhoneNumber
) from the association name (phone1
and phone2
).