From 3cb4fde24bcec098bc46a4d6de1beacc6c0b4deb Mon Sep 17 00:00:00 2001 From: James St-Pierre Date: Thu, 13 Jun 2024 10:38:00 -0400 Subject: [PATCH 1/6] Feature: Discard nil value field Signed-off-by: James St-Pierre --- lib/blueprinter/helpers/base_helpers.rb | 6 ++++- .../shared/base_render_examples.rb | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/blueprinter/helpers/base_helpers.rb b/lib/blueprinter/helpers/base_helpers.rb index f87960cc..ec3e7448 100644 --- a/lib/blueprinter/helpers/base_helpers.rb +++ b/lib/blueprinter/helpers/base_helpers.rb @@ -48,7 +48,11 @@ def object_to_hash(object, view_name:, local_options:) result_hash = view_collection.fields_for(view_name).each_with_object({}) do |field, hash| next if field.skip?(field.name, object, local_options) - hash[field.name] = field.extract(object, local_options) + value = field.extract(object, local_options) + + next if value.nil? && field.options[:discard_nil] + + hash[field.name] = value end view_collection.transformers(view_name).each do |transformer| transformer.transform(result_hash, object, local_options) diff --git a/spec/integrations/shared/base_render_examples.rb b/spec/integrations/shared/base_render_examples.rb index 6113ffcc..fdf2864d 100644 --- a/spec/integrations/shared/base_render_examples.rb +++ b/spec/integrations/shared/base_render_examples.rb @@ -50,6 +50,33 @@ it('returns json with a renamed field') { should eq(result) } end + context 'Given blueprint has ::fields with :discard_nil argument' do + context 'Given :discard_nil argument is true' do + let(:result) { '{"first_name":"Meg"}' } + let(:blueprint) do + Class.new(Blueprinter::Base) do + field :first_name, discard_nil: true + field :my_field, discard_nil: true do + nil + end + end + end + it('returns json without nil value fields') { should eq(result) } + end + context 'Given :discard_nil argument is false' do + let(:result) { '{"first_name":"Meg","my_field":null}' } + let(:blueprint) do + Class.new(Blueprinter::Base) do + field :first_name, discard_nil: false + field :my_field, discard_nil: false do + nil + end + end + end + it('returns json without nil value fields') { should eq(result) } + end + end + context 'non-default extractor' do let(:extractor) do Class.new(Blueprinter::Extractor) do From 32cd4c020895e548eeac5c49d540922f4a7830d4 Mon Sep 17 00:00:00 2001 From: James St-Pierre Date: Tue, 18 Jun 2024 11:11:05 -0400 Subject: [PATCH 2/6] Update README, Rename to exclude_if_nil, Update specs. Co-authored-by: Jake Sheehy Signed-off-by: James St-Pierre --- README.md | 30 +++++++++++++++++++ lib/blueprinter/helpers/base_helpers.rb | 2 +- .../shared/base_render_examples.rb | 14 ++++----- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 35ae3b6f..cfa2b284 100644 --- a/README.md +++ b/README.md @@ -694,6 +694,36 @@ _NOTE:_ The field-level setting overrides the global config setting (for the fie +
+ + + +By default, fields with `nil` values are included when rendering. You can override this behavior by setting `:exclude_if_nil: true` in the field definition. + +Usage: + +```ruby +class UserBlueprint < Blueprinter::Base + identifier :uuid + + field :name + field :birthday, exclude_if_nil: true +end + +user = User.new(name: 'John Doe') +puts UserBlueprint.render(user) +``` + +Output: + +```json +{ + "name": "John Doe" +} +``` + +
+
Custom Formatting for Dates and Times diff --git a/lib/blueprinter/helpers/base_helpers.rb b/lib/blueprinter/helpers/base_helpers.rb index ec3e7448..4eb98976 100644 --- a/lib/blueprinter/helpers/base_helpers.rb +++ b/lib/blueprinter/helpers/base_helpers.rb @@ -50,7 +50,7 @@ def object_to_hash(object, view_name:, local_options:) value = field.extract(object, local_options) - next if value.nil? && field.options[:discard_nil] + next if value.nil? && field.options[:exclude_if_nil] hash[field.name] = value end diff --git a/spec/integrations/shared/base_render_examples.rb b/spec/integrations/shared/base_render_examples.rb index fdf2864d..c4f6032b 100644 --- a/spec/integrations/shared/base_render_examples.rb +++ b/spec/integrations/shared/base_render_examples.rb @@ -50,25 +50,25 @@ it('returns json with a renamed field') { should eq(result) } end - context 'Given blueprint has ::fields with :discard_nil argument' do - context 'Given :discard_nil argument is true' do + context 'Given blueprint has ::fields with :exclude_if_nil set' do + context 'when :exclude_if_nil is true' do let(:result) { '{"first_name":"Meg"}' } let(:blueprint) do Class.new(Blueprinter::Base) do - field :first_name, discard_nil: true - field :my_field, discard_nil: true do + field :first_name, exclude_if_nil: true + field :my_field, exclude_if_nil: true do nil end end end it('returns json without nil value fields') { should eq(result) } end - context 'Given :discard_nil argument is false' do + context 'when :exclude_if_nil is false' do let(:result) { '{"first_name":"Meg","my_field":null}' } let(:blueprint) do Class.new(Blueprinter::Base) do - field :first_name, discard_nil: false - field :my_field, discard_nil: false do + field :first_name, exclude_if_nil: false + field :my_field, exclude_if_nil: false do nil end end From 1a70e3e0b911c0fc1309da3ff28e9e0ca79d5abf Mon Sep 17 00:00:00 2001 From: James St-Pierre Date: Tue, 18 Jun 2024 11:40:30 -0400 Subject: [PATCH 3/6] Spec: Move spec outside base_render_exemples as requested Signed-off-by: James St-Pierre --- spec/integrations/base_spec.rb | 24 +++++++++++++++++ .../shared/base_render_examples.rb | 27 ------------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/spec/integrations/base_spec.rb b/spec/integrations/base_spec.rb index c6db132a..6bbcdbac 100644 --- a/spec/integrations/base_spec.rb +++ b/spec/integrations/base_spec.rb @@ -82,6 +82,30 @@ end end + context 'Given exclude_if_nil is passed' do + let(:obj) { OpenStruct.new(obj_hash.merge(nil_attribute: nil)) } + + context 'and exclude_if_nil is true' do + let(:blueprint) do + Class.new(Blueprinter::Base) do + field :nil_attribute, exclude_if_nil: true + end + end + let(:result) { '{}' } + it { expect(blueprint.render(obj)).to eq(result) } + end + + context 'and exclude_if_nil is false' do + let(:blueprint) do + Class.new(Blueprinter::Base) do + field :nil_attribute, exclude_if_nil: false + end + end + let(:result) { '{"nil_attribute":null}' } + it { expect(blueprint.render(obj)).to eq(result) } + end + end + context 'Inside Rails project' do include FactoryBot::Syntax::Methods let(:obj) { create(:user) } diff --git a/spec/integrations/shared/base_render_examples.rb b/spec/integrations/shared/base_render_examples.rb index c4f6032b..6113ffcc 100644 --- a/spec/integrations/shared/base_render_examples.rb +++ b/spec/integrations/shared/base_render_examples.rb @@ -50,33 +50,6 @@ it('returns json with a renamed field') { should eq(result) } end - context 'Given blueprint has ::fields with :exclude_if_nil set' do - context 'when :exclude_if_nil is true' do - let(:result) { '{"first_name":"Meg"}' } - let(:blueprint) do - Class.new(Blueprinter::Base) do - field :first_name, exclude_if_nil: true - field :my_field, exclude_if_nil: true do - nil - end - end - end - it('returns json without nil value fields') { should eq(result) } - end - context 'when :exclude_if_nil is false' do - let(:result) { '{"first_name":"Meg","my_field":null}' } - let(:blueprint) do - Class.new(Blueprinter::Base) do - field :first_name, exclude_if_nil: false - field :my_field, exclude_if_nil: false do - nil - end - end - end - it('returns json without nil value fields') { should eq(result) } - end - end - context 'non-default extractor' do let(:extractor) do Class.new(Blueprinter::Extractor) do From cb8af9147a7db37cca05c828417a2717d6e85e1b Mon Sep 17 00:00:00 2001 From: James St-Pierre Date: Tue, 18 Jun 2024 11:51:08 -0400 Subject: [PATCH 4/6] README: Fix tag broken by github suggestion merge Signed-off-by: James St-Pierre --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cfa2b284..9666545c 100644 --- a/README.md +++ b/README.md @@ -695,7 +695,7 @@ _NOTE:_ The field-level setting overrides the global config setting (for the fie
- +Exclude Fields with nil Values By default, fields with `nil` values are included when rendering. You can override this behavior by setting `:exclude_if_nil: true` in the field definition. From 9e77b9837cf1591f2a75d570295936e56aefe320 Mon Sep 17 00:00:00 2001 From: James St-Pierre Date: Sun, 23 Jun 2024 22:05:17 -0400 Subject: [PATCH 5/6] Update spec/integrations/base_spec.rb Co-authored-by: Jake Sheehy Signed-off-by: James St-Pierre --- spec/integrations/base_spec.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/spec/integrations/base_spec.rb b/spec/integrations/base_spec.rb index 6bbcdbac..a9b1b75c 100644 --- a/spec/integrations/base_spec.rb +++ b/spec/integrations/base_spec.rb @@ -83,25 +83,27 @@ end context 'Given exclude_if_nil is passed' do - let(:obj) { OpenStruct.new(obj_hash.merge(nil_attribute: nil)) } + let(:obj) { OpenStruct.new(obj_hash.merge(category: nil, label: 'not nil')) } context 'and exclude_if_nil is true' do let(:blueprint) do Class.new(Blueprinter::Base) do - field :nil_attribute, exclude_if_nil: true + field :category, exclude_if_nil: true + field :label, exclude_if_nil: true end end - let(:result) { '{}' } + let(:result) { '{"label":"not nil"}' } it { expect(blueprint.render(obj)).to eq(result) } end context 'and exclude_if_nil is false' do let(:blueprint) do Class.new(Blueprinter::Base) do - field :nil_attribute, exclude_if_nil: false + field :category, exclude_if_nil: false, + field :label, exclude_if_nil: true end end - let(:result) { '{"nil_attribute":null}' } + let(:result) { '{"category":null,"label":"not nil"}' } it { expect(blueprint.render(obj)).to eq(result) } end end From 04f470538569c57a1b4c78f5816d49c3ff9d2f8d Mon Sep 17 00:00:00 2001 From: James St-Pierre Date: Wed, 10 Jul 2024 11:04:37 -0400 Subject: [PATCH 6/6] Fix specs Signed-off-by: James St-Pierre --- spec/integrations/base_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/integrations/base_spec.rb b/spec/integrations/base_spec.rb index dec22954..7eb95f98 100644 --- a/spec/integrations/base_spec.rb +++ b/spec/integrations/base_spec.rb @@ -99,7 +99,7 @@ context 'and exclude_if_nil is false' do let(:blueprint) do Class.new(Blueprinter::Base) do - field :category, exclude_if_nil: false, + field :category, exclude_if_nil: false field :label, exclude_if_nil: true end end