rails4 scoped has_many association - ruby-on-rails

In my product_users joint table there is a role column besides the product_id and user_id.
I have this association in my product model.
has_many :owners, -> { where(product_users: { role: "owner" }) },
through: :product_users, source: :user
All of the products will have only one "owner" and the rest will be "member".
What association should I use to to get the owner of the product instead of an owners collection. So in the views I wanna use product.owner. I couldn't figure out how to use either has_one or belongs_to.
I could use this instance method, but I guess it would be better to define a fine association somehow.
def owner
owners.first
end

I guess the easiest way to do that, would be to add a column "owner_id" to the product. Then, on the product:
belongs_to :owner
and on the user something like this
has_many :owned_products, class_name: "Product", foreign_key: "owner_id"
The "class_name" tells the association that you will be looking for a "Product" and the foreign_key, will define what column will be used to compare with users id.
If you don't want to add additional column, then you can name association to "has_many :owner", but that's wrong on so many levels, that you shouldn't do it. So in the case you don't want to add additional column, stick to the method.
def owner
owners.first
end

Related

Get association from custom name

My Seminar model has a column named teacher_id. That part of the relationship is working. I can call seminar.teacher to retrieve the User who teaches that seminar.
I'd like to be able to invert that query. In other words, I need to call teacher.own_seminars to get a collection of all the seminars where that User is listed as the teacher_id. I know that I could call Seminar.where(:teacher => teacher), but that's clunky. And I think that the performance is probably worse that way.
Note: Some of the Users are students who are linked to Seminar through the seminar_user join table, but I don't think that affects this question.
This is the model setup that isn't quite working yet
class User < ApplicationRecord
has_many :own_seminars, :class_name => "Seminar", foreign_key: 'own_seminar_ids'
end
class Seminar < ApplicationRecord
belongs_to :teacher, class_name: "User", foreign_key: 'teacher_id'
end
Cheers!
In foreign_key option, you specify the column which is, well, the foreign key.
The way has_many works, is it tries to guess, which one of the fields in the referenced entity corresponds to the primary key of this entity. By default, it's user_id (derived from name User). But since your column is actually called teacher_id, you should use that instead.
has_many :own_seminars,
class_name: "Seminar",
foreign_key: 'teacher_id'

Rails current_user association by user_id

