Which Association Should I Use? - ruby-on-rails

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/

Related

Ruby on Rails has_many :through in a polymorphic association

I have searched and searched and found only partial solutions to my current question.
The thing is, I'd like to know if it is possible to use has_many :through along with a polymorphic association in Ruby on Rails.
I have a system where students can create travel plans (that can belong to many students) and refund claims (that can belong to only one student) for their projects. In this system, both admin users and students are able to comment on the plans and claims.
My associations are:
class Student < ActiveRecord::Base
has_and_belongs_to_many :travel_plans
has_many :refund_claims
has_many :comments, through: :travel_plans
has_many :comments, through: :refund_claims
end
class AdminUser < ActiveRecord::Base
has_many :comments
end
class TravelPlan < ActiveRecord::Base
has_and_belongs_to_many :students
has_many :comments, as: :commentable
end
class RefundClaim < ActiveRecord::Base
belongs_to :student
has_many :comments, as: :commentable
end
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
end
My questions are:
Is it correct to associate comments twice in the Student model?
I don't want the AdminUsers to have travel plans and refund claims, how can I identify their comments as being made on a travel plan or on a refund claim?
Would there be a better approach?
Thanks a lot in advance for everyone!
Cheers,
You probably want to add an polymorphic author attribute to the Comment model. Than you just need has_many :comments, as: :author to the Student and AdminUser model.
If this is a new application and you are starting on the green field you might want to rethink your models a bit and add a Role and a User model. Student would than be a role of user as would AdminUser be.
Is it correct to associate comments twice in the Student model?
No, not really. If you have duplicate association name, you can only use one of them. If you want to use both, you have to name them differently.

How make categories relationships with several model?

I have next models: Articles, Announcements, Catalogs and Media.
For item of every model I need to create a subcategory and a category. I will plan to create a relationship table with two columns: parend_id and child_id, and a column for every model with category_id.
How many relationship models I should create?
One for all?
Or one relationship model for every model?
No need to create a relationship model instead just use belongs_to relationship
because you said following i guess belongs_to relations should do it
For item of every model I need create subcategory and category.
So just add subcategory_id and category_id in your tables: Articles, Announcements, Catalogs and Media and establish has_many belongs_to relationship
EDIT But if you insist for relationship model then I would suggest to use one relationship model for every model.
Last EDIT: I really think you should use belongs_to, has_many relation
Class Article < ActiveRecord::Base
belongs_to :category
belongs_to :subcategory
end
class Category < ActiveRecord::Base
has_many :articles
# the same relation(has_many) will be for Announcements, Catalogs and Media
has_many :subcategories
end
class Subcategory < ActiveRecord::Base
has_many :articles
belongs_to :category
end
In this way you can get all articles using category.subcategories.articles
If the category has only one Subcategory then change the relation between them to has_one and your syntax will become category.subcategory.articles
I would personally use a has_many :through relationship with a polymorphic association in a single join table:
#app/models/article.rb
Class Article < ActiveRecord::Base
has_many :categorizable_categories
has_many :categories, through: :categorizable_categories
end
class Article < ActiveRecord::Base
has_many :tags, as: :taggable,dependent: :destroy
has_many :categories, through: :tags
end
class Category < ActiveRecord::Base
has_many :tags, dependent: :destroy
has_many :articles, through: :tags, source: :taggable, source_type: 'Article'
end
class Tag < ActiveRecord::Base
belongs_to :taggable, polymorphic: true
belongs_to :category
end
This will allow you to call the categories for each model with the likes of #article.categories
To achieve the parent & child categories, I'd recommend using something like the Ancestry gem - you'd set up an ancestry column in your join table - basically allowing you to create relations between a model's categories directly

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

How to create multiple relations between the same models

I have a User model
class User < ActiveRecord::Base
has_many :projects
end
and I have a Project model
class Project < ActiveRecord::Base
belongs_to :user
end
Obviously right now each project is owned by a user and there can only be one user per project. I now want to make my models represent another relation between the two models. I want a User to be able to follow multiple Projects, no matter who owns the Project. I know that I am going to have to use a has_many :through and create a join, but I cant wrap my head around how to change the model to keep my current relationship and add the new relationship.
Well, in that case, in your show/index action display all the projects (Project.all) in your project table. This way all users have access to all the projects. Now, in your edit action, use user.projects.all to display projects of that particular user. That should solve your problem, I don't see the need of any further association here.
Update:
This should suffice:
class Project < ActiveRecord::Base
belongs_to :user
class User < ActiveRecord::Base
has_many :projects_followed, :through => :projects
user has_many :projects_owned, :through => :projects
If you don't wish to create two more relations, create just one:class ProjectsSubscribed
belongs_to :project with three fields: project_id, is_owned, is_followed
Try following relation.
class User < ActiveRecord::Base
has_many :followers
has_many :projects, :through => :followers
end
class Follower < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
class Project < ActiveRecord::Base
has_many :followers
has_many :users, :through => :followers
end
Note it:
You can use 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.
Hope it is helpful.

rails has_many through with independent through table

I have a User model, Person model and Company model.
a User has many companies through Person and vice versa.
But i would like to be able to populate People and Companies that are not tied to Users that can be tied later.
class User < ActiveRecord::Base
attr_accessible :name
has_many :people
has_many :companies, :through => :people
end
class Person < ActiveRecord::Base
attr_accessible :user_id, :company_id
belongs_to :users
belongs_to :companies
end
class Company < ActiveRecord::Base
attr_accessible :name
has_many :people
has_many :users, :through => :person
end
now in the console i want to be doing the following
User.find(1).companies
then it should find me the companies in which user(1) is a person of interest.
Have I got this wrong, is there a small change that I should be making.
Your Person model can't directly "belong_to" more than one, your belongs_to :users and belongs_to :companies associations won't work that way. Companies-to-people need to be connected through another join table that describes the relationship between them, for example Employment which points to one instance of each model:
class Person < ActiveRecord::Base
has_many :employments
has_many :companies, :through => :employments
end
class Employment < ActiveRecord::Base
belongs_to :person
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :employments
has_many :people, :through => :employments
end
You can then use the :through option to associate the many companies/people on the other side of that employment relationship in the middle.
Similarly, if a Person can be owned by more than one User then you will need a join model between those two entities as well.
Just as a followup, in a has_many :through relationship, there is nothing that says you cannot use your join table (in your case, Person) independently. By nature of the relationship, you are joining through a completely separate ActiveRecord model, which is what most notably distinguishes it from the has_and_belongs_to_many relationship.
As Brad pointed out in his comment, you need to pluralize 'person' to 'people' in your relationship. Other than that, it looks like you set it up correctly. Exposing :user_id and :company_id with attr_accessible will enable you to mass-assign these values later from a postback, but often times you want to shy away from doing so with role-based associations, as you may not want to leave them exposed to potential HTTP Post attacks.
Remember, in your controller you can always do something like this with or without attr_accessible:
#person = Person.new
#person.user = User.find(...)
#person.company = Company.find(...)
#person.save
Hope that helps.

Resources