From ed52108cc7ccd039d5db493d1ed682fb38be3d6d Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Sat, 25 Jul 2015 01:27:17 +0200 Subject: [PATCH] validate entities after creation if a validator is defined --- lib/diaspora_federation/entity.rb | 22 +++++++++ .../validators/rules/boolean.rb | 2 +- spec/entities.rb | 10 ++++ spec/lib/diaspora_federation/entity_spec.rb | 48 ++++++++++++++----- 4 files changed, 69 insertions(+), 13 deletions(-) diff --git a/lib/diaspora_federation/entity.rb b/lib/diaspora_federation/entity.rb index cbcda87..1d01224 100644 --- a/lib/diaspora_federation/entity.rb +++ b/lib/diaspora_federation/entity.rb @@ -53,7 +53,9 @@ module DiasporaFederation self.class.default_values.merge(data).each do |k, v| instance_variable_set("@#{k}", nilify(v)) if setable?(k, v) end + freeze + validate end # Returns a Hash representing this Entity (attributes => values) @@ -115,6 +117,22 @@ module DiasporaFederation value end + def validate + validator_name = "DiasporaFederation::Validators::#{self.class.name.split('::').last}Validator" + return unless Validators.const_defined? validator_name + + validator_class = Validators.const_get validator_name + validator = validator_class.new self + raise ValidationError, error_message(validator) unless validator.valid? + end + + def error_message(validator) + errors = validator.errors.map do |prop, rule| + "property: #{prop}, value: #{public_send(prop).inspect}, rule: #{rule[:rule]}, with params: #{rule[:params]}" + end + "Failed validation for properties: #{errors.join(' | ')}" + end + # Serialize the Entity into XML elements # @return [Nokogiri::XML::Element] root node def entity_xml @@ -146,5 +164,9 @@ module DiasporaFederation node.content = data unless data.empty? end end + + # Raised, if entity is not valid + class ValidationError < RuntimeError + end end end diff --git a/lib/diaspora_federation/validators/rules/boolean.rb b/lib/diaspora_federation/validators/rules/boolean.rb index 64eb9f9..ecc2b77 100644 --- a/lib/diaspora_federation/validators/rules/boolean.rb +++ b/lib/diaspora_federation/validators/rules/boolean.rb @@ -2,7 +2,7 @@ module Validation module Rule class Boolean def error_key - :numeric + :boolean end def valid_value?(value) diff --git a/spec/entities.rb b/spec/entities.rb index 8ec2002..2ecb901 100644 --- a/spec/entities.rb +++ b/spec/entities.rb @@ -26,4 +26,14 @@ module DiasporaFederation property :qwer, xml_name: :asdf end end + + module Validators + class TestDefaultEntityValidator < Validation::Validator + include Validation + + rule :test1, regular_expression: {regex: /\A[^;]{,32}\z/} + rule :test2, :not_nil + rule :test3, :boolean + end + end end diff --git a/spec/lib/diaspora_federation/entity_spec.rb b/spec/lib/diaspora_federation/entity_spec.rb index bc168d3..085bfb1 100644 --- a/spec/lib/diaspora_federation/entity_spec.rb +++ b/spec/lib/diaspora_federation/entity_spec.rb @@ -18,20 +18,22 @@ module DiasporaFederation }.to raise_error ArgumentError, "missing required properties: test1, test2" end - it "sets the defaults" do - entity = Entities::TestDefaultEntity.new(test1: 1, test2: 2) - expect(entity.test3).to be_truthy - end + context "defaults" do + it "sets the defaults" do + entity = Entities::TestDefaultEntity.new(test1: "1", test2: "2") + expect(entity.test3).to be_truthy + end - it "handles callable defaults" do - entity = Entities::TestDefaultEntity.new(test1: 1, test2: 2) - expect(entity.test4).to be_truthy - end + it "handles callable defaults" do + entity = Entities::TestDefaultEntity.new(test1: "1", test2: "2") + expect(entity.test4).to be_truthy + end - it "uses provided values over defaults" do - entity = Entities::TestDefaultEntity.new(data) - expect(entity.test3).to be_falsey - expect(entity.test4).to be_falsey + it "uses provided values over defaults" do + entity = Entities::TestDefaultEntity.new(data) + expect(entity.test3).to be_falsey + expect(entity.test4).to be_falsey + end end it "sets nil if string is empty" do @@ -39,6 +41,28 @@ module DiasporaFederation entity = Entities::TestDefaultEntity.new(data) expect(entity.test1).to be_nil end + + context "validation" do + let(:invalid_data) { {test1: "as;df", test2: nil, test3: "no boolean"} } + + it "validates the entity and raise an error with failed properties if not valid" do + expect { + Entities::TestDefaultEntity.new(invalid_data) + }.to raise_error Entity::ValidationError, /Failed validation for properties:.*test1.*\|.*test2.*\|.*test3/ + end + + it "contains the failed rule" do + expect { + Entities::TestDefaultEntity.new(invalid_data) + }.to raise_error Entity::ValidationError, /property: test2, value: nil, rule: not_nil, with params: \{\}/ + end + + it "contains the params of the failed rule" do + expect { + Entities::TestDefaultEntity.new(invalid_data) + }.to raise_error Entity::ValidationError, /rule: regular_expression, with params: \{:regex=>.*\}/ + end + end end describe "#to_h" do