Рельсы геокодируют двумя способами в модели

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

  before_validation :check
  def check
    if self.address.blank?
        reverse()
    else
        geo()
    end
  end

  def reverse
    reverse_geocoded_by :latitude, :longitude,
    :address => :address
    after_validation :reverse_geocode
  end

  def geo
    geocoded_by :address
    after_validation :geocode
  end

Но я получаю следующее undefined method reverse_geocoded_by Я не знаю, что делать!


person Jseb    schedule 11.02.2013    source источник


Ответы (1)


Вы не можете вызывать методы класса внутри метода экземпляра. Помните, что geocoded_by, вероятно, определен для класса вашей модели. Вы не можете произвольно изменить проверки одного экземпляра, не затрагивая все экземпляры модели, поэтому это обычно рассматривается как плохая идея.

Возможно, вам лучше иметь модель «Местоположение», которую можно геокодировать одним из двух разных способов, и создать подкласс для каждого типа кодирования. То есть правила могут быть установлены для каждого из них независимо. Хранить их легко с помощью технологии Single Table Inheritance (STI).

Итак, вы могли бы:

class Location < ActiveRecord::Base
end

class ForwardLocation < Location
  geocoded_by :address
  after_validation :geocode
end

class ReverseLocation < Location
  reverse_geocoded_by :latitude, :longitude,
    :address => :address
  after_validation :reverse_geocode
end

Затем вы должны добавить правильное местоположение соответственно:

self.location = self.address? ? ReverseLocation.create(...) : ForwardLocation.create(...)

Вы также можете написать методы, которые обрабатывают заполнение полей более непосредственно, чем использование подклассов, подобных этому, но это полностью зависит от типа данных, которые вы получаете и обрабатываете.

Как правило, класс должен иметь только один набор обратных вызовов до/после. Некоторые из этих обратных вызовов могут запускаться условно, если определение обратного вызова поддерживает объявление стиля :if. Иногда вам нужно написать свои собственные before_validation подпрограммы для удовлетворения ваших более экзотических требований.

person tadman    schedule 11.02.2013
comment
Единственное, что меня беспокоит, извините, но я все еще новичок в рубине, это self.location = .... ReverseLocation.create(...) как это определяется? это в моей модели, моем контроллере, и если это в моих моделях, то мне нужно будет правильно определить тип в местоположении - person Jseb; 11.02.2013
comment
Это может быть контроллер или модель в зависимости от дизайна вашего приложения. Возможно, было бы целесообразно фиксировать параметры местоположения отдельно, создавать объект местоположения надлежащего типа, а затем назначать его записи, с которой связано местоположение. - person tadman; 11.02.2013