Rails 5 动态添加非持久性ActiveRecord属性

Rails 5 add non persistent ActiveRecord attributes dynamically

我有一个 Rails 2.3 应用我想升级到 Rails 5.

在我的一些模型中有非持久属性,我可以这样在我的控制器中读写:

  r_v = Model.new
  r_v[:count_all_bqu] = 0
  r_v[:count_all_bsk] = 0
  r_v[:count_all_bmd] = 0

我更改了结构,因为某些原因 Rails 5 不再处理它。

所以,我在我的模型中创建了 attr_accessors:

  attr_accessor :count_all_bqu
  attr_accessor :count_all_bsk
  attr_accessor :count_all_bmd

并将上面的行替换为这些行:

  r_v = Model.new
  r_v.count_all_bqu = 0
  r_v.count_all_bsk = 0
  r_v.count_all_bmd = 0  

到目前为止,没问题。

但也有这样的:

  for r in Model.where(condition)
    r_v["count_#{r.b_id}_erg_bst"] = 0
    ...

如何将 "count_#{r.b_id}_erg_bst" 转换为非持久属性?

虽然我确信还有更多 ActiveModelRoR Guides, API - 但它可能不是 ActiveModel 而是类似的模块)方法,使用普通的 Ruby 你会这样做:

r_v.send("count_#{r.b_id}_erg_bst=", 0)

基本上,您 "call" 方法 count_..._erg...=(分配局部变量的方法,由 attr_accessor 定义)和参数 0.

对于 r.bid == 'my' 它与调用 r_v.count_my_erg_bst= 0 相同。

请注意,只有当 attr_accessor :count_my_erg_bst 是您的 class 定义的一部分时,这才有效。

否则,您可以使用 rv.instance_eval { @count_my_erg_bst = 0 } 之类的东西进行更多元编程,或者,因为您需要字符串插值 rv.instance_eval " @count_#{r.bid}_erg_bst = 0 "

注意安全隐患! 如果用户提供 r.bid,它可能是 "a = 1; system("rm -rf /");" 或其他有害代码!