Rails从孩子那里收集父母

时间:2015-09-15 13:31:51

标签: ruby-on-rails-4

我有以下模特/关系:

class Directory < ActiveRecord::Base
  has_one :location
end

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

Location使用geocoder宝石。每个目录条目都有一个位置,以及目录信息(联系人,网站等)。

directory#index中,我想显示用户搜索位置附近的位置。到目前为止,我有:

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

如何返回与位置(子)相对应的目录(父)条目的集合?

2 个答案:

答案 0 :(得分:0)

好吧,不是严格地回答我的问题,但由于其他答案尚未出现,我小睡了一下,然后意识到这对我来说有点XY problem

我没有生成父母(目录)的集合,而是完成了地理编码器宝石想要做的事情并生成了一系列位置。然后,在我看来,我只是使用directory父关联来访问每个相应的目录。

完美无缺。

答案 1 :(得分:0)

您可以使用以下内容:

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

这将生成类似于此的查询:

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" )

编辑:或者您可以将Location查询权限移至INNER JOIN子句:

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")

我认为上面的查询比直接映射目录更好,即

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

因为在我的查询中你可以在适当的级别(目录)应用分页,但是在这里你将它应用于位置。这不是很好,因为如果某些位置属于同一目录,您将最终得到重复的目录(如果您忘记在查询结束时添加.uniq)或更短的目录列表(如果您不喜欢不要忘记.uniq :))。

度过美好的一天!