steve klein
steve klein

Reputation: 2629

Rails get collection of parents from children

I have the following models/relationships:

class Directory < ActiveRecord::Base
  has_one :location
end

class Location < ActiveRecord::Base
  belongs_to :directory
  geocoded_by :full_address
end

Location uses the geocoder gem. Each directory entry has a location, along with directory information (contacts, website, etc).

In directory#index, I would like to show locations near the user's search location. So far I have:

def index
  if params[:search].present?
    @directories = Location.near(params[:search], 50, :order => :distance).paginate(page: params[:page], :per_page => 10)
  else
    @directories = Directory.order(:name).paginate(page: params[:page], :per_page => 10)
  end
end

How can return a collection of directory (parent) entries corresponding to locations (children)?

Upvotes: 1

Views: 305

Answers (2)

Aleksey Shein
Aleksey Shein

Reputation: 7482

You could use something like this:

Directory.joins(:locations).where(locations: { id: Location.near(params[:search], 50, :order => :distance) })

This will generate a query similar to this:

SELECT `directories`.* 
FROM `directories` 
INNER JOIN `locations` ON `locations`.`directory_id` = `directories`.`id` 
WHERE `locations`.`id` IN (SELECT `locations`.`id` FROM `locations` WHERE "your search query here" )

EDIT: Or you can move the Location query right into INNER JOIN clause:

location_query = Location.near(params[:search], 50, :order => :distance).distinct.select(:directory_id)
directories = Directory.joins("INNER JOIN (#{location_query.to_sql}) loc ON loc.directory_id = directories.id")

I believe the queries above are better than direct mapping directories, i.e.

directories = Location.near(params[:search], 50, :order => :distance).
  paginate(page: params[:page], :per_page => 10).map(&:directory)

because in my query you can apply pagination at the right level (directories), but here you apply it to locations. This is not so good, because if some locations belong to same directory, you'll end up with duplicate directories (if you forget to add .uniq at the end of your query) or a shorter directories list (if you don't forget about .uniq :) ).

Have a nice day!

Upvotes: 1

steve klein
steve klein

Reputation: 2629

Well, not strictly an answer to my question, but since other answers have not been forthcoming, I took a nap and then realized that this was a bit of an XY problem for me.

Rather than generating a collection of parents (directories), I just did what the geocoder gem wanted to do and generated a collection of locations. Then, in my view, I just used the directory parent association to get to each corresponding directory.

Works perfectly.

Upvotes: 0

Related Questions