blueprinter icon indicating copy to clipboard operation
blueprinter copied to clipboard

[With PR][Feature Request] Discard blank attribute

Open jamesst20 opened this issue 1 year ago • 0 comments

PR: https://github.com/procore-oss/blueprinter/pull/425

Is there an existing issue for this?

  • [X] I have searched the existing issues

Is your feature request related to a problem? Please describe

I can talk about my specific use case scenario. I'm using Blueprinter in a Ruby on Rails application. I have created an ApplicationBlueprint that extends Blueprinter::Base and I make all my blueprints extends from that class. It's pretty much the same pattern we use for ActiveRecord or Controllers or ApplicationJob, etc.

For my form validations, I always include in my output an errors field for every record or associations.

Exemple of output

{
  id: 1,
  name: null,
  errors: { name: ["can't be blank"] }
  cars: [
    { id: 1, name: "My super fast car", year: null, errors: [{year: ["can't be blank"}] }
  ]
}

This is done in my ApplicationBlueprint which all my blueprint extends of. A very important note here is that in Rails, calling user.errors will give me all errors of user but also includes all the ones from cars. In this payload, I only have interest in the error of the same 'level' i'm currently blueprinting. In order to do that, I simply reject all errors that contains a dot so my user error are basically this { "name": [...], "cars.year": [...] }.reject(...all attribute with dot)

field(:errors) do |record|
    record.try(:errors)&.as_json&.reject { |attribute| attribute.to_s.include?(".") }.presence
end

Describe the feature you'd like to see implemented

If there are no errors in a record or I am rendering something that doesn't even implement errors as a method, I would like to not render the field at all. I understand there is already a "similar" feature implemented:

if = ->(field_name, obj, _options) { true || false }

however this would force me to compute twice the value of the field to know if I should render it or not like so:

field(:errors, if: ->((_, obj, __) {  obj.try(:errors)&.as_json&.reject { |attribute| attribute.to_s.include?(".") }.present? } ) do |record|
  record.try(:errors)&.as_json&.reject { |attribute| attribute.to_s.include?(".") }.presence
end

What I would like:

field(:errors, discard_nil: true) do |record|
  record.try(:errors)&.as_json&.reject { |attribute| attribute.to_s.include?(".") }.presence
end

jamesst20 avatar Jun 13 '24 13:06 jamesst20