【问题标题】:Extending ActiveModel::Serializer with custom attributes method使用自定义属性方法扩展 ActiveModel::Serializer
【发布时间】:2018-08-31 19:26:14
【问题描述】:

我正在尝试创建我自己的attributes 方法,称为secure_attributes,在该方法中我将属性数组和授权用户查看这些属性所需的最低级别传递给它。我将授权用户的当前级别作为 instance_option 传递。我想扩展 Serializer 类,以便可以在多个序列化程序中使用此方法,但我遇到了问题。

这是我目前所拥有的:

config/initializers/secure_attributes.rb

module ActiveModel
  class Serializer
    def self.secure_attributes(attributes={}, minimum_level)

      attributes.delete_if {|attr| attr == :attribute_name } unless has_access?(minimum_level)

      attributes.each_with_object({}) do |name, hash|
        unless self.class._fragmented
          hash[name] = send(name)
        else
          hash[name] = self.class._fragmented.public_send(name)
        end
      end
    end
  end
end

然后在单个序列化程序中我有这样的事情:

secure_attributes([:id, :name, :password_hint], :guest)

然后

  def has_access?(minimum_level=nil)
    return false unless minimum_level
    return true # based on a bunch of logic...
  end

但显然secure_attributes 看不到has_access? 方法,如果我将has_access 放在Serializer 类中,它就无法访问instance_options。

知道如何完成我需要的吗?

【问题讨论】:

  • instance_option 是什么意思?
  • 您的问题是:您尝试访问类方法中的实例方法。您需要定义 self.has_access?(minimum_level=nil) 而不是 has_access?使您的代码正常工作。也许您想更多地解释您的用例 - 然后我可以提出一些更详细的解决方案。你想用你的逻辑覆盖什么方法调用?
  • 我认为您只需将secure_attributes 缓存在类级实例变量Hash 中,并为您要使用/覆盖它的方法编写一个钩子(检查此类实例变量)。因此,您要放入类方法的逻辑 - 必须移至实例级别。
  • 在我深入研究 ActiveModel::Serializer 之后 - 我认为你想覆盖初始化。

标签: ruby-on-rails active-model-serializers


【解决方案1】:

也许您想进行以下操作 - 但我仍然不明白您的真正目的,因为您从未对属性做过任何事情,而是调用它们:

module ActiveRecord
  class JoshsSerializer < Serializer
    class << self
      def secure_attributes(attributes={}, minimum_level)
        @secure_attributes = attributes
        @minimum_level = minimum_level
      end
      attr_reader :minimum_level, :secure_attributes
    end

    def initialize(attr, options)
      super attr, options
      secure_attributes = self.class.secure_attributes.dup
      secure_attributes.delete :attribute_name unless has_access?(self.class.minimum_level)
      secure_attributes.each_with_object({}) do |name, hash|
      if self.class._fragmented
        hash[name] = self.class._fragmented.public_send(name)
      else
        hash[name] = send(name)
      end
    end

    def has_access?(minimum_level=nil)
      return false unless minimum_level
      return true # based on a bunch of logic...
    end
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-09
    • 1970-01-01
    • 2016-07-21
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    相关资源
    最近更新 更多