为什么不使用符号而不是字符串来访问Rails模型属性?

时间:2011-10-12 18:57:41

标签: ruby-on-rails ruby model attributes symbols

我需要在数据库更新之前和之后比较一些Rails(2.3.11)模型属性值,所以我首先找到我的记录并将现有属性值保存在哈希中,如下所示:

id = params[:id]
work_effort = WorkEffort.find(id)

ancestor_rollup_fields = {
    :scheduled_completion_date => work_effort.scheduled_completion_date
}

work_effort.update_attributes(params.except(:controller, :action))
#etcetera

注意我坚持使用符号作为哈希键的“最佳实践”。

然后我有一个方法,如果哈希值和模型属性中的值不匹配,则采用模型和哈希来确定可能采取的其他步骤。为了确定这一点,我尝试在每个循环中获取模型属性值,但我最初得到nil:

def rollup_ancestor_updates(work_effort, ancestor_rollup_fields)
    ancestor_rollup_fields.each do |key, value|
        model_val = work_effort.attributes[key] #nil
        #etcetera

在调试上面的内容中,我注意到将字符串硬编码为键:

work_effort.attribute['scheduled_completion_date']

返回所需的值。那么在我的每个块中我尝试了以下它并且它起作用了:

model_val = work_effort.attributes[key.to_s]

有不同的方法吗?对我来说,仅仅3个月的Ruby / Rails经验,使用符号作为散列键就像规定的最佳实践一样令人困惑,但是必须在符号上调用.to_s才能获得模型属性。有没有其他人经历过这个,解决过这个,也被这个混淆了?提前致谢

4 个答案:

答案 0 :(得分:10)

当您在AR实例上调用#attributes时,返回的哈希值具有字符串键,这就是为什么作为哈希索引的符号在您的情况下不起作用的原因。有一个名为Hash的{​​{1}}子类,它自动将符号索引转换为字符串。

在Rails中经常会遇到HashWithIndifferentAccess个实例。一个完美的例子是您在控制器中访问的params变量和查看代码。

尝试使用HashWithIndifferentAccess

真的,它只是做同样的事情,但它在幕后做。

答案 1 :(得分:5)

您可以使用自己的方法覆盖属性方法。

打开WorkEffort类

class WorkEffort
  def attributes
    super.symbolize_keys
  end
end

然后当你调用work_effort.attributes时,你将在哈希中有符号化的键。

答案 2 :(得分:1)

您所有的Rails模型都可以具有符号化的属性名称:

class ApplicationRecord < ActiveRecord::Base
  # ...

  class << self
    def attribute_names(symbols = false)
      return self.attribute_names.map(&:to_sym) if symbols

      super()
    end
  end
end

然后,您可以调用MyModel.attribute_names(symbols = true)并返回[:id, :my_attribute, :updated_at, :created_at, ...],同时仍然允许attribute_names返回字符串。

请注意,you need the parentheses after super可以避免原始定义的函数出现参数错误。

答案 3 :(得分:0)

您可能想要使用:stringify_keys!它遍及Rails代码广泛使用。

def rollup_ancestor_updates(work_effort, ancestor_rollup_fields)
  ancestor_rollup_fields.stringify_keys!.each do |key, value|
    model_val = work_effort.attributes[key]
  end
  #....
end
相关问题