繁体   English   中英

从ActiveRecord / ActiveModel JSON输出中过滤字段(通过魔术!)

[英]Filtering fields from ActiveRecord/ActiveModel JSON output (by magic!)

我想在输出JSON时从ActiveRecord / ActiveModel类中过滤掉特定字段。

最简单的方法就是覆盖as_json ,也许是这样:

def as_json (options = nil)
  options ||= {}
  super(options.deep_merge({:except => filter_attributes}))
end

def filter_attributes
  [:password_digest, :some_attribute]
end

这是有效的,但它有点冗长,并且有助于不快速干燥。 我认为用一个神奇的类方法声明过滤的属性会很好。 例如:

class User < ActiveRecord::Base
  include FilterJson

  has_secure_password
  filter_json :password_digest
  #...
end

module FilterJson
  extend ActiveSupport::Concern

  module ClassMethods
    def filter_json (*attributes)
      (@filter_attributes ||= Set.new).merge(attributes.map(&:to_s))
    end

    def filter_attributes
      @filter_attributes
    end
  end

  def as_json (options = nil)
    options ||= {}
    super(options.deep_merge({:except => self.class.filter_attributes.to_a}))
  end
end

这个问题是让它正确处理继承。 假设我是子类User:

class SecretiveUser < User
  filter_json :some_attribute, :another_attribute
  #...
end

从逻辑上讲,过滤掉:some_attribute:another_attribute以及:password_digest是有意义的。

但是,这只会过滤在类上声明的属性。 为了达到预期的目的,我尝试在filter_attributes调用super ,但是失败了。 我想出了这个,这是一个黑客。

def filter_attributes
  if superclass.respond_to?(:filter_attributes)
    superclass.filter_attributes + @filter_attributes
  else
    @filter_attributes
  end
end

这显然是脆弱的而不是惯用的,但是我正在努力实现“什么”。 任何人都可以想到一种更正确的方式(并希望更优雅)吗? 谢谢!

我认为这是一个更安全的 白名单属性解决方案,而不是黑名单。 这将防止添加到UserSomeUser不需要的未来属性使其成为您的JSON响应,因为您忘记将所述属性添加到filter_json

您似乎正在寻找特定继承问题的解决方案。 我仍然会指出active_model_serializers ,因为我觉得它是管理序列化的一种更健全的方式。

class UserSerializer < ActiveModel::Serializer
  attributes :id, :first_name, :last_name
end

class SecretUserSerializer < UserSerializer
  attributes :secret_attribute, :another_attribute
end

鉴于一些SecretUser s ,你可以做

SecretUserSerializer.new(s).as_json

你会得到:id:first_name:last_name:secret_attribute ,和:another_attribute 继承按预期工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM