如何迭代ActiveRecord属性,包括attr_accessor方法

时间:2009-06-14 21:48:07

标签: ruby-on-rails ruby activerecord

我到处寻找优雅的解决方案。基本问题似乎是,在ActiveRecord :: Base中,映射到数据库列的ActiveRecord属性与attr_accessor方法完全不同。

我想做点什么:

model.attribute_names.each do |name|
  # do stuff
end

的方式还包括attr_accessor字段,但不包括任何其他实例方法。我知道这不是内置的,但最优雅的方法是什么?

3 个答案:

答案 0 :(得分:9)

你无法解决这个问题。你可以近似一个黑客攻击,但它不会很好地工作。

model.attribute_names应该为您提供所有ActiveRecord,但attr_accessor字段不是字段。它们只是普通的ruby方法,获取它们的唯一方法是使用model.instance_methods

创意1

你可以model.attribute_names + model.instance_methods,但是你必须过滤掉所有其他正常的红宝石方法initialize, save等,这是不切实际的。

要帮助过滤instance_methods,您可以将它们与model.instance_variables进行匹配(您必须手动考虑实例变量中的@符号),但问题是是实例变量在首次分配之前根本不存在。

创意2

environment.rb中,在加载任何其他内容之前,请在self.attr_accessor中定义您自己的ActiveRecord::Base。然后,这可以包装基础attr_accessor,但也将属性名称保存到私有列表。然后你就可以在以后退出这个列表了。但是我建议不要这样做......像attr_accessor这样的猴子修补核心语言设施可以保证给你带来很大的痛苦。

创意3

custom_attr_accessor中定义您自己的ActiveRecord::Base,其功能与Idea 2相同,并在您希望能够检索属性名称的代码中使用它。这样会很安全,因为您不会再破坏内置的attr_accessor方法,但是您必须更改所有代码才能使用custom_attr_accessor

总的来说,您想要做什么,需要了解所有attr_accessor字段?如果可以,请尝试从不同角度查看问题。

答案 1 :(得分:3)

我来到这里寻找做同样的事情,并且由于猎户座的回答,发现这是错误的做法。

包括其他人的用例与我的相似,这是我的解决方案。在使用ActiveRecord查询模型后,我使用attr_accessor为模型添加了额外的属性。然后我想把结果输出为JSON等。

更好的解决方案是首先将模型从ActiveRecord转换为常规哈希,然后将attr_accessor属性添加为常规哈希键。

示例:

model_hash = model_from_activerecord.attributes.to_options
model_hash[:key] = value

答案 2 :(得分:0)

我为自己提出的解决方案建立在猎户座爱德华兹的回答之上。

代码:

klass_attributes = klass.column_names + klass.instance_methods(false). map(&:to_s).keep_if{|a| a.include?('=')}.map{|a| a.sub('=', '')}

细分:

klass.instance_methods(false)只返回实例方法,而不是继承方法。

map(&:to_s)将符号数组转换为字符串数组,以便我们可以使用include?方法。还需要与column_names返回的字符串数组合并。

keep_if{|a| a.include?('=')}将删除数组中没有等号的所有字符串。这很重要,因为我注意到attr_accessor属性都有'='。例如:'app_url'vs'login_url ='

map{|a| a.sub('=', '')}是最后一段,然后从数组中的每个字符串中删除'='。

最终得到一个表示属性的字符串数组,包括attr_accessor属性。

相关问题