Rails 3: How should I set up this has_many relationship? - ruby-on-rails

Trying to figure out the best way to set up my models. Here's what I've going going on...
Models: Dog, Video, Photo, User
class Dog < ActiveRecord::Base
has_many :videos
has_many :photos
belongs_to :user
end
class Video < ActiveRecord::Base
has_many :dogs
belongs_to :user
end
class Photo < ActiveRecord::Base
has_many :dogs
belongs_to :user
end
class User < ActiveRecord::Base
has_many :dogs
has_many :videos
has_many :photo
end
Should I do has_many :through and a polymorphic?
In my previous iteration of this, I had DogPhoto and DogVideo models, but seems like I could have a single DogItem model that's polymorphic.
Thoughts?

Yes, a polymorphic association would apply here, and it would be a good practice. However, i think that you should have a new model like DogMedia or so, that would be the polymorphic association.
This way a user has a dog and a dog has many DogMedias. A DogMedia is a polymorphic association that can either be a photo, video or anything else you like :)
You could use has many through to get dogmedia for a user's dog directly yes. Something like :
User has many dog_medias through dog (plain language)
or just traverse it through dog :
user.dog.dog_media
If you do the latter, you can even create a Media instead of DogMedia class, create a delegate and execute the neat :
user.dog_media
directly ( The law of demeter : http://en.wikipedia.org/wiki/Law_of_Demeter )

Related

Has many through doesn't persist

I have a question about the Has Many Through relationship.
I have 3 models : Artist, Skill, and Mastery
skill.rb
class Skill < ActiveRecord::Base
has_many :masteries
has_many :artists, through: :masteries
end
mastery.rb
class Mastery < ActiveRecord::Base
belongs_to :artist
belongs_to :skill
end
artist.rb
class Artist < ActiveRecord::Base
has_many :masteries
has_many :skills, through: :masteries
end
Everytime I try to attach a skill to an Artist, using artist.skills << skill, a mastery is created, but the artist_id is nil. Same thing the other way around. skill.artists << artist gives me a Mastery with a nil skill_id.
Does this mean that I have to execute both every time ? Or did I miss something ?
So basically, here's why it failed : it appears that you cannot set it in rails console under certain unclear circumstances. However, if you got the same model setup as me, using the model.attributes << attribute syntax will work just fine. Obviously, if you need to create a fake relationship in your rails console, all you have to do is create a new Mastery, and set its creator_id and skill_id accordingly, then save it.

ActiveModel: proper relation for a different type of the resource

I'm trying to determine the proper ActiveModel realtionship for the following situation: there are pictures and there are different categories of them: foo, bar, baz and qux. A User can set one like and several comments per the picture.
I started with a Catregory and a Foo models. The simpliest approach could be - creatation of likes and comments properties for each of the Foo, Bar, Baz and Qux models. But I feel it's a silly approach... There might be a better one.
What is the best kind of realationship can be chosen for such a case?
Here's what I imagined reading your question (I've decided that your pictures were created by users, because your model looks a lot like a social network):
class User < ActiveRecord::Base
has_many :pictures
has_many :comments
has_one :like
end
class Picture < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :likes
has_many :comments
end
class Category < ActiveRecord::Base
has_many :pictures
end
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :picture
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :picture
end
Categories are rows of the categories Table. Instead of making one Model per category, you should have one model Category for all of them, with attributes like name, color or whatever you want.

Rails: How can I achieve this relationship model?

I'm looking to create a simple relationship model with the following:
I have 2 main items. Product / WishList
The relationship between them is pretty straight forward a WishList has_many :products and a Product belongs_to_many :wishlists
I understand that there isn't a belongs_to_many association and as simple as this may be I can't seem to wrap my head around the right relationship model.
If someone could suggest a nice way to achieve this it would be much appreciated.
Thanks.
You have a choice between a has_many :through and a has_and_belong_to_many relation.
Pick the first one if you need to attach other attributes to the model that will be the bridge (for instance a position, if you want to order your wishlist), or the second one otherwise (more about that here)
So it could look like so
class Product < ActiveRecord::Base
has_many :items
has_many :wishlists, through: :items
end
class Item < ActiveRecord::Base
belongs_to :product
belongs_to :wishlist
end
class Wishlist < ActiveRecord::Base
has_many :items
has_many :products, through: :items
end

