Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call object.dump in rendered for Dumpable instances #27

Merged
merged 2 commits into from
Feb 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

## next

* Ensure we call `object.dump` in Renderer when dumping a Attributor::Hash or collection of Attributor::Hash if no subfields were selected.
* Ensure we call `object.dump` in Renderer when fully dumping an instance (or array of instances) that have the Attributor::Dumpable module (i.e., when no subfields were selected)
* In other words, attributor types (custom or not) will need to include the Attributor::Dumpable module and properly implement the dump instance method to produce the right output with native ruby objects.


## 3.1

Expand Down
13 changes: 11 additions & 2 deletions lib/praxis-blueprints/blueprint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ def self.example(context=nil, **values)


def self.validate(value, context=Attributor::DEFAULT_ROOT_CONTEXT, _attribute=nil)

raise ArgumentError, "Invalid context received (nil) while validating value of type #{self.name}" if context == nil
context = [context] if context.is_a? ::String

Expand Down Expand Up @@ -341,19 +340,29 @@ def render(view_name=nil, context: Attributor::DEFAULT_ROOT_CONTEXT,renderer: Re
def validate(context=Attributor::DEFAULT_ROOT_CONTEXT)
raise ArgumentError, "Invalid context received (nil) while validating value of type #{self.name}" if context == nil
context = [context] if context.is_a? ::String
keys_with_values = []

raise "validation conflict" if @validating
@validating = true

self.class.attributes.each_with_object(Array.new) do |(sub_attribute_name, sub_attribute), errors|
errors = []
self.class.attributes.each do |sub_attribute_name, sub_attribute|
sub_context = self.class.generate_subcontext(context,sub_attribute_name)
value = self.send(sub_attribute_name)
unless value.nil?
keys_with_values << sub_attribute_name
end

if value.respond_to?(:validating) # really, it's a thing with sub-attributes
next if value.validating
end
errors.push(*sub_attribute.validate(value, sub_context))
end
self.class.attribute.type.requirements.each do |req|
validation_errors = req.validate(keys_with_values, context)
errors.push(*validation_errors) unless validation_errors.empty?
end
errors
ensure
@validating = false
end
Expand Down
4 changes: 2 additions & 2 deletions lib/praxis-blueprints/renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def render(object, fields, view=nil, context: Attributor::DEFAULT_ROOT_CONTEXT)
def _render(object, fields, view=nil, context: Attributor::DEFAULT_ROOT_CONTEXT)
if fields == true
return case object
when Attributor::Hash
when Attributor::Dumpable
object.dump
else
object
Expand All @@ -82,7 +82,7 @@ def _render(object, fields, view=nil, context: Attributor::DEFAULT_ROOT_CONTEXT)

if subfields == true
hash[key] = case value
when Attributor::Hash
when Attributor::Dumpable
value.dump
else
value
Expand Down
2 changes: 1 addition & 1 deletion praxis-blueprints.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ it results in a structured hash instead of an encoded string. Blueprints can aut
spec.require_paths = ["lib"]

spec.add_runtime_dependency(%q<randexp>, ["~> 0"])
spec.add_runtime_dependency(%q<attributor>, [">= 4.2"])
spec.add_runtime_dependency(%q<attributor>, [">= 5.0.2"])
spec.add_runtime_dependency(%q<activesupport>, [">= 3"])

spec.add_development_dependency "bundler", "~> 1.6"
Expand Down
33 changes: 30 additions & 3 deletions spec/praxis-blueprints/renderer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@

let(:address) { Address.example }
let(:prior_addresses) { 2.times.collect { Address.example } }
let(:alias_one) { FullName.example }
let(:alias_two) { FullName.example }
let(:aliases) { [alias_one, alias_two] }
let(:metadata_hash) { { something: 'here' } }
let(:metadata) { Attributor::Hash.load( metadata_hash ) }

let(:person) do
Person.example(
address: address,
email: nil,
prior_addresses: prior_addresses,
alive: false,
work_address: nil
work_address: nil,
aliases: aliases,
metadata: metadata
)
end

Expand All @@ -27,7 +35,9 @@
},
prior_addresses: [{name: true}],
work_address: true,
alive: true
alive: true,
metadata: true,
aliases: [true]
}
end

Expand All @@ -36,7 +46,7 @@
subject(:output) { renderer.render(person, fields) }

it 'renders existing attributes' do
output.keys.should match_array([:name, :full_name, :alive, :address, :prior_addresses])
output.keys.should match_array([:name, :full_name, :alive, :address, :prior_addresses, :metadata, :aliases])

output[:name].should eq person.name
output[:full_name].should eq({first: person.full_name.first, last: person.full_name.last})
Expand All @@ -50,6 +60,23 @@

expected_prior_addresses = prior_addresses.collect { |addr| {name: addr.name} }
output[:prior_addresses].should match_array(expected_prior_addresses)

expected_aliases = aliases.collect { |the_alias| the_alias.dump }
output[:aliases].should match_array( expected_aliases )

output[:metadata].should eq( metadata.dump )
end

context 'calls dump for non-Blueprint, but still Dumpable instances' do
it 'when rendering them in full as array members' do
alias_one.should_receive(:dump).and_call_original
output[:aliases].first.should eq( first: alias_one.first, last: alias_one.last )
end
it 'when rendering them in full as leaf object' do
metadata.should_receive(:dump).and_call_original
output[:metadata].should eq( metadata_hash )
end

end

it 'does not render attributes with nil values' do
Expand Down
1 change: 1 addition & 0 deletions spec/support/spec_blueprints.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Person < Praxis::Blueprint
attribute :alive, Attributor::Boolean, default: true
attribute :myself, Person
attribute :friends, Attributor::Collection.of(Person)
attribute :metadata, Attributor::Hash
end

view :default do
Expand Down