From 83a69012c70678c0f10af1d92cc7a71e5eaeec37 Mon Sep 17 00:00:00 2001 From: Gavin Joyce Date: Tue, 31 May 2016 14:34:36 +0100 Subject: [PATCH] add support for @context[:attribute_whitelist] and @context[:attribute_blacklist] --- lib/restpack_serializer/serializable.rb | 36 +++++++++++++++++++++++ spec/serializable/serializer_spec.rb | 38 +++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/lib/restpack_serializer/serializable.rb b/lib/restpack_serializer/serializable.rb index 3f66f02..5822e53 100644 --- a/lib/restpack_serializer/serializable.rb +++ b/lib/restpack_serializer/serializable.rb @@ -37,6 +37,7 @@ def as_json(model, context = {}) return model.map { |item| as_json(item, context) } end + apply_whitelist_and_blacklist(context) @model, @context = model, context data = {} @@ -72,6 +73,41 @@ def add_custom_attributes(data) data.merge!(custom) if custom end + def apply_whitelist_and_blacklist(context) + blacklist = context[:attribute_blacklist] + whitelist = context[:attribute_whitelist] + + if blacklist.present? && whitelist.present? + raise ArgumentError.new "the context can't define both an `attribute_whitelist` and an `attribute_blacklist`" + end + + if blacklist.present? + blacklist = csv_to_symbol_array(blacklist) + self.class.serializable_attributes.each do |key, value| + if blacklist.include? key + context[value[:include_method_name]] = false + end + end + end + + if whitelist.present? + whitelist = csv_to_symbol_array(whitelist) + self.class.serializable_attributes.each do |key, value| + unless whitelist.include? key + context[value[:include_method_name]] = false + end + end + end + end + + def csv_to_symbol_array(maybe_csv) + if maybe_csv.is_a? String + maybe_csv.split(',').map {|a| a.strip.to_sym} + else + maybe_csv + end + end + def add_links(model, data) self.class.associations.each do |association| data[:links] ||= {} diff --git a/spec/serializable/serializer_spec.rb b/spec/serializable/serializer_spec.rb index f667b26..747d2ab 100644 --- a/spec/serializable/serializer_spec.rb +++ b/spec/serializable/serializer_spec.rb @@ -198,6 +198,44 @@ def custom_attributes ] } end + + it "excludes a blacklist of attributes if specified as an array" do + serializer.as_json(person, { attribute_blacklist: [:name, :description] }).should == { + id: '123', + href: '/people/123', + custom_key: 'custom value for model id 123' + } + end + + it "excludes a blacklist of attributes if specified as a string" do + serializer.as_json(person, { attribute_blacklist: 'name, description' }).should == { + id: '123', + href: '/people/123', + custom_key: 'custom value for model id 123' + } + end + + it "includes a whitelist of attributes if specified as an array" do + serializer.as_json(person, { attribute_whitelist: [:name, :description] }).should == { + name: 'Gavin', + description: 'This is person #123', + custom_key: 'custom value for model id 123' + } + end + + it "includes a whitelist of attributes if specified as a string" do + serializer.as_json(person, { attribute_whitelist: 'name, description' }).should == { + name: 'Gavin', + description: 'This is person #123', + custom_key: 'custom value for model id 123' + } + end + + it "raises an exception if both the whitelist and blacklist are provided" do + expect do + serializer.as_json(person, { attribute_whitelist: [:name], attribute_blacklist: [:id] }) + end.to raise_error(ArgumentError, "the context can't define both an `attribute_whitelist` and an `attribute_blacklist`") + end end context "links" do