Ruby/Rails将字符串转换为类属性

4
假设我有一个名为Article的类,它包含以下内容:
class Article

  attr_accessor :title, :author

  def initialize(title, author)
    @title = title
    @author= author
  end

end

此外,变量atrib是一个包含属性名称的String。我该如何将这个字符串转换为一个变量,以便用作getter?
a = Article.new
atrib='title'
puts a.eval(atrib)     # <---- I want to do this

扩展

假设我现在有一组文章的Array,我想按标题排序。 是否有一种使用&进行压缩版本的方法,例如:

col = Article[0..10]
sorted_one = col.sort_by{|a| a.try('title') }   #This works
sorted_two = col.sort_by(&:try('title'))   #This does not work

6
你尝试过 a.send(atrib.to_sym) 吗? - engineersmnky
@engineersmnky 那确实有效,谢谢! - lllllll
1
to_sym 实际上并不是必需的,字符串也可以接受,因此您可以调用 a.send(atrib) - engineersmnky
为什么不使用 a.title.. ? - Arup Rakshit
@ArupRakshit 我将其简化为一个简单的示例。棘手的问题是,我已经将属性名称存储到字符串中。 - lllllll
你的类是 ActiveRecord 吗? - Stefan
2个回答

6
你可以使用send或者instance_variable_get
a = Article.new 'Asdf', 'Coco'
a.pubic_send(:title) # (Recommended) Tries to call a public method named 'title'. Can raise NoMethodError
=> "Asdf"
# If at rails like your case:
a.try :title # Tries to call 'title' method, returns `nil` if the receiver is `nil` or it does not respond to method 'title'
=> "Asdf"
a.send(:title) # Same, but will work even if the method is private/protected
=> "Asdf"
a.instance_variable_get :@title # Looks for an instance variable, returns nil if one doesn't exist
=> "Asdf"

简短回答你的问题:不是。对于Proc而言,&:symbol 快捷键依赖于 Symbol#to_proc 方法。因此,为了启用该行为,您需要重新定义 Symbol 类中的该方法:

class Symbol
  def to_proc  
    ->(x) { x.instance_eval(self.to_s) }    
  end  
end

[1,2,3].map(&:"to_s.to_i * 10")
=> [10, 20, 30]

1
或者使用.try,这将是一种更优雅的方式。 - pdu
1
@pduersteler很有见地!只适用于Rails。 - lllllll
@nicooga 请查看更新后的帖子,其中包括原始问题的一个子问题。 - lllllll
1
这三种不同方法有什么区别? - timpone
@nicooga,感谢您对扩展部分的回答!我现在明白了。 - lllllll

1

ActiveRecord实例有一个attributes哈希:

a = Article.new(title: 'foo')
#=> <#Article id: nil, title: "foo">

atrib = 'title'
a.attributes[atrib]
#=> "foo"

您可以使用order从数据库中获取排序后的对象:

Article.order('title').first(10)
#=> array of first 10 articles ordered by title

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接