Ruby on rails 在SQL where子句中使用之前修改值?
在WHERE子句中的值进入MySQL之前,有没有一种方法可以修改模型中的值 具体来说,我正在处理电话号码,为了确保用户隐私,我只在数据库中存储SHA256哈希电话号码。但是,我希望能够对模型进行处理,就好像它没有被散列一样 例如: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 这可以让我保存原始电话号码并自动哈
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
...
我曾经是我的缪斯女神。感谢那些帮助过我的人 我喜欢这个概念,但它最终没有为我工作。我需要一个自定义序列化程序