【问题标题】:Rails ActiveRecord writes encrypted attribute but does not read itRails ActiveRecord 写入加密属性但不读取它
【发布时间】:2020-09-25 08:08:16
【问题描述】:

我有一个由patients Postgres 数据库表支持的Patient 模型。它有一个属性national_id,由密码箱gem 加密,因此存储在national_id_ciphertext 列中。这个属性保存/更新很好,我可以在数据库中验证这一点。

但是当我读回这条记录时,没有包含national_id属性。

Rails 控制台:

pry(main)> p = Patient.find(8)
=> #<Patient id: 8, name: "Øyvind Hansen", address: nil, address_directions: nil, zip: "0667", city: "Oslo", phone_number: "+4712345678", email: "oyvind@test.com", created_at: "2020-09-05 19:41:55", updated_at: "2020-09-05 20:45:46", referral_id: nil>

pry(main)> p.national_id
=> "12345678912"

架构是:

create_table "patients", force: :cascade do |t|
    t.string "name"
    t.string "address"
    t.string "zip"
    t.string "city"
    t.string "phone_number"
    t.string "email"
    t.text "national_id_ciphertext" # Saved, but not retrieved
    t.bigint "referral_id"
    t.index ["referral_id"], name: "index_patients_on_referral_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

密码箱加密的实现非常简单,直接来自the docs的基本示例。

class Patient < ApplicationRecord
    encrypts :national_id
end

知道为什么 Lockbox 创建的 national_id 访问器不包含在可枚举模型属性中吗?

【问题讨论】:

  • national_id 不是 db 列,因此未显示在基本输出中。

标签: ruby-on-rails encryption rails-activerecord ruby-on-rails-6


【解决方案1】:

正如您在自己的测试中所指出的,该值是可用的。 national_id 是对象的可用方法,但不是 DB 属性。您始终可以使用点符号检索它,例如my_patient.national_id 但不是通过哈希表示法

my_patient.national_id
=> "12345678912"

my_patient["national_id"]
=> nil

这通常不是问题,只需使用点符号即可。

如果问题是转成 json,您可以在 json 调用中添加方法...

my_patient.to_json(methods: [:national_id])

或者您可以修改您的 to_json 以始终包含它

class Patient < ActiveRecord
   
  def to_json(options={})
    super options.merge({methods: [:national_id]})
  end

end

【讨论】:

  • 谢谢!是否有任何与此方法等效的方法来确保它包含在基本查找中,例如Patient.find(8, methods: [:national_id)(显然我知道这不起作用,但我试图解释我想要做什么)。
  • 但它是可用的。 my_patient = Patient.find(8); my_patient.name # this returns "Øyvind Hansen"; my_patient.national_id # this returns "12345678912" 你需要的一切都在那里。患者对象是属性和方法的集合,您可以调用其中任何一个。
  • 只需将@patient.national_id 包含在您的节目页面上,它就在那里。
  • 谢谢。我知道它在那里,但是在模型被序列化时它不包括在内,例如在将它作为道具传递给 React 时。
  • 覆盖您的 to_json 方法以将其包含在每个 to_json 调用中...请参阅我修改后答案的最后一部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多