Rails has many and belongs to one - ruby-on-rails

I have a User model which has many projects and a Project model which can have many users, but also belongs to a single user (ie the user who created this project). It must belong to a User. It also allows a list of users to be associated with it, think collaboration.
With this in mind, my models look like this:
class User < ActiveRecord::Base
has_many :assigned_projects
has_many :projects, :through => :assigned_projects
end
class Project < ActiveRecord::Base
belongs_to :user
has_many :assigned_projects
has_many :users, :through => :assigned_projects
end
class AssignedProject < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
Now, when I want to create a new project through a User, this is how I would do it:
user = User.create(:name => 'injekt')
user.projects.create(:name => 'project one')
Now, I know that projects is provided through an AssignedProject join model, which is why project.user will return nil. What I'm struggling to get my head around is the best way to assign the project creator (which by the way doesn't need to be user, it could be creator or something else descriptive, as long as it is of type User).
The idea then is to create a method to return projects_created from a User which will select only projects created by this user. Where user.projects will of course return ALL projects a user is associated with.
Assuming this kind of association is fairly common, what's the best way to achieve what I want? Any direction is greatly appreciated.

Add a creator_id column to your projects table for the creator relationship, and then add the associations to the models:
class User < ActiveRecord::Base
has_many :assigned_projects
has_many :projects, :through => :assigned_projects
has_many :created_projects, :class_name => "Project", :foreign_key => :creator_id
end
class Project < ActiveRecord::Base
belongs_to :user
has_many :assigned_projects
has_many :users, :through => :assigned_projects
belongs_to :creator, :class_name => "User", :foreign_key => :creator_id
end
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many

I wanted to add little improvement to design. We don't actually need intermediate model because it does not contain any extra column other than reference_ids hence HABTM association is best suited over here.
class User < ActiveRecord::Base
has_and_belongs_to_many :projects, :join_table => :assigned_projects
has_many :created_projects, :class_name => "Project", :foreign_key => :creator_id
end
class Project < ActiveRecord::Base
has_and_belongs_to_many :users, :join_table => :assigned_projects
belongs_to :creator, :class_name => "User", :foreign_key => :creator_id
end

Related

Ruby on Rails how to distinguish multiple relationships between same models

So I have the following models
User, Course, Order, Line_item
User (seller) has_many :courses (as the instructor, uploading them)
On the other hand...
User (buyer): has_many :orders
Order: has many :line_items
line_item: belongs_to :course
So I want a list of all courses purchased by a buyer, can I at this point use #user.courses to do so? How can I distinguish between buyer.courses and seller.courses?
Any help is appreciated. Thanks!
You need to use self-referential association for this.
#cousre.rb
Class Course < ActiveRecord::Base
belongs_to :sellar, :class_name => 'User', :foreign_key => 'sellar_id'
end
#order.rb
Class Order < ActiveRecord::Base
belongs_to :buyer, :class_name => 'User', :foreign_key => 'buyer_id'
end

How to fix my model associations

I'm struggling to understand model associations, and how to have them set up correctly. I'm hoping someone here knows how, and that I can kind of explain what I want to accomplish.
I have a user model that looks like this:
has_many :companies
has_many :contacts
belongs_to :company
a user can create a company, and belongs to a company. It can also import contacts from email providers (such as Google). Thus it can have many contacts.
Then we have the company model:
belongs_to :admin, class_name: 'User', foreign_key: 'user_id'
has_many :users
has_many :categories
has_many :contacts
a company belongs to an admin, which is the user that creates it. It can also however have several users that belongs to the company (they get invited by the admin). It also has categories, that the admin can create - which belongs to the company. It can also have contacts, which will be put the content of the categories (the categories are groups for contacts).
Then we have the categories. They are created by the admin (user) for the company.
belongs_to :company
has_many :contacts
The categories store all the contacts.
Then lastly the contacts:
belongs_to :user
belongs_to :company
The contacts belongs to the user (the user that imports them) however they are also a part of the assets to the company (as all the actions the user makes), they don't necessarily need to be a part of a category, however they can - and can also be a part of several categories.
I'm certain there are some flaws, and I want to fix my associations now so I don't end up building a lot of code on the wrong structure.
Hope somebody can help me out, on how to clean up this relatively large app, for a rookie
I'd change a few things:
In the company model, change has_many :contacts to has_many :contacts, through: :categories. It seems like categories only serve to group contacts together. And so therefore:
In the contact model, add belongs_to :category and remove belongs_to :company
Users and contacts do not have to be associated if a user wants to import contacts. I would either remove this association entirely if you don't need it or have a the same has_many :categories and has_many :contacts, through: :categories relationship as the companies. Of course, remove belongs_to :user in the contacts.
You might look into polymorphism. I'm doing something like this although I stripped out and and renamed a few things to more closely match your question. This is untested but might help illustrate a different approach
class User < ActiveRecord::Base
has_many :business_users
has_many :businesses, :through => business_users
has_many :contacts, :through => :contact_users
...
end
class Contact < ActiveRecord::Base
belongs_to :user
belongs_to :company
has_many :categorizations, :as => :categorizeable
has_many :categories, -> { order(created_at: :desc) }, :through => :categorizations
...
end
class Company < ActiveRecord::Base
belongs_to :admin, :class_name => :User, :foreign_key => "user_id"
has_many :company_users
has_many :users, :through => :company_users
has_many :categorizations, :as => :categorizeable
has_many :categories, -> { order(created_at: :desc) }, :through => :categorizations
...
end
class Category < ActiveRecord::Base
belongs_to :categorizeable, polymorphic: true
has_many :categorizations
has_many :companies, :through => :categorizations, :source => :categorized, :source_type => 'User'
has_many :contacts, :through => :categorizations, :source => :categorized, :source_type => 'Contact'
...
end

