ruby on rails - Filtering fields from ActiveRecord/ActiveModel JSON output (by magic!) -
i want filter out specific fields activerecord/activemodel classes when outputting json.
the straightforward way overriding as_json
, perhaps so:
def as_json (options = nil) options ||= {} super(options.deep_merge({:except => filter_attributes})) end def filter_attributes [:password_digest, :some_attribute] end
this works, it's little verbose , lends not being dry pretty fast. thought nice declare filtered properties magical class method. example:
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
the problem getting deal inheritance properly. let's subclass user:
class secretiveuser < user filter_json :some_attribute, :another_attribute #... end
logically, makes sense filter out :some_attribute
, :another_attribute
, , :password_digest
.
however, filter attributes declared on class. desired end, tried call super
within filter_attributes
, failed. came this, , it's hack.
def filter_attributes if superclass.respond_to?(:filter_attributes) superclass.filter_attributes + @filter_attributes else @filter_attributes end end
this brittle , not idiomatic, there's "what" i'm trying accomplish. can think of way more correctly (and more elegantly)? thanks!
i think safer solution white-list attributes black-list them. prevent unwanted future attributes added user
or someuser
making json response because forgot add said attributes filter_json
.
you seem looking solution specific inheritance issue. i'm still going point out active_model_serializers, feel saner way manage serialization.
class userserializer < activemodel::serializer attributes :id, :first_name, :last_name end class secretuserserializer < userserializer attributes :secret_attribute, :another_attribute end
given secretuser
s
can do
secretuserserializer.new(s).as_json
and you'll :id
, :first_name
, :last_name
, :secret_attribute
, , :another_attribute
. inheritance works expected.
Comments
Post a Comment