Область ActiveRecord с помощью пользовательского метода

Итак, скажем, у меня есть класс с именем Property, и я использую адаптер PostGIS для отслеживания пространственных отношений между физическими объектами (такими как дом, офис и т. д.). Я также использую гем RGeo для отслеживания отдельных объектов. расположение свойств.

Таким образом, если я позвоню:

p = Property.first
p.location # => #<RGeo::Geographic::ProjectedPointImpl:0x3f9303eecc3c "POINT (-111.67226 33.231371)">
p.location.latitude # => 33.231371

У меня также есть собственный метод в модели свойств:

class Property < ActiveRecord::Base
  ...
  def lat
    self[:location].latitude
  end
end

p.lat # => 33.231371

Я хочу создать область, похожую на «широта меньше x» или «долгота больше x».

Однако, если я наберу в консоли

irb> Property.where("lat > ?", 30)
# => ActiveRecord::StatementInvalid: PG::Error: ERROR:  column "lat" does not exist

И если я попробую область, которая выглядит так:

class Property < ActiveRecord::Base
  ...
  scope :lat_lt, lambda {|val| where(['properties.location.latitude <= ?', val]) }
end

Тогда я получаю

irb> Property.lat_lt "30"
# => Property Load (1.3ms)  SELECT "properties".* FROM "properties" WHERE (properties.location.latitude <= '30')
# => ActiveRecord::StatementInvalid: PG::Error: ERROR:  schema "properties" does not exist

Таким образом, в основном нет столбца для «lat», хотя я могу вызвать .lat для экземпляра свойства и получить необходимую мне информацию. Теперь мне просто нужно создать способ охвата по этому возвращаемому значению, даже если столбца нет.

Я хотел бы получить больше информации о том, как это работает; Запрос ActiveRecord работает на уровне, который не знает о методах, определенных в модели, которые не существуют сами по себе в базе данных?

Любая помощь будет высоко оценена.


person user3155324    schedule 02.01.2014    source источник


Ответы (1)


Когда вы используете метод where (или любой другой метод из интерфейса запросов AR: http://guides.rubyonrails.org/active_record_querying.html) вы создаете SQL-запрос, который выполняется при необходимости. Поскольку ваша база данных не имеет доступа к вашему коду, она понятия не имеет об определенных вами методах — она имеет доступ только к тому, что хранится в базе данных.

Если вы хотите получить результаты на основе своего пользовательского метода, вы можете 1. получить список всех свойств, а затем отфильтровать их с помощью select метода (http://www.ruby-doc.org/core-2.1)..0/Array.html#method-i-select ) - однако это может привести к серьезным проблемам с производительностью и ресурсами. 2. (рекомендуется) выяснить, как получить то, что вы хотите, используя чистый sql.

Если бы вы могли показать, как местоположение хранится внутри db, я постараюсь помочь дальше.

person BroiSatse    schedule 02.01.2014