Creating a many-to-many relation in Rails

So I'm Rails n00b and I want to create a "favorites" relationship such that a User can have many favorite Item. I'm not entirely sure how to do this, this is how I'm going to try but I'm not sure if this is a good practice at all:
class User < ActiveRecord::Base
has_many :favorites
//other code
end
class Favorite < ActiveRecord::Base
belong_to :user
has_one :item
end
class Item < ActiveRecord::Base
belongs_to :item
end
Is this a good way to do it? Should I be using has_and_belongs_to_many ?
I'm specially concerned in the following scenario: Say a user has 100 favorite items.
When I do a User.find(id) will I also be retrieving the 100 favorites and the 100 Items?
In case it's important: ruby version 1.9.3, rails version 3.2.11
Can you try has_many => :through?
class User < ActiveRecord::Base
has_many :favorites
has_many :items, :through => :favorites
//other code
end
In your case has_many :through is definitely the way to go. I would recommend reading: http://guides.rubyonrails.org/association_basics.html
Of particular interest with regard to your question:
2.8 Choosing Between has_many :through and has_and_belongs_to_many
Rails offers two different ways to declare a many-to-many relationship between models. The simpler way is to use has_and_belongs_to_many, which allows you to make the association directly:
class Assembly < ActiveRecord::Base
has_and_belongs_to_many :parts
end
class Part < ActiveRecord::Base
has_and_belongs_to_many :assemblies
end
The second way to declare a many-to-many relationship is to use has_many :through. This makes the association indirectly, through a join model:
class Assembly < ActiveRecord::Base
has_many :manifests
has_many :parts, :through => :manifests
end
class Manifest < ActiveRecord::Base
belongs_to :assembly
belongs_to :part
end
class Part < ActiveRecord::Base
has_many :manifests
has_many :assemblies, :through => :manifests
end
The simplest rule of thumb is that you should set up a has_many :through relationship if you need to work with the relationship model as an independent entity. If you don’t need to do anything with the relationship model, it may be simpler to set up a has_and_belongs_to_many relationship (though you’ll need to remember to create the joining table in the database).
You should use has_many :through if you need validations, callbacks, or extra attributes on the join model.
It is better than using has_and_belongs_to_many.
When I do a User.find(id) will I also be retrieving the 100 favorites
and the 100 Items?
No. You'll just get the user object.
Update:
Calling User.include(:favourites, :items).find(id) will get you joined tables in case you want to make many calls to items table from user object.

How to improve this association in Rails

hey guys
I want to build a database and some association between them, below are some descriptions
Drummer and Video are many-to-many association, because, sometimes, more than one drummer will appear on one video clip
Cymbal and Video are only many-to-many association, same reason
Event and Video are one-to-many, because it makes sense that one video only represent only one Event
so for the first two my solution is using two has-and-belongs-to-many association sign to the both side, and for the 3rd one i use simple one-to-many:
here's the code:
class Drummer < ActiveRecord::Base
has_and_belongs_to_many :videos
end
class Cymbal < ActiveRecord::Base
has_and_belongs_to_many :videos
end
class Video < ActiveRecord::Base
has_and_belongs_to_many :drummers
has_and_belongs_to_many :cymbals
belongs_to :event
end
class Event < ActiveRecord::Base
has_many :videos
end
But I think the polymorphic is the better solutions, video should apply two many other models, but I don't know how to make a many-to-many polymorphic association, i already ask a question about this
What about this:
class Interpreter < ActiveRecord::Base
belongs_to :video
end
class Drummer < Interpreter
end
class Cymbal < Interpreter
end
class Video < ActiveRecord::Base
has_and_belongs_to_many :interpreters
has_and_belongs_to_many :drummers
has_and_belongs_to_many :cymbals
belongs_to :event
end
class Event < ActiveRecord::Base
has_many :videos
end
Video.first.interpreters should return all drumers and cymbals, while Video.first.drummers and Video.first.cymbals will return only corresponding models
Cymbals and Drummers will share same database table interpreters
Have you watched this http://railscasts.com/episodes/154-polymorphic-association

Resources