I have the follow two models:
User
Mentions (user_id, mentioned_by)
#mention.user gives me the creator, but I need the user who was mention. I would like to do: #mention.mentioner which gets the user_id with mentioned_by
How do I set that relationship in the models? I tried:
User.rb:
has_many :mentions
Mention.rb
belongs_to :user
belongs_to :user, :as => "mentioner", :foreign_key => "mentioned_by"
But that errors. Ideas? Thanks
In mention.rb, try this:
belongs_to :user
belongs_to :mentioner, :class_name => "User", :foreign_key => "mentioned_by"
Related
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.e. Post model has a column poster_id and for posters I'm actually using User model. Obviously this is a User has_many Posts relationship, but how to I specify that poster_id is actually an id to User model?
Use foreign_key option:
has_many :posts, :foreign_key => :poster_id
For Post model it will be
belongs_to :user, :foreign_key => :poster_id
or
belongs_to :poster, :class_name => 'User'
So lets I have a Transactions model.
Transactions.rb has:
belongs_to :buyer, :class_name => "User"
belongs_to :seller, :class_name => "User"
The user logged in, is accessed with current_user.
How can I do something like current_user.transactions? (which won't work as transactions doesn't have a user_id column) Or something like current_user.transactions.buyer?
Thanks!
(also the user model has_many :transactions)
All associations in Rails are one-way.
So for each belongs_to, you need to add a has_many or has_one on the other side.
I'd suggest you want something like this;
class User
has_many :transactions_as_buyer,
:class_name => "Transaction",
:foreign_key => :buyer_id
has_many :transactions_as_seller,
:class_name => "Transaction",
:foreign_key => :seller_id
end
Now you can say;
current_user.transactions_as_seller.map(&:buyer)
to get an array of buyers.
Of course, depending on your app you may have a better name than "transactions_as_buyer/seller"
I have multiple models with created_by and modified_by columns. This is what I have for a Deal Model.
class Deal
has_one :user , :foreign_key => 'created_by'
has_one :user , :foreign_key => 'modified_by'
end
class User
belongs_to :created_by , :class_name => 'Deal' , :foreign_key => 'created_by'
belongs_to :modified_by , :class_name => 'Deal' , :foreign_key => 'modified_by'
end
When I create the deal, looks like it is saving correctly. But in the show view when I try to get #deal.created_by.email I get an "undefined method email" error. Can some tell me how to get this working please?
Also since I have multiple models with these two columns, there can be many belongs_to in User model. Is there an elegant solution for this case?
First thing you have to add is the specification of accessible attributes.
In User you would have to add:
attr_accessible :email, :created_by, :modified_by
In Deal:
attr_accessible :created_by, :modified_by
But you should also change the direction of your relation. The foreign_key is always on the belongs_to side.
This is what worked for me:
class Deal < ActiveRecord::Base
belongs_to :created_by, :class_name => "User", :foreign_key => "created_by"
belongs_to :modified_by, :class_name => "User", :foreign_key =>"modified_by"
attr_accessible :created_by, :modified_by, :name
end
class User < ActiveRecord::Base
has_many :created_deals, :class_name => "Deal", :foreign_key => "created_by"
has_many :modified_deals, :class_name => "Deal", :foreign_key => "modified_by"
attr_accessible :created_deals, :modified_deals, :name
end
If you have more models, which look similiar you could probably use polymorphic associations: http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
First of all, from my experience it is generally a bad idea to have associations using the foreign key as name. Especially when writing fixtures it seems rails will get confused between setting the actual value "created_by" or the model in the created_by association. In my models I generally use these associations for the cases you describe:
belongs_to :creator, :class_name => "User", :foreign_key => 'created_by'
belongs_to :modifier, :class_name => "User", :foreign_key => 'modified_by'
You can use association names like 'creating_user' instead if you prefer. If you really want created_by as association name you should have created_by_id or something similar as foreign key, just as long as its not equal to the association name.
Then I am a bit confused by your pasted code. Your choice "Deal has_one User" and "User belongs_to Deal" means that the users table will have the columns created_by and modified_by (foreign keys) containing Deal Ids, basically meaning that users get created by a single deal? However it seems like deals should get created by users and not the other way round. Your example of deal.created_by.email can not work at all with your associations, since deal would not have an association called "created_by", only "user", of which you have two associations with the same name in a single model which can not work at all in the first place.
Fixing your associations similar to what Patrick suggested:
class Deal < ActiveRecord::Base
belongs_to :creator, :class_name => "User", :foreign_key => "created_by"
belongs_to :modifier, :class_name => "User", :foreign_key =>"modified_by"
end
class User < ActiveRecord::Base
has_many :created_deals, :class_name => "Deal", :foreign_key => "created_by"
has_many :modified_deals, :class_name => "Deal", :foreign_key => "modified_by"
end
I'm struggling with a has_many association. I have a diary application. The model players are as follows:
User
UserFriend
UserFoodProfile
I want to be able to get at all the foods that a user's friends have eaten. So, I want to be able to get: current_user.friends.profiles
I've setup the associations properly so far so that I'm able to access current_user.friends, but now I want to be able to get all the friend's entries as well over the last 30 days.
Here are my models
class User < ActiveRecord::Base
cattr_reader :per_page
##per_page = 20
has_many :user_food_profiles
has_many :preferred_profiles
has_many :food_profiles, :through => :user_food_profiles
has_many :weight_entries
has_one :notification
has_many :user_friends
has_many :friendships, :class_name => "UserFriend", :foreign_key => "friend_id"
has_many :friends, :through => :user_friends
class UserFriend < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => "User", :foreign_key => "friend_id"
class UserFoodProfile < ActiveRecord::Base
belongs_to :user
belongs_to :food_profile
belongs_to :post
The UserFriend model is setup the following way:
id
user_id
friend_id
friend_name
I want to connect to user_food_profiles from friend so that I can get a user's friend's current user_food_profiles as "entries" but everything I've tried hasn't worked. How would I setup this association?
Tried to do:
UserFriend: has_many :user_food_profiles, :as => 'entries'
UserFoodProfile: belongs_to :friend, :foreign_key => 'friend_id'
Any ideas on how to make this work? Tempted to create a custom finder_sql but I'm sure this can work with associations.
Isn't a "friend" just another user that's in the database?
Let your UserFriend be a many_to_many relationship (either with "has_and_belongs_to_many" or "has_many :through"): each user can have several users as friends.
You can then link those user_ids (which could be in the many_to_many table called 'friend_id' if you like) to their foodprofile without a problem, since it is using the same link as user.foodprofile .
This is the line I see being the problem:
class User < ActiveRecord::Base
# <snip/>
has_many :friendships,
:class_name => "UserFriend",
:foreign_key => "friend_id"
I'm assuming that you're using a join table here called user_friend. That would mean that the foreign key there should be "user_id".
Now, unless you're going to store extra metadata in that UserFriend model, it's not required — you can get away with a self-referential has_and_belongs_to_many relationship like so:
has_and_belongs_to_many :friends,
:class_name => "User",
:join_table => "user_friends",
:foreign_key => "user_id",
:association_foreign_key => "friend_id"
Doing this, all you have to do is user.friends.profiles quite easily.
Now, if the relationship is bi-directional it gets a bit more complex, but I feel like this should at least get you started along the way.