如何在Ruby on Rails中为模型添加虚拟属性?

时间:2015-11-16 01:56:34

标签: ruby-on-rails ruby ruby-on-rails-4 activeadmin

我正在研究RubyonRails / ActiveAdmin应用程序。我的RoR版本是4.2.5,AA版本是1.0.0。我的模型Message如下所示。

class Message < ActiveRecord::Base

  belongs_to :user
  validates :user, :content, presence: true

  def palindrome
    # return true/false
  end

end

如您所见,我希望拥有一个只读属性palindrome,该属性仅取决于邮件的content。我希望将此属性视为与普通属性完全相同。通常,我的意思是当我通过rails console或请求json格式的邮件检索邮件时,我希望在列表中看到palindrome属性。我还希望通过此属性对消息进行过滤。

我不确定如何实现这一目标。

3 个答案:

答案 0 :(得分:22)

Ruby实际上允许您以这种方式创建虚拟属性,这使您无需手动创建getter和setter方法:

attr_reader   :palindrome #getter
attr_writer   :palindrome #setter
attr_accessor :palindrome #both

您也可以传递多个参数:

attr_accessor :palindrome, :foo, :bar

documentation for it并不是最伟大的。

答案 1 :(得分:12)

在您的模型中,您可以通过以下方式为虚拟属性palindrome属性编写属性访问器(读取器/写入器):

# attr_reader
def palindrome
  self[:palindrome]
end

# attr_writer
def palindrome=(val)
  self[:palindrome] = val
end

# virtual attribute
def palindrome
  #return true/false
end

而且,当您使用Rails 4时,您必须将palindrome属性列入控制器内强param定义中的任何其他模型属性,以便能够批量分配palindrome的值。像这样:

# your_controller.rb
private

def your_model_params
  params.require(:message).permit(:palindrome)
end

看看这个RailsCast on Virtual Attributes。虽然,它有点旧,但对概念有用。

注意:

虚拟属性不会自动显示在参数列表中。但是,您应该可以通过Rails控制台访问它,如下所示:Message.new.palindrome。此外,您可以在JSON API中公开此虚拟属性,例如,如果您使用的是Active Model Serializer,则可以在attribute palindrome中使用MessageSerializer,然后palindrome暴露给JSON API。

答案 2 :(得分:4)

从 Rails 5 开始,您还可以像这样设置虚拟属性:

attribute :palindrome, :boolean

它会自动将属性转换为指定的类型,这在值来自表单时很有用。 This GoRails video 展示了使用 attr_accessorattribute 方法的一些非常好的示例。 The documentation 还包括一些示例。