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