【问题标题】:How to add a virtual attribute to a model in Ruby on Rails?如何在 Ruby on Rails 中为模型添加虚拟属性?
【发布时间】:2015-11-16 01:56:34
【问题描述】:

我正在开发一个 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 属性。我还想通过此属性过滤消息。

我不知道如何才能做到这一点。

【问题讨论】:

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


    【解决方案1】:

    Ruby 实际上允许您以这种方式创建虚拟属性,这样您就不必手动创建 getter 和 setter 方法:

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

    你也可以传递多个参数:

    attr_accessor :palindrome, :foo, :bar
    

    documentation for it 不是最棒的。

    【讨论】:

    • @RajaRaviVarma:你在第一句话中混合了 rails 和 ruby​​ 自己:)。我会修复答案。
    【解决方案2】:

    在您的模型中,您可以通过这种方式为您的虚拟属性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 属性列入白名单,以便能够批量分配 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,您可以在 MessageSerializer 中拥有:attribute palindrome,然后 palindrome 将公开给 JSON API。

    【讨论】:

    • 好的,谢谢。我有两个问题。首先,我不希望这个属性是可写的,因为它只取决于另一个属性的值。其次,self[:palindrome] 的评估结果是什么?
    • 如果您不需要编写属性值,那么您不需要设置方法并将其列入强参数定义中。 self[:palindrome] 将为您提供 self 的回文值,这是您的模型对象的实例。这类似于model_instance.palindrome。希望现在清楚。如果您有任何其他问题,请告诉我。
    • 虚拟属性不会自动出现在参数列表中。但是,他应该可以像这样通过 Rails 控制台访问它:model_instance.palindrome。此外,他可以在他的 JSON API 中公开这个虚拟属性,例如,如果使用 Active Model Serializer,他可以在他的 MessageSerializer 中拥有:attribute palindrome,然后它将被公开给 ​​JSON API。
    • 谢谢。它现在可以工作了,我可以向 JSON API 公开。我想知道如何将它也暴露给 XML API?
    • 这个截屏视频值得一看gorails.com/episodes/…
    【解决方案3】:

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

    attribute :palindrome, :boolean
    

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

    【讨论】:

      猜你喜欢
      • 2013-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多