我的模型的地址字段需要是唯一的:
class AddressMeta < AR::Base
def normalize
# normalize and store full_address
end
validates_uniqueness_of :full_address
after_validation :normalize
end
我通过地理编码API传递地址,以确保它们在存储之前有效并规范化。我遇到的麻烦是我还希望地址是唯一的,因此每个唯一的地址字符串只有一条记录。请访问以下地址:
101 E 1st St #101, Austin, TX
101 E 1st Street Suite 101, Austin, TX
这两个显然是相同的地址,但我无法在数据库中找到第二个,除非它首先被标准化以匹配第一个。因此,如果存在第一个并且我在第二个上运行find_or_create_by(full_address: address)
调用,我最终会错过搜索并创建一个新对象,这会导致冲突。
所以 - 我的问题。在Rails / AR中,如何在执行搜索之前规范化find_or_create_by方法的输入?或者有一种更好的方法来处理在标准化字段后我在一个唯一字段上发生碰撞的情况吗?
答案 0 :(得分:0)
如果没有代码的完整上下文,很难确定,但是一个解决方案是将规范化执行更改为在验证之前而不是之后:
class AddressMeta < AR::Base
validates_uniqueness_of :full_address
before_validation do
full_address = normalize_address(full_address)
end
private
def normalize_address(address_string)
# Code to convert address with API
# Returns normalized address string
end
end
这样唯一性验证器应该有效。另外,一个不错的小重构就是将地址规范化逻辑提取到它自己的类中:
# lib/address_converter.rb
class AddressConverter
class << self
def normalize(raw_address)
# Logic and API Code
# Returns normalized string
end
end
end
# app/models/address_meta.rb
require 'address_converter'
class AddressMeta < AR::Base
validates_uniqueness_of :full_address
before_validation do
full_address = AddressConverter::normalize(full_address)
end
end