范围来自另一个模型

时间:2013-09-18 00:48:06

标签: ruby-on-rails

我需要找到一种解决方法,以便我可以按@events方法过滤我的.is_near,然后按照.sort_today范围按顺序对它们进行排序。

单独他们都可以工作,我可以将.is_near添加到范围的末尾而没有任何问题,但是我的结果是.is_near中的默认排序参数,我需要他们按.sort_today排序。

有没有办法忽略.is_near如何返回/调整我的结果?或者像@events.is_near(session[:city]).sort_today一样将它们链接在一起?目前我链接它们时会出现这样的错误:未定义的方法`sort_today'代表#Array:0x007f8ca3c673c0

这是我的模特:

class Venue < ActiveRecord::Base
  attr_accessible :name, :address, :latitude, :longitude

  has_many :events, :dependent => :destroy

  geocoded_by :address

  def self.is_near(city)
    self.near(city, 20, :units => :km).map(&:events).flatten
  end
end

class Event < ActiveRecord::Base
  attr_accessible :title, :details, :start_time, :end_time, :date, :cost, :venue_id

  belongs_to :venue

  scope :is_today, where(:date => Date.today)
  scope :sort_today, is_today.order(:start_time)

  class << self
    def is_near(*args, &block)
      Venue.is_near(*args, &block)
    end
  end
end

所以Venue由RubyGeocoder gem进行地理编码,它包含所有事件。 .is_near方法必须位于Venue,因为纬度和经度属性存在。 .is_near底部的Event方法基本上是重定向。 (我试图让代表工作,但这是我能做到的唯一方法)

这是我的控制器:

class EventsController < ApplicationController
  def index
    @events = Event.sort_today.is_near(session[:city]) #returns results but sorted wrong
    #@events = Event.is_near(session[:city]).sort_today #returns undefined method `sort_today' error
  end
end

class ApplicationController < ActionController::Base
  before_filter :set_city
  def set_city
    unless session[:city].present?
      session[:city] = request.location.city
    end
  end
end

set_city方法只是获取用户通过输入字段输入的城市。

编辑:以下是Ruby Geocoder文档的链接:https://github.com/alexreisner/geocoder

2 个答案:

答案 0 :(得分:1)

当您在.map(&:events)中致电Venue.is_near时,会返回Array而不是AcitveRecord::Relation。这意味着当调用is_near时,数据库查询会立即完成,而不是使用链式方法懒惰地评估查询。

我可以看到几种不同的方法来解决这个问题。

一种是调用Venue.is_near(session[:city]),然后在返回的Array数组上使用sort_by的{​​{1}}方法在Ruby中进行排序。这可能比在数据库中执行速度慢。

另一种方法是执行joinEvent子句和where子句的评估移动到一个数据库查询中。我对地理编码器宝石不太熟悉,所以我不确定这是否适用。基本上我希望能够specify a condition on the join

在活动中:

order by

但是我不确定geocoder gem是否会让你做这样的哈希条件: - /试一试并报告回来?

答案 1 :(得分:0)

我通过将范围位置从Venue模型更改为Event模型来实现它:

class Venue < ActiveRecord::Base
  attr_accessible :name, :address, :latitude, :longitude

  has_many :events, :dependent => :destroy

  geocoded_by :address
end

class Event < ActiveRecord::Base
  attr_accessible :title, :details, :start_time, :end_time, :date, :cost, :venue_id

  belongs_to :venue

  scope :is_today, where(:date => Date.today)
  scope :sort_today, is_today.order(:start_time)
  scope :is_near, lambda {|city| Venue.near(city, 20, :units => :km).map(&:events).flatten }
end

这适用于我的控制器:@events = @events.sort_today.is_near(session[:city])

TLDR:我删除了重定向方法并将其替换为lambda