Reputation: 2085
I'm trying to implement sponsored photos, so I have my photos table and my sponsors table.
Sponsor will have many photos, and photos will have many sponsors.
Should I use a has_and_belongs_to_many relation in both of the models?
In that case,
1.) Should I create a join intermediate table manually or Rails will do It automatically?
2.) Should I add photo_id
to sponsors
and sponsor_id
to photos
?
Thanks guys
Upvotes: 1
Views: 423
Reputation: 76784
Sounds like you'll benefit from has_and_belongs_to_many
- if you don't want to include any specific information in the join table. I'll give you information on has_many :through
to give you an overview of both approaches
has_and_belongs_to_many
is used if you just want to associate two tables.
It's "dumb" in that it doesn't rely on primary keys
- only housing two foreign_key
columns in the data-table. It's for this reason that you cannot include any specific information in the join model:
This means that if you want to use has_and_belongs_to_many
, you'll be able to do this:
#app/models/sponsor.rb
class Sponsors < ActiveRecord::Base
has_and_belongs_to_many :photos
end
#app/models/photo.rb
class Photo < ActiveRecord::Base
has_and_belongs_to_many :sponsors
end
You'll then need to create a join table, with the name [plural_alphabetical_model]_[plural_alphabetical_model]
$ rails g migration CreatePhotosSponsors
#db/migrate/create_photos_sponsors.rb
class CreatePhotosSponsors < ActiveRecord::Migration
def self.up
create_table :photo_sponsors, :id => false do |t|
t.references :photo
t.references :sponsor
end
add_index :photos_sponsors, [:photo_id, :sponsor_id]
add_index :photos_sponsors, :sponsor_id
end
def self.down
drop_table :photos_students
end
end
An alternative to the HABTM method is the has_many :through
association. If you wanted to add specific information to your join data, you'll want to use this association. Reason being that it has a primary_key
in the data table (and so can reference individual records):
#app/models/student.rb
class Student < ActiveRecord::Base
has_many :sponsor_photos
has_many :photos, through: :sponsor_photos
end
#app/models/sponsor_photo.rb
class SponsorPhoto < ActiveRecord::Base
belongs_to :sponsor
belongs_to :photo
end
#app/models/photo.rb
class Photo < ActiveRecord::Base
has_many :sponsor_photos
has_many :sponsors, through: :sponsor_photos
end
The beauty of this association is that you can include specific information in the join model, such as the price paid, or their expiry date
Upvotes: 3
Reputation: 42919
First the habtm relation, quoting from 'rails 4 way'
7.5.1 has_and_belongs_to_many
Before proceeding with this section, I must clear my conscience by stating that has_and_belongs_to_many is practically obsolete in the minds of many Rails developers, including the authors of this book. Use has_many :through instead and your life should be a lot easier.
generate a joining model SponsorPhoto for example, with photo_id
and sponsor_id
class Sponsor < ActiveRecord::Base
has_many :photos, through: :sponsor_photos
end
class Photo < ActiveRecord::Base
has many :sponsors, through :sponsor_photos
end
class SponsorPhoto < ActiveRecord::Base
belongs_to :sponsors
belongs_to :photos
end
Upvotes: 2
Reputation: 5112
in this case,The has_many :through Association will work great
sponsor.rb
has_many :sponsor_photos, :dependent => :destroy
has_many :photos, :through => :sponsor_photos
photo.rb
has_many :sponsor_photos, :dependent => :destroy
has_many :sponsors, :through => :sponsor_photos
sponsor_photo.rb
##holding only sponsor_id and photo_id
belongs_to :sponsor
belongs_to :photo
###########so now you can use################
@sponsor=Sponsor.first
##get all photos of a sponsor
@sponsor.photos
@photo=Photo.first
##get all sponsors from a photo
@photo.sponsors
HOPE THIS HELPS...
Upvotes: 2