Association with the same model - ruby-on-rails

I have two models 'Product' and 'Variant',product has many variants,now I have to set assocaiation of a new Model named as "Ingridient" with variant in such a way that Variant has many ingridients.but in ingridents I want to show that it again has_one product and variant.for example
class Variant
has_many :ingridients
belongs_to :product
end
class Ingridient
belongs_to :variant
belongs_to :product
end
now in my ingrident model I also want has_one variant and has_one product at the same time.how should I set my associations.I know multiple association with same table but dont know how to implement it in my app.Iam using mongoid as my database.
Edit : Actually in my flow User can create a Product with many variants and then each variant can have multiple ingridients.In that each ingrident i have select box for selecting products and variants form database .means ingridients will consist a product a variant ,quantity etc fields .To make it more clear Iam making a Recipe
.

I am not 100% clear on what you want to do.
But what it looks like is that you want to have a association with a different name.
class Variant
has_many :ingridients, :foreign_key => 'FieldName', :class_name => 'CassName'
belongs_to :product, :foreign_key => 'FieldName', :class_name => "CassName"
end
class Ingridient
belongs_to :variant, :foreign_key => 'FieldName', :class_name => "CassName"
belongs_to :product, :foreign_key => 'FieldName', :class_name => "CassName"
end
I hope that this helps

Related

When an association is specified with class name, how do you access it? Rails 3

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"

How to access referenced table in a n:m relation in Ruby on Rails?