I've got three models: user, product and order. The associations are as follows:
a User (seller) has many Products
a User (buyer) has many Orders
an Order has one Product
an Order has one User (buyer)
a Product has one User (seller)
a Product has one Order
Now in the product model there's an association to a user:
belongs_to :seller, class_name: "User", foreign_key: "seller_id"
in the products_controller for adding a new product linking it to a user:
def create
#product = current_user.products.create(product_params)
....
In the database the foreign key has also been renamed to "seller_id".
When the current_user.products line is called the response fails
ActiveRecord::UnknownAttributeError (unknown attribute 'user_id' for Product.):
app/controllers/products_controller.rb:23:in `create'
I'm not sure how to change the current_user to products association to use this seller_id key. Any help would be much appreciated, thanks.
The :foreign_key option you have in your Product.belongs_to actually needs to be over on User.has_many, ie., in User:
has_many :products, foreign_key: :seller_id

Custom includes association in rails

I have the following table
Users(user_id, name, last_name)
Relationships(user_id, spouse_id)
I want to run the following query
person = Relationships.includes(:person).where(:name => 'David')
But I don't want the related person to be associated by the user_id. I would rather it be associated by the spouse_id only for this specific query.
Rails is perfectly content to allow multiple associations to the same table, providing they use a different foreign key.
In this case, you'd have something like this:
class User
has_many :relationships
has_many :spouses, class_name: "Relationship", foreign_key: :spouse_id
end
User.first.spouses would then be a collection of all relationships where the user's id was present in the spouse_id field.

Multiple relationships between two models in rails

I have a comment system with two tables: comments, and users. On the comment I want to record who the author was and also I want to notify any user that is mentioned in the comment with (#username). So I'm thinking I need to have an author_id on the comment, and also a comments_users table with the comment id and all the users ids that were mentioned. Would this be a correct way to accomplish it?:
User:
has_many :comments
Comment:
belongs_to :users, class_name: 'User', foreign_key: 'author_id'
has_many :users
The associations could be set up thus:
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :mentions, join_table: "comments_users", association_foriegn_key: "comment_id"
end
Class Comment < ActiveRecord::Base
belongs_to :author, class_name: "User", foreign_key: "author_id"
has_and_belongs_to_many :mentions, join_table: "comments_users", foreign_key: "comment_id"
end
#comments_users
comment_id | user_id
This will allow you to call:
#user.comments #-> shows comments user has authored
#user.mentions.first.comment #-> shows first comment user was mentioned in
#comment.author #-> shows user who authored comment
#comment.mentions.first.user #-> shows first user who was mentioned in comment
Update
HABTM still needs a table (Rails migration for has_and_belongs_to_many join table), but the difference is that it doesn't need a primary key column (just comment_id | user_id)
We've created a "self-referential" habtm relationship, meaning you don't need to "create" any records -- they should all be created already. The HABTM will just reference them. As such, you'll need to use the << ActiveRecord method to add records into your mentions collection:
#app/controllers/comments_controller.rb
Class CommentsController < ActiveRecord::Base
def create
#comment = Comment.new(comments_params)
#comment.save_with_mentions
end
end
#app/models/comment.rb
Class Comment < ActiveRecord::Base
def save_with_mentions
comment = self.save
#do something to find mentioned users
mentioned_users = User.where("user_id = 1") #example
for user in mentioned_users do
comment.mentions << user
end
end
end
There are always many ways to accomplish any given task, but I'm guessing you're looking for something like this for your models & associations.
User:
has_many :comments
The user model association looked right.
Comment:
belongs_to :author, class_name: 'User', foreign_key: 'user_id'
has_many :users
Note, the belongs_to should reference a model in singular-naming style (ie: user vs users). I think you're going to want to do a reference like comment.author to find the author of your comments. It is more typical to provide a foreign_key of user_id when referring to a User model to keep things clear, but then provide a clarifying association name like "author" or "creator" or whatever for reference as I showed above. So your Comments table would have a foreign_key of user_id to reference back to the Users table. This user would be referenced in Rails by the name "author".
The second part of your question that has to do with tracking other user references in your model sounds like a one-to-many from the comment-users table. So, that sounds like one option. Similar to your "author" comment, you may want to provide a clearer name like "tags" which can just be references to users.
Another good option for this feature may be to set up a polymorphic table (essentially a flexible join table) if you plan to use this principle elsewhere in your app (like for referencing/tagging people in other elements like a photo or posting or something). It could provide greater flexibility for adding features and tracking these user references. A polymorphic table could have any name, but usually has an "-able" type name - like "taggable". Here's a useful reference: http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

Has many conditions in Rails 4

How to do this:
has_many :space_mappings, -> { where(group_id: group_id) }, through: :category
That is - SpaceMapping and this model both has a group_id and they have to match. I could just make a method but I would like for this to be possible.
Here I get:
undefined local variable or method `group_id' for #<ActiveRecord::Relation::ActiveRecord_Relation_SpaceMapping:0x007fe5ac118bd8>
I have done this instead:
def space_mappings
category.space_mappings.where(space_id: Space.where(group_id: group_id))
end
Thanks in advance.
You must assign a value for category_id.
See http://guides.rubyonrails.org/association_basics.html (4.3.3.1 section).
It can help your for understanding details and clear concept.
If "this model" has a belongs_to :category relationship or a has_one :category relationship, then you shouldn't need that where clause at all. The whole point of "has many through" is to restrict the associated models to those that are associated with the model they're associated through
That is, you should just be able to do
belongs_to :category
has_many :space_mappings, through: :category
assuming that space mappings also belong to a category.

Resources