Multiple relationships to the same models - ruby-on-rails

I'm having trouble figuring out the best way to do this. I have a User model and a Tournament model and I set up a has_many :through relation between these two models called 'followed_tournaments' so that users can follow a tournament. As such, I already have a has_many :tournaments in the User model and a has_many :users in the Tournament model so that a tournament has many followers and a user can follow many tournaments.
I'd like to set up another habtm or has_many :through relationship so that a User can be considered a "contributor" to a Tournament -- a completely separate relationship than what I already set up. I'd like a tournament to have any number of contributors and the user to contribute to many tournaments.
What's the best way to go about implementing this?

Use source or class_name
class Tournament < ActiveRecord::Base
has_many :users # ... whatever
has_many :contributions
# using class_name
has_many :contributors, :through => :contributions
# using source
has_many :contributors, :through => :contributions, :source => :user
end
class Contribution < ActiveRecord::Base
belongs_to :tournament
# using class_name
belongs_to :contributor, :class_name => 'User'
# using source
belongs_to :user
end

Related

How to associate through a join table that reference the same model?

I have a model called House and I want to be able to associate houses with each other to show recommendations.
So I would expect that given a house, I should be able to ask: house.recommended_houses. A house could be recommended for more than one house.
I was thinking on having a table that would store this association (I don't know the name yet), so it would have the following columns:
recommended_house_id
recommended_for_house_id
I am failing to understand how would I hook this up with my House model. What would the associations look like, and also what name should I be using for that join model?
This should get you started:
class House < ApplicationRecord
has_and_belongs_to_many :recommendations,
class_name: "House",
foreign_key: "recommended_by_id",
association_foreign_key: "recommendation_id"
end
What you're describing is called a self-referential association.
You can set up a join table (recommendations) and the associated model:
class Recommendation < ActiveRecord::Base
belongs_to :house
belongs_to :recommended_house, :class_name => 'House'
end
and then use has_many, :through relationships within the House model to set up the relationships you're looking for.
class House < ActiveRecord::Base
has_many :recommendations
has_many :recommended_houses, :through => :recommendations
has_many :inverse_recommendations, :class_name => "Recommendation", :foreign_key => "recommended_house_id"
has_many :recommended_by_houses, :through => :inverse_recommendations, :source => :house
end
Now you can use both house.recommended_houses and house.recommended_by_houses.

Ruby ORM polymorphic relationships, Active Record

So I am working with the Ruby ORM and trying to understand many-to-many syntax and polymorphism.
Here are my Active Record relationships so far.
class Association < ActiveRecord::Base
belongs_to :user
belongs_to :friend, class_name: "User"
end
and
class User < ActiveRecord::Base
has_many :associations
has_many :friends, through: :associations
end
I can't seem to get a list of friends per user when those friends are associated with more than one user. In other words some users have friends and these friends may have more than one user association too.
First off, these are not polymorphic associations. One uses polymorphic associations when a model could belong to many models, like a Comment model. A user can comment on a post, on a picture, on a project, so the Comment model could belong to any of these, so there we use Polymorphic associations. Read here to know more about it.
Well, the thing that you are asking is about Inverse Friends, and here is how you can implement it.
class User < ActiveRecord::Base
has_many :associations
has_many :friends, through: :associations
has_many :inverse_associations, class_name: "Association", foreign_key: :friend_id
has_many :inverse_friends, through: :inverse_associations, source: :user
end
class Assocation < ActiveRecord::Base
belongs_to :user
belogns_to :friend, class_name: 'User'
belongs_to :inverse_friend, class_name: 'User', foreign_key: :friend_id
end

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

Rails 3 / Active Record - Association problems with additional model in assignment table

I currently have a setup that links the models User, Dealer and Role together. User and Dealer is many to many, and is working as expected with a Dealer_user assignment table.
The problem is that I want to have roles assigned to the user that are specific to the dealer also (i.e. a user could be a Sales Manager and a Parts Manager in one dealership, while being a Sales Manager and a Director in another).
In order to do this, I have a Role model (which belongs to a Role_type). Role should belong to Dealer_user, and Dealer_user has many Roles.
The intention is that I will be able to do dealer.users.where(:id => user.id).first.roles and it will return only the roles specific to that dealership.
The problem I have is that when I run the following test code: dealer.users.where(:id => user.id).first.roles.create(:role_type_id => 1 + Random.rand(4))
I get an error: Cannot modify association 'User#roles' because the source reflection class 'Role' is associated to 'DealerUser' via :has_many.
Can anyone suggest what I am doing wrong with my models (which are below)?
NOTE: The belongs_to relationship that Role has with Dealer_user is polymorphic because it could also belong to Sale_user or other association tables, which require the same functionality as Dealer.
class Dealer < ActiveRecord::Base
attr_accessible :name, :address_id
has_many :dealer_users
has_many :users, :through => :dealer_users
has_many :roles, :through => :dealer_users
end
class User < ActiveRecord::Base
attr_accessible :first_name, :last_name
has_many :dealer_users
has_many :dealers, :through => :dealer_users
has_many :roles, :through => :dealer_users
end
class DealerUser < ActiveRecord::Base
attr_accessible :dealer_id, :user_id
belongs_to :dealer
belongs_to :user
has_many :roles, :as => :role_originator
end
class Role < ActiveRecord::Base
attr_accessible :role_type_id
belongs_to :role_type
belongs_to :role_originator, :polymorphic => true
end
Edit: No luck so far - can anyone help?
I would use has_many through association with the roles table. Get rid of the dealer_user table, and add columns to the roles table dealer_id and user_id
Then your models would look something like this:
class Dealer < ActiveRecord::Base
has_many :users, :through => :roles
has_many :roles
end
class User < ActiveRecord::Base
has_many :dealers, :through => :roles
has_many :roles
end
class Role < ActiveRecord::Base
belongs_to :dealer
belongs_to :user
end
That should make it easier to do the types of queries you're trying. The rails guide has a really good overview here

Rails: Many-to-many relationships with 3 Models

I have a situation where I have Products, Suppliers, ShoppingLists and Valuations.
A shopping_list consist of many valuations each with a product, an specific supplier and a price.
My models are as follows:
class Product < ActiveRecord::Base
has_many :valuations
has_many :shopping_lists, :through => :valuations
end
class Supplier < ActiveRecord::Base
has_many :valuations
has_many :shopping_lists, :through => :valuations
end
class ShoppingList < ActiveRecord::Base
has_many :valuations
has_many :products, :through => :valuations
has_many :suppliers, :through => :valuations
end
class Valuation < ActiveRecord::Base
belongs_to :product
belongs_to :supplier
belongs_to :shopping_list
end
My routes.rb is:
map.resources :shopping_lists do |shopping_list|
shopping_list.resources :valuations
end
map.resources :product
map.resources :supplier
I wonder if this could be the best solution, anyway what I want is that the user can create as many lists as he wish, each with several valuations.
The first time a shopping list is created its also filled with one valuation at least. Then, the user can add/remove valuations to/from the shopping_list.
I would like a simple and elegant solution, without Ajax callbacks.
What is the best way to do this, from the controllers/views/routes perspectives?
Or should I completley change my schema ?
Thanks!
Just found two excelent resources from Ryan Bates:
http://asciicasts.com/episodes/196-nested-model-form-part-1
http://asciicasts.com/episodes/197-nested-model-form-part-2
Let's see if that do the job!
// UPDATE: Worked great!

Resources