I have got a Database like this:
users
-id
user_cars
-user_id
-car_id
cars
-id
-model
-color
So a user can have multiple cars, and detailed information about the cars are in a big cars table. I also created the models with the relationships.
class User
has_many :user_cars
class User_car
belongs_to :user
belongs_to :cars
class Car
has_many :user_cars
Now I want to access the information for all the cars for one user. My first approach would be to get at least one information (i.e. color) from the cars table.
I tried this one, just as an example for accessing the middle table:
#user_id = current_user.user_cars.find(1).user_id
works! But when I try to access the cars table I always get an error.
#color = current_user.user_cars.cars.find(1).color
undefined method `cars' for #<ActiveRecord::Relation:0xaf92e8c>
So I think Im doin something easy very wrong...
When I know how to get access to the third table, I have to do it in that fashion, that I only get results for the user and not just only the first entry, maybe you guys can help me with that aswell. Thanks!
The issue in your example by the way is that belongs_to should be singular. Also, your order was wrong.
#color = current_user.user_cars.find_by_car_id(1).car.color
You should rewrite this to use a has_many through association:
class User
has_many :user_cars
has_many :cars, :through => :user_cars
class UserCar
belongs_to :user
belongs_to :car
You can then access the cars by doing:
current_user.cars
And the color by doing:
#color = current_user.cars.find_by_car_id(1).color
EDIT
After some debugging, it turns out that the Car model has a class property. Class is a reserved word in ruby. Be careful with naming your attributes!
Without has_many :through associations:
#color = current_user.user_cars.where(:car_id => 1).first.color
With them:
class User < ActiveRecord::Base
has_many :user_cars, :foreign_key => :user_id, :class_name => "UserCar", :inverse_of => :user
has_many :cars, :through => :user_cars
end
class UserCar < ActiveRecord::Base
belongs_to :user
belongs_to :car
end
class Car < ActiveRecord::Base
has_many :user_cars, :foreign_key => :car_id, :class_name => "UserCar", :inverse_of => :car
has_many :cars, :through => :user_cars
end
#color = current_user.cars.find(1).color
http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association
:through defines a shortcut
:inverse_of defines a method (association) which represents current model in :class_name model
:class_name defines which model should be represented by :user_cars
:foreign_key tells which column in the target model's table represents current model (in table user_cars (or users_cars, depends on how you define the association, i think it should be user_cars in this example.. and users_cars for has_and_belongs_to_many)
Details on those are in the link above.

Rails associations - ideas for best practice

A question regarding Rails associations.
Consider the following models:
People
Events
Images
People and events can have many images.
Images uploaded to an event, need to have the ability to be associated with multiple people.
This means that there are two relationships between people and images.
One where images are uploaded directly on the person. And one where a person is tagged in an event.
Can there also be a relationship between a person and an event based on the fact they were tagged in one (or multiple) images in an event? In this regard, it's a sort of image tagging system where associations are created based on what event people are tagged in.
Wondering what is the best practice in Rails to create this association? Any help or advice is greatly appreciated!
I am not absolutely sure about best practice,
but there is a chance to solve your case in simple way, as far as i understand you:
We have:
Event ... has_many :photos; Photo ... belongs_to :event
and solution is to create some intermediary ActiveRecord class
People ... has_many :photos, :through photo_mappings
PhotoMapping ... belongs_to :user; belongs_to :photo
Have a nice AR associations best practice1
In rails it is definitely possible to define a join-table that has extra fields. So in this case I would define the following table:
class LinkedImage
belongs_to :person
belongs_to :image
OWNER=1
TAGGED=2
validates :relation_type, :inclusion => {:in => [OWNER, TAGGED]}
end
This table would link an image to a person, and has an extra field relation_type (you could think of a more appropriate name maybe), which now can have two values: 1 (for the OWNER, meaning the image was directly uploaded to the person), and 2 (the person is tagged in the image). Aside from the relation, maybe you want to store something extra, like the position in the image, an extra comment, then you could easily add that here as well.
And the person would look like:
class Person
has_many :linked_images
has_many :uploaded_images, :class_name => Image,
:through => :linked_images,
:conditions => "relation_type=#{LinkedImage::OWNER}"
has_many :tagged_in_images, :class_name => Image,
:through => :linked_images,
:conditions => 'relation_type=#{LinkedImage::TAGGED}"
end
and the code for Image could be similar.
I hope this helps.
I don't know if this is the best approach, but I would do something like this:
class User < ActiveRecord::Base
has_many :images, :as => :owner
has_many :tags
has_many :tagged_images, :through => :tags, :source => :image
has_many :tagged_events, :finder_sql => %q( SELECT `events`.* FROM `events`, `images` WHERE `events`.id = `images`.owner_id AND `images.owner_type ="Event" `
WHERE (`images`.id IN (#{tagged_image_ids.join(',')}) ))
end
class Event < ActiveRecord::Base
has_many :images, :as => :owner
has_many :tagged_users, :finder_sql => %q( SELECT `users`.* FROM `users`, `images` WHERE `users`.id = `images`.owner_id AND `images.owner_type ="User" `
WHERE (`images`.id IN (#{image_ids.join(',')}) ))
end
class Tag < ActiveRecord::Base
belongs_to :user
belongs_to :image
end
class Image < ActiveRecord::Base
belongs_to :owner, :polymorphic => true
has_many :tags
has_many :tagged_users, :through => :tags, :source => :user
end
Note: Using finder_sql is not the best in Rails, because for example it doesn't allow you to add new tagged images just using the relationship, but it works fine for reading.

generic categories for my rails models

I am working in a rails app which main points are articles and products.
Someone has implemented categories for articles.
class ArticleCategory < MainSchemaBase
belongs_to :user
has_many :articles, :through => :article_category_articles, :conditions => 'articles.deleted_at IS NULL'
has_many :article_category_articles, :conditions => 'article_category_articles.deleted_at IS NULL'
And I have been asked to do basically the same thing for products.
Of course I want to DRY but products belongs to brand instead of user, and I have many products instead of many articles
The model is almost empty (some named scopes), controller and views also very dependent of the context (article)
Can this be DRY? Or should I just copy the implemntation ?
Make it polymorphic: The best way, i think, is to set up a polymorphic many-to-many relationship using has_many_polymorphs (https://github.com/Nielsomat/has_many_polymorphs) so that a single category could be applied to a product and an article.
class Category
#doesn't have any association fields
has_many_polymorphs :categorizables, :from => [:products, :articles], :through => :categorizations, :dependent => :destroy
end
class Categorization < ActiveRecord::Base
#has fields categorizable_id, categorizable_type, :category_id
belongs_to :categorizable, :polymorphic => true
belongs_to :category
end
class Product < ActiveRecord::Base
#doesn't need anything to set up the association
end
class Article < ActiveRecord::Base
#doesn't need anything to set up the association
end
"Categorizable" is a bit of a mouthful but you won't actually be using it. You'll be saying #product.categories or #category.articles etc.

How can I have two columns in one table point to the same column in another with ActiveRecord?

I run the risk of palm-to-forehead here, but I can't quite figure out how to do this with Rails' ActiveRecord sugar.
I have a tickets table that has two columns (submitter_id and assignee_id) that should each reference a different user from the users table (specifically the id column in the users table). I'd like to be able to do things like ticket.submitter.name and ticket.assignee.email using ActiveRecord's associations. Submitter and Assignee are simply user objects under different associative names.
The only thing I've found that comes close to what I am doing is using polymorphic associations, but in the end I'm fairly certain that it's not really what I need. I'm not going to have multiple types, both submitter and assignee will be users, and very well could be two different users.
Any help would be fantastic. Thanks!
class Ticket < ActiveRecord::Base
belongs_to :submitter, :class_name => "User"
belongs_to :assignee, :class_name => "User"
end
Should work.
Edit: Without trying it out, I'm not sure whether you need the :foreign_key parameter or not. My instinct is not, but it couldn't hurt.
Edit again: Sorry, left off the User -> Ticket associations. You didn't mention using them, and I typically will only add associations in one direction if I don't plan on using them in the other direction.
Anyway, try:
class User < ActiveRecord::Base
has_many :assigned_tickets, :class_name => "Ticket", :foreign_key => "assignee_id"
has_many :submitted_tickets, :class_name => "Ticket", :foreign_key => "submitter_id"
end
Something like this should work
class Ticket < ActiveRecord::Base
belongs_to :submitter, :class_name => 'User', :foreign_key => 'submitter_id'
belongs_to :assignee, :class_name => 'User', :foreign_key => 'assignee_id'
end
class User < ActiveRecord::Base
has_many :tickets, :class_name => 'Ticket', :foreign_key => 'submitter_id'
has_many :tickets_assigned, :class_name => 'Ticket', :foreign_key => 'assignee_id'
end
Yes, PreciousBodilyFluids is right we don't need to specify the foreign_key in the Ticket class as rails can infer it from the column name, i.e. submitter_id and assignee_id
But if your association name is different from the column_name_{id} then you will have to specify it, i.e. the User class case

Resources