Rails 5 - I have band and venue models. I have a common model that I want to use for info that is common between the band and model. I can't seem to get the relationships right.
Band.rb
class Band < ApplicationRecord
has_one :common
accepts_nested_attributes_for :common, allow_destroy: true
end
band schema
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
common Schema. Note - no key for the association with band. I'm pretty sure that I have that wrong.
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
I thought that the common_id would go in the bands model but apparently I'm wrong.
I don't have any foreign keys in the common model.
How do I set up my models so that I can have :
Band -- Common
Venue -- Common
If I put a foreign key of band_id in the common model, what happens when I try to do the same association with venues. Do I add a venue_id to the common model?
Yes, you need to add venue_id and band_id in the common table. Common entity will have multiple belongs_to (ie belongs_to: Band & belongs_to: venue)
cascading will be done from the Band and Venue side as belongs_to exist in the Common entity and it's many_to_one/one_to_one relationship.
All i can see is that you need a many to many relation as a band can play at any number of venues and venue can host any number of bands so something like
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
and yes you need to have band_id and venue_id in common model and I would say you can even name your common model as Event as its more of a real world entity.
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
).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.