Representers: `defaults` block is lost in nested declarations
Complete Description of Issue
Due to legacy design, we want to use the non-strict behavior for as: for property-names, allowing underscores.
Following the Documentation I implemented a representer with the default set to strict: false.
require "roar/json"
require "roar/json/json_api"
class RuleRepresenter < Roar::Decorator
include Roar::JSON::JSONAPI.resource :rules
defaults do |name, _|
{ as: JSONAPI::MemberName.call(name, strict: false) }
end
attributes do
property :chain_id
property :name
property :event_type
end
end
However, the output was hyphenated!
[{:id=>"1c9c618a-86ad-437f-b3dd-50dd5a3e290f", :attributes=>{:"chain-id"=>"072bb8ca-a7c7-4408-b5f1-831d7277f676", :"event-type"=>"transactions"}, :type=>"rules"}]
I was able to workaround by changing my Representer. I placed the defaults block inside of the attributes block.
require "roar/json"
require "roar/json/json_api"
class RuleRepresenter < Roar::Decorator
include Roar::JSON::JSONAPI.resource :rules
attributes do
defaults do |name, _|
{ as: JSONAPI::MemberName.call(name, strict: false) }
end
property :chain_id
property :name
property :event_type
end
end
Steps to reproduce
Create a representer which sets a defaults block like so:
defaults do |name, _|
{ as: JSONAPI::MemberName.call(name, strict: false) }
end
and has attributes
attributes do
property :name
end
Expected behavior
The attributes should be allowed to pass the non-strict conversion and remain underscored.
Actual behavior
Attributes are hyphenated.
System configuration
Roar version: 1.1.0
Roar JSONAPI version: 0.0.3
Declarative version: 0.0.9
During research, I found many things I didn't understand. Please excuse my ignorance.
-
attributes->Roar::JSON::JSONAPI::Declarative, sets theinherit: trueproperty, presumably so you can have multiple attributes blocks and they merge together. -
nested-> When a block is passed, theoptions[:_base]is set toDecorator.default_nested_class, which is just an baseRepresentable::Decorator. At this point,selfis actually stillRuleRepresenter. - Several steps omitted...
-
Declarative::Definitions::Definition#addCalled withattributes, options and the block. Here it extracts some properties, calls the_defaultspipeline, and then calls the nested builder with the_base, name, and block. -
Declarative::Schema::DSL::NestedBuilder (proc)is called, whereinselfisDeclarative::Schema::DSL. No context anymore here, except what was provided inoptions. which is provided for that purpose. This proc begins withClass.new(options[:_base]), which extends theRepresentable::Decoratorsupplied above. Then a block is evaluated which adds the features from the options context, and finally the block isclass_evald. The evaluation offeaturewith theRoar::JSON::JSONAPI::Defaultsfeature sets up@optionswith a fresh set, and theoptions[:_defaults]from the parent is not used here. There's no way to set the options. There's no way to access the@dynamic_optionsblock ofoptions[:_defaults]either. I can't determine if there's some means by which tomergewithout hacking too much further.
Now, if you were to change Roar::JSON::JSONAPI::Declarative to pass the private option _defaults, then those configurations would be available inside of Declarative::Definitions::Definition#add. However, getting it merged inside of Declarative::Schema::DSL::NestedBuilder is beyond me at this time.
@apotonick we should discuss making ::Declarative::Schema::DSL::NestedBuilder inherit defaults (same issue as https://github.com/trailblazer/roar/issues/173#issuecomment-161547989, #13)
Is anyone looking into this? Is this gem still maintained?
Is there anyway to help solve this issue?
Hey @myabc - any ideas?
Sorry @GustavoTango I am not maintaining this gem.