I have two models
class User
has_many :disputes
end
class Dispute
belongs_to :user
end
So Dispute has :user_id, but my problem is that a Dispute has 2 sides - the claimant and the indicted, both of which are users.
I tried to solve this problem by creating two columns: :claimant_id and :indicted_id, and passing arguments like #dispute.claimant_id = current_user.id, but after that I can't use a relationship tricks like #dispute.user.name or #user.disputes with my :claimant_id and :indicted_id.
Is there any way to set up two :user_id (like a claimant and an indicted) in one model and still maintain the relationships between Dispute and User models?
You can go the route of having :claimant_id and :indicted_id on your users table, but in your class def you need
class Dispute < ActiveRecord::Base
belongs_to :claimant, class_name: 'User', :foreign_key => :claimant_id
belongs_to :indicted, class_name: 'User', :foreign_key => :indicted_id
end
Reference: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-belongs_to
I think this is a duplicate of Ruby on Rails Double Association
For your case use class_name as the second parameter to your belongs_to function and a hash with foreign_key and the id column name (as pointed out by #devkaoru), like so:
class Dispute < ActiveRecord::Base
belongs_to :claimant, class_name: 'User', :foreign_key => :claimant_id
belongs_to :indicted, class_name: 'User', :foreign_key => :indicted_id
end
I think that should do it up right.
Disclaimer: This is an untested solution
Related
I'm having a trouble with grasping a proper relationship between two Rails/ActiveRecord classes.
I have a User, which can both create a Slip and simultaneously be an addressee of another slip. Each user can create any number of slips but only one user as the addressee of a given slip.
From the db perspective I have two integer (key) columns for 'user_id' (author) and 'addressee' in the slips table and no reference on the users table.
This is my current approach which is not working at all:
class User < ApplicationRecord
has_many :slips
belongs_to :slips, :foreign_key => 'addressee'
end
class Slip < ApplicationRecord
belongs_to :user
has_one :addressee, :through => :user
end
Please direct me to the proper way of binding these objects.
Thanks and have a nice day!
It should look something like this (the second one could just be called 'slip' but I've called it 'addressor_slip' to avoid confusion):
class User < ApplicationRecord
has_many :slips
has_one :addressor_slip, :class_name=> 'Slip', :foreign_key => 'addressee'
end
class Slip < ApplicationRecord
belongs_to :user
belongs_to :addressee, :class_name=> 'User', :foreign_key => 'addressee'
end
You could also create an association from User to User through :addressor_slip
Look at many to many relationships here: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
You're probably looking for has_and_belongs_to_many.
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
I have these model definitions:
class Property < ActiveRecord::Base
belongs_to :user
has_many :users_favourites_properties, class_name: 'UsersFavouritesProperties', dependent: :destroy, :foreign_key => :property_id
has_many :favourites, :class_name => "User", through: :users_favourites_properties
end
class User < ActiveRecord::Base
has_many :properties
has_many :users_favourites_properties, class_name: 'UsersFavouritesProperties', dependent: :destroy, :foreign_key => :user_id
has_many :favourites, class_name: "Property", through: :users_favourites_properties
end
class UsersFavouritesProperties < ActiveRecord::Base
self.table_name = "favourites"
belongs_to :favourites, class_name: 'User', :foreign_key => :user_id, :primary_key => :id
belongs_to :favourites, class_name: 'Property', :foreign_key => :property_id, :primary_key => :id, counter_cache: :users_count
end
When I execute:
current_user.favourites << property
The UsersFavouritesProperties object created has the same user_id and property_id because the user_id is beign setted with the property_id.
Do you know what is happening?
You seem to misunderstand what the association name is for.
Each association method call (like has_many) adds certain methods to a model that allow for easy lookup for associated objects.
The name of association means (in scope of a model) "what is it for me". A symbol you specify first is an association name, and it is used (among other things) as a name of a method that you will use to access that association.
By defining an association named favourites once, you've defined the methods for UsersFavouritesProperties. The second time you define an association with the same name, some of the first one is redefined and crazy things can happen.
So, following that "what is it for me" principle, you can figure that a User associated with a certain UsersFavouritesProperty is UsersFavouritesProperty's user, and the resulting association, that you have:
belongs_to :favourites, class_name: 'User', :foreign_key => :user_id, :primary_key => :id
should be more like simple:
belongs_to :user
The rest is not even needed, as it follows the Rails' convention: class name and foreign key can be derived from association name in standard ways (capitalize for class name, add _id for foreign key), primary key is default.
I strongly recommend you read the Rails Style Guide and let ActiveRecord guess the most you can provide.
These lines
belongs_to :favourites, ...
belongs_to :favourites, ...
Should be
belongs_to :user, ...
belongs_to :property, ...
You can't use two keys for belongs_to
I have a Friends model with user_id and friend_id...both are id's back to specific users.
What I'd like to able to do is something like this:
#relationship = Friend.find_by_user_id(current_user.id)
#relationship.friend.username
Where I can basically pull the user through the friend_id column in the same way I can do #relationship.user.username.
How would I setup my associations to pull that off?
Isn't this just a many-to-many situation.
I think there is a perfect solution in Many-to-many relationship with the same model in rails?
Hope this help!
Use class_name if your column doesn't reflect the convention expected:
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, class_name: 'User'
end
Note that I modified the model name to Friendship to better reflect the use of this model. Also, you can make it easier for yourself if you revise your User model to look like this:
class User < ActiveRecord::Base
has_many :friendships
has_many :friends, :through => :friendships
has_many :friendships_of, :class_name => 'Friendship', :foreign_key => :friend_id
has_many :friends_of, :through => :friendships_of, :source => :user
end
Now to see all the user's friends:
current_user.friends.map(&:username)
And to see who has 'friended' the user:
current_user.friends_of.map(&:username)
I'm trying to represent a relationship between users in my application where a user can have many followers and can follow other users.
I would like to have something like user.followers() and user.followed_by()
Could you please tell me in details how to represent this using ActiveRecord?
Thanks.
You need two models, a Person and a Followings
rails generate model Person name:string
rails generate model Followings person_id:integer follower_id:integer blocked:boolean
and the following code in the models
class Person < ActiveRecord::Base
has_many :followers, :class_name => 'Followings', :foreign_key => 'person_id'
has_many :following, :class_name => 'Followings', :foreign_key => 'follower_id'
end
and corresponding in the Followings class you write
class Followings < ActiveRecord::Base
belongs_to :person
belongs_to :follower, :class_name => 'Person'
end
You could make the names clearer to your liking (i especially don't like the Followings-name), but this should get you started.
The twitter follower model differs from the friendship model in that you do not need permission from the person to follow them. Here I set up a lazy loading where the relationship is not fully defined in the person object.
/app/models/person.rb
def followers
Followership.where(:leader_id=>self.id).not_blocked
end
def following
Followership.where(:follower_id=>:self.id).not_blocked
end
has_many :followers, :class_name=>'Followership'
has_many :followed_by, :class_name=>'Followership'
/app/models/followership.rb
belongs_to :leader, :class_name=>'Person'
belongs_to :follower, :class_name=>'Person'
#leader_id integer
#follower_id integer
#blocked boolean
scope :not_blocked, :conditions => ['blocked = ?', false]