[英]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
这显然是脆弱的而不是惯用的,但是我正在努力实现“什么”。 任何人都可以想到一种更正确的方式(并希望更优雅)吗? 谢谢!
我认为这是一个更安全的 白名单属性解决方案,而不是黑名单。 这将防止添加到User
或SomeUser
不需要的未来属性使其成为您的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.