Rails find by has_many :through - ruby-on-rails

I am looking for a way to query a model based on children in a has_many through association.
I have 3 models:
class Conversation < ActiveRecord::Base
has_many :conversations_participants
has_many :participants, through: :conversations_participants
end
class ConversationsParticipant < ActiveRecord::Base
belongs_to :conversation
belongs_to :participant, class_name: 'User'
end
class User < ActiveRecord::Base
has_many :conversations_participants
has_many :conversations, through: :conversations_participants
end
I need to find conversations where participants matches an array of ids.
This is what i have at the moment (not working):
Conversation.includes(:participants).where(participants: params[:participants])

Sounds like you just want the conversations, if so you can joins.
Conversation.joins(:participants).where(:users => { :id => params[:participants] } )
Otherwise, if you want to eager load the participants, use includes
Conversation.includes(:participants).where(:users => { :id => params[:participants] } )

You can pass an array like this:
Conversation.includes(:participants).where(:id => params[:participants])
Assuming that params[:participants] is an array.

Conversation.includes(:participants).where( 'conversation_participants.participant_id' => params[:participants])
assuming that participant_id is the foreign key of participants in the conversation_participants table

Related

Rails 4, How to get through - has_many associations active records

I modeling a three tables
Event, EventEventCategory and EventCategory
class Event < ActiveRecord::Base
has_many :event_event_categories
has_many :event_categories, :through => :event_event_categories
scope :live_event, ->{where(visible_status: 1)}
end
class EventEventCategory < ActiveRecord::Base
belongs_to :event
belongs_to :event_category
end
class EventCategory < ActiveRecord::Base
has_many :event_event_categories
has_many :events, :through => :event_event_categories
end
And I get a event using live_event scope.
#events = Event.live_event
And I wanna get a live_event 's category_lists
Now I get a Category list usgin below code
EventCategory.where("id in (?)", EventEventCategory.where("id in (?)", #events.pluck(:id).uniq))
or
EventCategory.where("id in (?)", #events.joins(:event_event_categories).pluck(:event_category_id).uniq)
is another command exist get a events category's list like a
Event.live_events.event_categories
EventCategory.joins(:events).where(events: { visible_status: 1 })
maybe this one can help

Returning unique object from Active Record Association Relation

I'm having trouble with a simple has_many relationship. I'm trying to return unique objects, but because I'm putting restraints on the object in the middle of the relationship, I'm getting an undefined method on my ActiveRecord_AssociationRelation.
I have:
class Customer < ActiveRecord::Base
has_many :session_enrollments
has_many :session_details, through: :session_enrollments
class SessionDetail < ActiveRecord::Base
has_many :customers, through: :session_enrollments
belongs_to :trainer
class Trainer < ActiveRecord::Base
has_many :session_details
has_many :session_enrollments, through: :session_details
has_many :customers, through: :session_enrollments
class SessionEnrollment < ActiveRecord::Base
belongs_to :customer, :foreign_key => "customer_id"
belongs_to :session_detail, :foreign_key => "session_detail_id"
I'm trying to return all trainers that have a current session with a customer via:
Customer.rb
#trainers = self.session_details.where(state: ["CONFIRMED"]).trainers
But the where statement loads an active record association object. How can I include this condition and still return the unique trainers?
Try this:
#trainers = Trainer.joins(:session_details, :customers).where(session_details: {state: "CONFIRMED"}).where(customers: {id: self.id}).distinct
I'd try this:
#trainers = Trainer.joins(session_details: [:session_enrollments]).where(session_details: {state: 'CONFIRMED'}).where(session_enrollments: {customer_id: self.id}).distinct
I'm assuming that state is a column in Customer, You need to join the records, try this instead
#trainers = self.includes(:session_details => :trainer).where(session_details: {state: ["CONFIRMED"]})
This query will return customer along with their session details with associated trainers

Given a 'Location' model, which has_many 'tags' (Tag), find all locations which own associated (tag) records with a certain tag column value

So I'm trying to find all Locations which have Tags with the name "school". Location has_many Tags and Tag has_many Locations via a join table accessed via the :through model method
class Location < ActiveRecord::Base
has_many :location_tags
has_many :locations, :through => :location_tags
end
class LocationTag < ActiveRecord::Base
belongs_to :location
belongs_to :tag
end
class Tag < ActiveRecord::Base
has_many :location_tags
has_many :locations, :through => :location_tags
end
So those are my models. I know the solution will involve includes, joins or something along those lines
Tag.where(:name => 'school').locations
Got it.
Location.where(query_stuff).includes(:tags).where(:tags => { :name => "school" })

Fetching records through multiple tables

The image shows part of my data model. I would like to fetch all items that are associated with a user (through organizations and items_group). How should I change the models and write this query in the controller? Using :through => organizations I can get all items_groups but I don't how to include one more relation to query related items.
class User < ActiveRecord::Base
has_and_belongs_to_many :organizations
has_many :items_groups, :through => :organizations
end
class Organization < ActiveRecord::Base
has_and_belongs_to_many :users
has_and_belongs_to_many :items_groups
has_many :items, :through => :items_groups
end
class ItemsGroup < ActiveRecord::Base
has_many :items, :inverse_of => :items_group
has_and_belongs_to_many :organizations
has_many :users, :through => :organizations
end
I think you might have to do it back-to-front and find items joined back to your user.
You could define method like this in your User class:
def items
Item.joins(:items_group => {:organizations => :users}).where("users.id" => self.id).select("distinct items.*")
end
The items it returns will be read-only because of the explicit select but I think you'll want that to avoid returning individual items more than once.
If you set in your models the relationships this should work:
users.organizations.item_groups.items
Though for it to work your models should contain this:
class User < ActiveRecord::Base
has_many :organizations, :through => :organization_users
end
class Organization < ActiveRecord::Base
has_many :item_groups, :through => :items_groups_organizations
end
class ItemsGroup < ActiveRecord::Base
belongs_to :item
end
Hope it works for you!

How to "order by" using has_many through?

I have two tables with a join table between them:
Parent: Pages
Child: Things
Join: Grids
In my models they are set up with a many to many relationship (has_many through):
class Page < ActiveRecord::Base
belongs_to :books
has_many :grids
has_many :things, :through => :grids
end
class Thing < ActiveRecord::Base
has_many :grids
has_many :pages, :through => :grids
end
class Grid < ActiveRecord::Base
belongs_to :page
belongs_to :thing
end
Now I want to be able to sort "things" using an ordering id from grid, called number, how can I do that ?
Thanks!
you need the ":include(s)" option in your find method, and then "order_by()" ...
you would use something like this:
Thing.where(...some condition or all..., :include => :grid ).order_by(grid.number)
See:
http://guides.rubyonrails.org/active_record_querying.html
http://m.onkey.org/active-record-query-interface
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Resources