I am trying to get an activerecord association through 2 layers of has_one associations and cannot quite figure it out.
I have 3 models:
class Dialog < ActiveRecord::Base
belongs_to :contact
end
class Contact < ActiveRecord::Base
has_many :dialogs
belongs_to :location
end
class Location < ActiveRecord::Base
has_many :contacts
end
I would like to create a scope in the Dialog model that allows me to pass in the id of a Location and get all Dialogs created by Contacts from the given Location... something like:
Dialog.from_location(Location.first.id)
I can get a non-activerecord array of the desired result using select:
Dialog.all.select{|s| s.contact.location_id == Location.first.id }
But I need this to return an activerecord array so that other scopes or class methods can be called on the result. I have tried using joins and includes, but am confused after reading the rails guides on how to use them.
Can anyone help me figure out how to construct a scope or class method that will accomplish this?
Thanks in advance
Just adding a note to the answer you accepted, quoting from the ruby on rails guides website:
Using a class method is the preferred way to accept arguments for scopes. These methods will still be accessible on the association objects ( link )
So in your condition, instead of doing a scope with an argument, define a method :
class Contact < ActiveRecord::Base
has_many :dialogs
belongs_to :location
def self.from_location(id)
where(location_id: id)
end
end
You can define your scopes as follows:
class Dialog < ActiveRecord::Base
belongs_to :contact
scope :from_location, -> (id) do
where(contact_id: Contact.from_location(id).select(:id))
end
end
class Contact < ActiveRecord::Base
has_many :dialogs
belongs_to :location
scope :from_location, ->(id) do
where(location_id: id)
end
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.