【问题标题】:attr_encrypted and encrypting dates generated by the date_select form helper由 date_select 表单助手生成的 attr_encrypted 和加密日期
【发布时间】:2014-05-02 15:51:04
【问题描述】:

我是 Rails 新手,我正在使用 Rails 4 和 attr_encrypted gem 来加密一些字段(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_encrypted gem 能够对其进行加密。完成此任务的最佳方法是什么?

【问题讨论】:

    标签: mysql ruby-on-rails ruby encryption attr-encrypted


    【解决方案1】:

    我发现 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
    

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

    【讨论】:

    • 很抱歉这么久才回复,但非常感谢!它完美地工作。近一周我一直试图弄清楚这一点。我唯一要做的就是在编辑客户端时将日期解析回日期,仅此而已。再次感谢。
    【解决方案2】:

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

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

    我逐字复制了DateMarshalercompose_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
    

    它在任何数量的嵌套模型上都非常有效!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多