Ruby on rails 从ActiveRecord/ActiveModel JSON输出中筛选字段(通过magic!)

Ruby on rails 从ActiveRecord/ActiveModel JSON输出中筛选字段(通过magic!),ruby-on-rails,ruby,inheritance,activerecord,metaprogramming,Ruby On Rails,Ruby,Inheritance,Activerecord,Metaprogramming,我想在输出JSON时从ActiveRecord/ActiveModel类中过滤掉特定字段 最直接的方法是将重写为_json,可能是这样的: def as_json (options = nil) options ||= {} super(options.deep_merge({:except => filter_attributes})) end def filter_attributes [:password_digest, :some_attribute] end 这是

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

最直接的方法是将
重写为_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
SomeUser
的不需要的属性进入JSON响应,因为您忘记了将所述属性添加到
filter\u JSON

您似乎正在寻找解决特定继承问题的方法。我仍然要指出,因为我觉得这是管理序列化的一种更明智的方法

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

class SecretUserSerializer < UserSerializer
  attributes :secret_attribute, :another_attribute
end

您将获得
:id
:first\u name
:last\u name
:secret\u attribute
,以及
:另一个\u attribute
。继承按预期工作。

哦,实际上我真的很喜欢这个。它安全、优雅,并且使测试更容易。我可能会使用它,即使是与我所看到的表面相关的东西。谢谢认可的。这是一个比我想要的更好的解决方案。关于继承问题,您知道为什么我不能在类方法中调用
super
?是因为它被定义为模块的一部分吗?
def filter_attributes
  if superclass.respond_to?(:filter_attributes)
    superclass.filter_attributes + @filter_attributes
  else
    @filter_attributes
  end
end
class UserSerializer < ActiveModel::Serializer
  attributes :id, :first_name, :last_name
end

class SecretUserSerializer < UserSerializer
  attributes :secret_attribute, :another_attribute
end
SecretUserSerializer.new(s).as_json