我希望这不是一个骗局,但由于到目前为止我还没有找到一个令人满意的答案,我将提出我的问题。我是轨道初学者,所以请对我温柔;)
对于一个小型制图项目,我们使用地理编码器 gem。我们有一个模型Place
包含:street
、:house_number
、:postal_code
、:city
被:address
包装为一个简单的字符串,作为传递给地理编码器的虚拟属性。我们正在使用 nominatim (-> OSM 数据)进行查询。与谷歌API不同,如果给定的地址不对应于纬度/纬度对,则nominatim返回nil。到目前为止,我们的模型文件如下所示
class Place < ActiveRecord::Base
has_many :descriptions, :dependent => :delete_all
accepts_nested_attributes_for :descriptions
geocoded_by :address
before_validation :geocode
validates :address, presence: true
validates :name, presence: true
validates :longitude, presence: true,
numericality: { less_than_or_equal_to: 90, greater_than_or_equal_to: -90 }
validates :latitude, presence: true,
numericality: { less_than_or_equal_to: 180, greater_than_or_equal_to: -180 }
validates :categories, presence: true
def address
["#{self.street} #{self.house_number}", self.postal_code, self.city].join(', ')
end
end
与我看过的大多数示例不同,我使用的是before_validation :geocode
因为否则 lat 和 lon 在被评估引发验证错误(不存在)之前将为 nil。到目前为止,这适用于创建新位置,但我无法修改验证以使其适用于控制器内的update
操作。基本上,我想检查应用于address
的更改是否有效(即 API 是否找到到给定地址的纬度/纬度对)。研究我发现的文档,我做了一个像before_validate :geocode, if: :address_changed?
这样的条件回调,但由于更新请求的参数在我的模型中不可用,我不知道如何检查它。我会很高兴任何提示!
编辑:
下面接受的答案是正确的,没有立即工作,因为在我的控制器中我使用的是update
而不是update_attributes
。
模型无需知道参数即可更新请求。您可以通过检查构成地址的任何列是否已更改来检查地址是否已更改。由于address
不是列,因此需要像这样定义address_changed?
:
before_validation :geocode, if: :address_changed?
def address_changed?
street_changed? || house_number_changed? || postal_code_changed? || city_changed?
end
请注意,street
、house_number
、city
和 postal_code
都需要是列才能使上述内容正常工作。