Rails Polymorphic Association with multiple associations on the same model
I have done that in my project.
The trick is that photos need a column that will be used in has_one condition to distinguish between primary and secondary photos. Pay attention to what happens in :conditions
here.
has_one :photo, :as => 'attachable',
:conditions => {:photo_type => 'primary_photo'}, :dependent => :destroy
has_one :secondary_photo, :class_name => 'Photo', :as => 'attachable',
:conditions => {:photo_type => 'secondary_photo'}, :dependent => :destroy
The beauty of this approach is that when you create photos using @post.build_photo
, the photo_type will automatically be pre-populated with corresponding type, like 'primary_photo'. ActiveRecord is smart enough to do that.
Polymorphic Association with multiple associations on the same model
Yep. That's totally possible.
You might need to specify the class name for header_image
, as it can't be inferred. Include :dependent => :destroy
too, to ensure that the images are destroyed if the article is removed
class Article < ActiveRecord::Base
has_one :header_image, :as => :imageable, :class_name => 'Image', :dependent => :destroy
has_many :images, :as => :imageable, :dependent => :destroy
end
then on the other end...
class Image < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
Rails Polymorphic Association with multiple associations on the same model bug
image_type
has a specific function in this polymorphic association... it identifies the associated model (just as image_id
identifies the id).
You should not be changing image_type
as that breaks the association.
Make a new boolean column in the picture model, say cover_picture
, and you can do...
has_one :cover_picture, -> {where cover_picture: true} ...
The advantage of this is your cover picture is also included in your pictures association, but if you want that picture excluded from the has_many then you can apply a where clause to that as well...
has_many :pictures, -> {where.not cover_picture: true} ...
Rails two polymorphic associations in one model
Of course class_name: "Teamable"
does not work as the whole point of a polymorphic association is that the class that the class (and more importantly target table) of the association is dynamic. Its not needed either.
A polymorphic association uses a separate association_name_type
string column which contains the class name which its associated with.
Given the following data:
| id | team_one_id | team_one_type # ...
----------------------------------
1 | 1 | "HighSchoolTeam"
2 | 2 | "ClubTeam"
3 | 3 | "HighSchoolTeam"
When you do Game.find(1).team_one
Rails knows to use the HighSchoolTeam
class and join the high_school_teams
table. But it needs to pull the rows out before it can make the connection and of course your database knows nothing about the relation and won't maintain referential integrity.
So all you need is:
class Game < ApplicationRecord
belongs_to :team_one, polymorphic: true
belongs_to :team_two, polymorphic: true
end
And make sure you have team_one_type
and team_two_type
string columns on the games
table.
Rails Polymorphic Association with multiple models
There's no limit. A polymorphic association is an open interface that any other model can plug into. In your example, maybe you have a Contact
model, which belongs_to :contactable, polymorphic: true
. The contacts
table will need two indexed columns: contactable_id:integer
, and contactable_type:string
. Any other model can be contactable
, as long as it has_one :contact, as: :contactable
.
As far as if it's a good idea, I'd say if you think you will need to work with contacts
as a separate entity from the contactable
models, then this is a good solution. However, if you won't need to deal directly with contacts
then it might be overcomplicating when you could just add email
and phone
fields to these models.
Multiple polymorphic association on a same model in rails
by adding the condition in the relation, it is letting you retrieve the images
with imageable_sub_type = cover_image
when you call place.cover_image
. It will not set the attribute for you when you add the image. That has to be done separately when the image is added based on some input from the view like a checkbox tag.
Update: You can override the default association=
method , sthing like below in Place
model:
def cover_image=(img)
# add the img to tthe associated pictures
self.pictures << img
# mark current img type as cover
img.update_attribute(:imageable_sub_type, "cover_image")
# mark all other images type as nil, this to avoid multiple cover images,
Picture.update_all( {:imageable_sub_type => nil}, {:id => (self.pictures-[img])} )
end
Rails polymorphic association and has_many for the same model
You'll want to use another name for that association.
has_many :comments, as: :commentable
has_many :commented_on, class_name: 'Comment' # you might also need foreign_key: 'from_user_id'.
See has_many
's documentation online.
The foreign_key
should not be needed in your case, but I'm pointing it out Just In Case™. Rails will guess "{class_lowercase}_id" by default (so user_id
in a class named User).
Then you can access both associations (The class_name
is explicitly needed because Rails can't find Comment
from commented_on
).
Polymorphic Relationship with Multiple Associations
I came up with the following idea to utilize the existing Polymorphic Relationship to handle multiple associations.
First, I changed the schema to this:
Employees
id
NonEmployees
id
Sponsors
id
sponsored_id
sponsored_type
sponsorable_id
sponsorable_type
So, I removed the sponsor_id field from each of the account type tables and added a second polymorphic relationship to the Sponsors table.
I updated the models as follows:
Models/Employee.php & Models/NonEmployee.php
public function sponsorable()
{
return $this->morphOne('Sponsor', 'sponsorable');
}
public function sponsors()
{
return $this->morphMany('Sponsor', 'sponsor');
}
Models/Sponsor.php
public function sponsor()
{
return $this->morphTo();
}
public function sponsorable()
{
return $this->morphTo();
}
Now, because Laravel doesn't support a morphManyThrough() relationship type, you'll notice I changed some of the names of the functions so that it would read a little cleaner when using the relationships since I have to go from one table through an intermediary table and then to a 3rd table to get the information I want.
With this structure, I can do the following:
$employee = Employee::find(2)->sponsorable->sponsor; // Gets employee's sponsored party
$sponsors = $employee->sponsors; // Gets individual that the employee is sponsoring.
foreach ($sponsors as $sponsor)
echo $sponsor->sponsorable->first_name;
$employee->sponsors()->save(new Sponsor()); // New sponsor
$non_employee->sponsors()->save(new Sponsor()); // New sponsor
I can also perform a reverse lookup:
Sponsor::find(1)->sponsor->first_name; // Sponsoring party
Sponsor::find(1)->sponsorable->first_name; // Party being sponsored
Rails: Polymorphic Relationship needed multiple times for one model. How to differentiate? Is there a better way?
What separates the address categories? You mention that you may have a billing address and a site address.
If for example the categories are determined by an attribute called 'category', then all you have to do is set a condition on the association declarations on the addressable:
class Account < ApplicationRecord
has_one :billing_address, -> { where category: 'billing' }, class_name: "Address", as: :addressable
has_one :site_address, -> { where category: 'site' }, class_name: "Address", as: :addressable
end
Related Topics
Unable to Load Gem Cocoa Pods While Creating Repo
How to Run Ruby 2.0 with Jruby 1.7
What Do the Fields of Ruby's Gc.Stat Mean
How to Get Ruby to Parse Time as If It Were in a Different Time Zone
Ruby: How to "Require" a File from the Current Working Dir
How to Run Phantomjs on Heroku
Rails Sort Tags by Most Used (Tag.Posts.Count)
Finding Lines in a Text File Matching a Regular Expression
Rubocop Error 'Class Definition Is Too Long Ruby'
Rendering Haml Partials from Within Haml Outside of Rails
Checking Whether the C Compiler Works... No
Find Memory Leak in a Ruby on Rails Project
Constants or Class Variables in Ruby
How to Turn a Ruby Method into a Block
Pry Not Stopping When Called from a Ruby Script That Reads from Stdin