Skip to content

Commit

Permalink
Merge beec198 into 9962d0d
Browse files Browse the repository at this point in the history
  • Loading branch information
blanquer committed Feb 18, 2016
2 parents 9962d0d + beec198 commit be400b9
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 9 deletions.
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

0 comments on commit be400b9

Please sign in to comment.