Polymorphic associations and/or has_many_through - ruby-on-rails

I need to create relationships between a user, product and a photo-model. A user can add photos to a product. Therefore, a user has_many photos and a product has_many photos, but each photo belongs_to both a product and a user. How can I achieve this in Rails? As far as I understand a polymorphic association would only allow a photo to belong to a product or a user. Do I have to instead using separate has_many_through relationships for the user-photo and product-photo relationships?

You can have multiple belongs_to attributes within the same model. Essentially the Model that is marked as belongs_to will hold a foreign key to the Model that has been marked with has_many.
class MyModel < ActiveRecord::Base
belongs_to :other_model1
belongs_to :other_model2
end
If you want to use polymorphic associates as you mentioned below you could do that along these lines
class Photos < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
class Users < ActiveRecord::Base
has_many :photos, :as => :imageable
end
class Product < ActiveRecord::Base
has_many :photos, :as => :imageable
end
In this case you can create the relationship simply by adding the has_many :phots, :as => :imageable attribute without having to revisit the Photos class.

Related

Which Association Should I Use?

My app has 5 core models. I'm trying to figure out the best way to associate the models. How many tables should I build and which kind etc?
Here are the associations I would like to include and their respective models:
User
Has many boards
Has many lists
Has many cards
Has many comments
Board
Has many users
Has many lists
Has many cards
List
Belongs to board
Has many cards
Card
Belongs to board
Belongs to list
Has many comments
Comment
Belongs to card
Belongs to user
class User < ActiveRecord::Base
has_and_belongs_to_many :boards
has_many :lists, as: listable
has_many :cards, as: cardable
has_may :comments, as: commentable
end
class Board < ActiveRecord::Base
has_and_belongs_to_many :users
has_many :lists, as: listable
has_many :cards, as: cardable
end
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class List < ActiveRecord::Base
belongs_to :listable, :polymorphic => true
has_many :cards, as: cardable
end
class Card < ActiveRecord::Base
belongs_to :cardable, :polymorphic => true
has_many :comments, as:commentable
end
To establish HABTM relation you have to create a table named 'users_boards'
As Board and User are having many to many relationship, there will be a new table for it, if you want HABTM you can use it.
User(id, name, other_attributes...)
Board(id, name,...)
List(id, name, user_id(fk),...)
Card(id, name, user_id(fk), list_id(fk), board_id(fk),...)
Comment(id, comment_msg, user_id(fk), card_id(fk),...)
Board_User(board_id(fk), user_if(fk)) --- M-M relation
Few attributes might change if there is a has_many through relation.
FK-- Foreign key, you can use has_many through depending on your requirements.
Using polymorphic associations has some limitations, so please do through it then decide to use a polymorphic association
http://codeblow.com/questions/pros-and-cons-for-ruby-on-rails-polymorphic-associations/

has_many :through relationships explained

I'm new to Rails and have some doubts about the kind of relationship do I need to use. Here is the case.
I have two models Offer and User, a user could belong to to many offers and offers can have many user. Also the users create the offers.
I think I have to use a has_many :through ralationship. For example I've created another model "Applicant". Applicant belongs_to user and belongs_to offer. But how is the relationship from the user and offer model? For example:
User Model
has_many :offer, :through => :applicant
Offer Model
has_many :user, :through => :applicant
My doubt is because I already have this two relationship
User Model
has_many :offers, :dependent => :destroy
Offer Model
belongs_to :user
After solve this, I guest I have to save the record in the applicant model from the applicanst_controller, right?
Thanks in advance
What you have described is a many-to-many relationship using a join table. You're actually pretty close but you just need to remove the has_many :offers, :dependent => :destroy from your user model and the blongs_to :user in your offer model. It should look something like this:
class User < ActiveRecord::Base
has_many :offers, :through => :applicants
end
class Applicant < ActiveRecord::Base
belongs_to :users
belongs_to :offers
end
class Offer < ActiveRecord::Base
has_many :users, :through => :applicants
end
You don't have to worry about the dependent destroy part as associations are automatically removed as the corresponding objects are removed. With a many to many association it doesn't really matter how you go about building the relationship. Either of the following will work:
#user.offers << #offer
#offers.users << #user
If you don't need to store any information specific to your applicant join table (e.g., time stamps, descriptions) you might instead want to look at a has_and_belongs_to_many relationship. Check out choosing between has_many_through and has_and_belongs_to_many for reference.
Edit
Heres the code for a HABTM relationship:
class User < ActiveRecord::Base
has_and_belongs_to_many :offers
end
class Offer < ActiveRecord::Base
has_and_belongs_to_many :users
end

Using Rails, not sure if I should use belongs_to or not

Very new to Rails... I'm building out functionality that lets people compare photos, and I can't decide exactly how I should structure it. Ideally what I'd like is to have a "comparisons" table which keeps a record of the IDs of the photos compared as well as the user that compared them, but I'm not quite sure whether this warrants use of the "belongs_to" function or not. If so, how do I specify that each comparison belongs to TWO separate photos?
The following has_many, :through => Model structure will let you have additonal properties on the join table, e.g. 'comparing_user_id'.
class Photo < ActiveRecord::Base
has_many :appearances
has_many :users, :through => :appearances
end
class Appearance < ActiveRecord::Base
belongs_to :photo
belongs_to :user
end
class User < ActiveRecord::Base
has_many :appearances
has_many :photos, :through => :appearances
end

Active record: Querying nested many to many models

I have a Store that has many Catalogs and in turn each catalog has many Products.
The Product and Catalog shares many to many relationship.
One product can belong to many catalogs and vice-verse.
So, my model definition goes like this:
class Store < ActiveRecord::Base
has_many :store_catalogs
has_many :catalogs, :through => :store_catalogs
end
class StoreCatalog < ActiveRecord::Base
belongs_to :store
belongs_to :catalog
end
class Catalog < ActiveRecord::Base
has_many :store_catalogs
has_many :stores, :through => :store_catalogs
has_and_belongs_to_many :product_set, :class_name => "Product"
end
class Product < ActiveRecord::Base
has_and_belongs_to_many :catalogs
end
Now, I would like to access all the products that belongs to a store.
How do I link those together so that I get that? please suggest.
I am trying out various combinations from the rails console to pull the data, not sure if the console itself limits the relation based querying by any chance(though i would like to believe it doesn't).
I think this should solve your problem
class Store < ActiveRecord::Base
has_many :catalogs
has_many :products, :through => :catalogs
end
class Catalog < ActiveRecord::Base
belongs_to :store
has_and_belongs_to_many :products
end
class Product < ActiveRecord::Base
has_and_belongs_to_many :catalogs
end
And then you just need a table in your database called catalogs_products with catalog_id and product_id to link the has_and_belongs_to_many association.
Then in order to get all the products from a store just do
Store.find(id).products

Rails Polymorphism 'backwards'

Say I'm writing a blog app with models for posts, pages and photos. I've got a category model, that may be linked to any of these models. So, a category may contain various kinds of items. Every item only has ONE category.
I could implement this using a generic tagging pattern with a join table, but I want to make sure every subject can have only category.
What would be the best way to implement this in Rails?
Okay, I think I've got it:
class Post < ActiveRecord::Base
has_one :categorization, :as => :categorizable
has_one :category, :through => :categorization
end
class Category < ActiveRecord::Base
has_many :categorizations, :dependent => :destroy
end
class Categorization < ActiveRecord::Base
belongs_to :category
belongs_to :categorizable, :polymorphic => true
end
Now various models can have a category, but each instance can have only one category… I guess.

Resources