1

我是 Rails 新手,我正在使用 Rails 4 和attr_encryptedgem 来加密一些字段(SSN、姓名、出生日期等),这些字段都将按varchar列插入到数据库中。在表单视图中,我date_select用于生成出生日期字段 (dob),但在尝试将所选日期转换为字符串以便attr_encrypted对其进行加密以插入数据库时​​遇到问题。

_form.html.erb

<%= f.label :dob %><br>
<%= f.date_select :dob,  { start_year: 1900, :order => [ :month, :day, :year ] , prompt: true, add_month_numbers: true, use_two_digit_numbers: true } %>

给出的错误是批量分配错误,但我不知道如何/在哪里(控制器/模型)将哈希转换为字符串,以便attr_encryptedgem 能够对其进行加密。实现这一目标的最佳方法是什么?

4

2 回答 2

2

我发现 attr_encrypted 破坏了 Rails 的自动日期组合date_select。我找到的最简单的解决方案是自己组装日期字符串并重写params哈希。在您的控制器中:

protected    

def compose_date(attributes, property)
  # if the date is already composed, don't try to compose it
  return unless attributes[property].nil?

  keys, values = [], []

  # find the keys representing the components of the date
  attributes.each_key {|k| keys << k if k.start_with?(property) }

  # assemble the date components in the right order and write to the params
  keys.sort.each { |k| values << attributes[k]; attributes.delete(k); }
  attributes[property] = values.join("-") unless values.empty?
end

然后你可以正常进行,一切都会好起来的:

def create
  compose_date(params[:client], "dob")

  @client = Client.new(params[:client])
  ...
end

编辑:起初我忘记了这一点,但我必须做一些额外的工作才能让日期正确存储在数据库中。attr_encrypted gem 总是想要存储字符串,所以如果您的数据不是字符串,那么您需要向它展示如何编组它。

我创建了一个模块来处理数据加密:

module ClientDataEncryption
  def self.included(base)
    base.class_eval do
      attr_encrypted :ssn, :key => "my_ssn_key"
      attr_encrypted :first_name, :last_name, :key => "my_name_key"
      attr_encrypted :dob, :key => "my_dob_key",
                     :marshal => true, :marshaler => DateMarshaler
    end
  end

  class DateMarshaler
    def self.dump(date)
      # if our "date" is already a string, don't try to convert it
      date.is_a?(String) ? date : date.to_s(:db)
    end

    def self.load(date_string)
      Date.parse(date_string)
    end
  end
end

然后将其包含在我的客户端模型中。

于 2014-05-02T21:40:17.043 回答
0

我正在写一份贷款申请表,并且attr_encrypted在我Owner的模型date_of_birth属性上遇到了同样的问题,这导致我来到这里。我发现 Wally Altman 的解决方案几乎是完美的,只需在我的应用程序中进行一些必要的更改:

  • 以嵌套形式使用它
  • 强大的参数
  • 多个模型实例

我逐字复制了DateMarshalerandcompose_date()方法,然后在我的控制器中添加了一个循环,该循环遍历Owner我们在这里编辑的所有对象。

def resource_params
  params[:loan_application][:owners_attributes].each do |owner| 
    compose_date(owner[1], 'date_of_birth')
    # If there were more fields that needed this I'd put them here
  end
  params.require(:loan_application).permit(:owners_attributes =>
    [ # Regular strong params stuff here ])
end

它在任何数量的嵌套模型上都像一个魅力!

于 2015-03-30T14:40:56.877 回答