Ruby on rails 从ActiveRecord/ActiveModel JSON输出中筛选字段(通过magic!)
我想在输出JSON时从ActiveRecord/ActiveModel类中过滤掉特定字段 最直接的方法是将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
,可能是这样的:
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