Association rules in rails

I have a User model, a Listing model and an Order model. A user can either place an order or publish a listing which others can place an order for. Thus, a User can be customer as well as supplier.
My Order model has listing_id, from_id and to_id.
My question is, how can I set up associations between these models ? I read the rails guide on associations but the example there were dealing with separate customer and supplier models.
class User < ActiveRecord::Base
has_many :listings, :foreign_key => :supplier_id, :inverse_of => :supplier
has_many :orders, :foreign_key => :customer_id, :inverse_of => :customer
end
class Listing < ActiveRecord::Base
belongs_to :supplier, :class_name => 'User'
belongs_to :order
end
class Order < ActiveRecord::Base
belongs_to :customer, :class_name => 'User'
has_many :listings
end

Rails: has_many through association - did I get this right?

I building a photo sharing web application using Rails 3.1. I just want to verify that I got the associations right.
Some context: A User has many Share. A Share has one User (i.e the "sharer"), one Photoand many Receiver. A Receiveris a arbitrary User.
The reason why I'm using a through association is simply because I want to store additional data for each receiver of the shared photo.
class Photo < ActiveRecord::Base
has_many :shares
end
class Receiver < ActiveRecord::Base
belongs_to :share
belongs_to :user
end
class Share < ActiveRecord::Base
belongs_to :photo
belongs_to :user
has_many :receivers
has_many :users, :through => :receivers
end
class User < ActiveRecord::Base
has_many :receivers
has_many :shares, :through => :receivers
end
Retreiving a User shared photos could then be performed using the shares class method?
User.first.shares
# => [<#Share:0x000>, ...]
Retreiving a User received shares could then be performed using the receivers class method?
User.first.receivers
# => [<#Receiver:0x000>, ...]
Did I get this right?
I did something similar a while ago, I didn't test this code, so play around with it and see if it actually is what you need, it may point you in the right direction though.
If yours work I don't see the point of changing it, this code is a bit more complex but you dont have a Receiver model, everything goes through the Share model.
class User < ActiveRecord::Base
has_many :shares_links, :class_name => "Share", :foreign_key => :sharing_id, :dependent => :destroy
has_many :receiver_links, :class_name => "Share", :foreign_key => :shared_to_id, :dependent => :destroy
has_many :shares, :through => :shares_links
has_many :receivers, :through => :receiver_links
end
class Share < ActiveRecord::Base
belongs_to :sharing, :validate => true, :class_name => "User", :foreign_key => :sharing_id
belongs_to :shared_to, :validate => true, :class_name => "User", :foreign_key => :shared_to_id
has_one :photo
end
class Photo < ActiveRecord::Base
belongs_to :photo
end
User.first.shares
User.first.receivers
User.first.receivers.first.photo

Rails: Multiple "has_many through" for the two same models?

Can't wrap my head around this...
class User < ActiveRecord::Base
has_many :fantasies, :through => :fantasizings
has_many :fantasizings, :dependent => :destroy
end
class Fantasy < ActiveRecord::Base
has_many :users, :through => :fantasizings
has_many :fantasizings, :dependent => :destroy
end
class Fantasizing < ActiveRecord::Base
belongs_to :user
belongs_to :fantasy
end
... which works fine for my primary relationship, in that a User can have many Fantasies, and that a Fantasy can belong to many Users.
However, I need to add another relationship for liking (as in, a User "likes" a Fantasy rather than "has" it... think of Facebook and how you can "like" a wall-post, even though it doesn't "belong" to you... in fact, the Facebook example is almost exactly what I'm aiming for).
I gathered that I should make another association, but I'm kinda confused as to how I might use it, or if this is even the right approach. I started by adding the following:
class Fantasy < ActiveRecord::Base
...
has_many :users, :through => :approvals
has_many :approvals, :dependent => :destroy
end
class User < ActiveRecord::Base
...
has_many :fantasies, :through => :approvals
has_many :approvals, :dependent => :destroy
end
class Approval < ActiveRecord::Base
belongs_to :user
belongs_to :fantasy
end
... but how do I create the association through Approval rather than through Fantasizing?
If someone could set me straight on this, I'd be much obliged!
Keep your first set of code, then in your User Model add:
has_many :approved_fantasies, :through => :fantasizings, :source => :fantasy, :conditions => "fantasizings.is_approved = 1"
In your Fantasizing table, add an is_approved boolean field.

Resources