Rails normalize before find_or_create

泄露秘密 提交于 2019-12-25 01:24:49

问题


I have a model with an address field that needs to be unique:

class AddressMeta < AR::Base
  def normalize
    # normalize and store full_address
  end

  validates_uniqueness_of :full_address

  after_validation :normalize
end

I am passing addresses through a geocoding API to ensure that they are valid and normalized before storing. The trouble I'm running into is that I also want addresses to be unique, so there's only a single record per unique address string. Take the following addresses:

101 E 1st St #101, Austin, TX
101 E 1st Street Suite 101, Austin, TX

These two are obviously the same address, but I can't find the second in the database unless it is first normalized to match the first. So if the first one exists and I run a find_or_create_by(full_address: address) call on the second, I end up missing with the search and creating a new object, and this results in a collision.

So - my question. In Rails/AR, how can I normalize the input to the find_or_create_by method prior to performing the search? Or is there a better way to handle the case that I have a collision on a unique field after normalizing a field?


回答1:


It's difficult to determine without the full context of the code, however one solution is to change the normalize execution to occur before validation and not after:

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

That way the uniqueness validator should work. Also, a nice little refactor would be to extract the address normalization logic out into its own class:

# 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    


来源:https://stackoverflow.com/questions/26855803/rails-normalize-before-find-or-create

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!