Ruby on rails 在SQL where子句中使用之前修改值?

Ruby on rails 在SQL where子句中使用之前修改值?,ruby-on-rails,rails-activerecord,Ruby On Rails,Rails Activerecord,在WHERE子句中的值进入MySQL之前,有没有一种方法可以修改模型中的值 具体来说,我正在处理电话号码,为了确保用户隐私,我只在数据库中存储SHA256哈希电话号码。但是,我希望能够对模型进行处理,就好像它没有被散列一样 例如: def phone_number=(number) write_attribute(:phone_number, OpenSSL::HMAC.hexdigest('SHA256', 'salt', number)) end 这可以让我保存原始电话号码并自动哈

在WHERE子句中的值进入MySQL之前,有没有一种方法可以修改模型中的值

具体来说,我正在处理电话号码,为了确保用户隐私,我只在数据库中存储SHA256哈希电话号码。但是,我希望能够对模型进行处理,就好像它没有被散列一样

例如:

def phone_number=(number)
    write_attribute(:phone_number, OpenSSL::HMAC.hexdigest('SHA256', 'salt', number))
end
这可以让我保存原始电话号码并自动哈希。但我能做什么呢

PhoneNumbers.where(phone_number: '555-1234')
并在将“555-1234”转换为SQL之前对其进行哈希处理?

检查此项,特别是创建自定义类型标题

定义自定义类型并将其设置为属性的类型。定义一个序列化方法,该方法将值转换为使用SQL语句

从文档中:

class Money < Struct.new(:amount, :currency)
end

class MoneyType < Type::Value
  def initialize(currency_converter:)
    @currency_converter = currency_converter
  end

  # value will be the result of +deserialize+ or
  # +cast+. Assumed to be an instance of +Money+ in
  # this case.
  def serialize(value)
    value_in_bitcoins = @currency_converter.convert_to_bitcoins(value)
    value_in_bitcoins.amount
  end
end

# config/initializers/types.rb
ActiveRecord::Type.register(:money, MoneyType)

# app/models/product.rb
class Product < ActiveRecord::Base
  currency_converter = ConversionRatesFromTheInternet.new
  attribute :price_in_bitcoins, :money, currency_converter: currency_converter
end

Product.where(price_in_bitcoins: Money.new(5, "USD"))
# => SELECT * FROM products WHERE price_in_bitcoins = 0.02230

Product.where(price_in_bitcoins: Money.new(5, "GBP"))
# => SELECT * FROM products WHERE price_in_bitcoins = 0.03412

如您所见,where方法接收Money对象,但SQL语句有一个十进制值。

一个自定义序列化程序完美地解决了我的用例

# lib/serializers/phone_hash_serializer.rb
class PhoneHashSerializer
  def self.load(value)
    value.to_s
  end

  def self.dump(value)
    value = value.to_s
    if value.start_with? 'hashed!'
      value
    else
      # Rails serializer's do not handle one-way hashing well, as the value ends up getting
      # getting dumped/hashed twice (once on the type-cast, then again before storing to DB).
      # So, we "tag" the value as "hashed!" to ensure we don't double hash since search's
      # only get hashed once, and would therefore never match the DB value
      'hashed!' + hash_string(value)
    end
  end

  private

  def self.hash_string(value)
    OpenSSL::HMAC.hexdigest('SHA256', 'hash_salt', value)
  end
end


# models/phone_number.rb
require 'serializers/phone_hash_serializer'
...
serialize :phone_number, PhoneHashSerializer
...

我曾经是我的缪斯女神。感谢那些帮助过我的人

我喜欢这个概念,但它最终没有为我工作。我需要一个自定义序列化程序