From 6838391cc95f63831d93381a280b0e1d3621da88 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Fri, 25 Sep 2015 02:33:21 +0200 Subject: [PATCH] refactored Entity.entity_name and XmlPayload.entity_class_name write tests and simplified regexes. --- lib/diaspora_federation/entity.rb | 7 ++- lib/diaspora_federation/salmon/xml_payload.rb | 22 ++++++---- spec/entities.rb | 4 ++ spec/lib/diaspora_federation/entity_spec.rb | 4 ++ .../salmon/xml_payload_spec.rb | 43 +++++++++++++++++++ 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/lib/diaspora_federation/entity.rb b/lib/diaspora_federation/entity.rb index 944333a..ba294df 100644 --- a/lib/diaspora_federation/entity.rb +++ b/lib/diaspora_federation/entity.rb @@ -83,12 +83,11 @@ module DiasporaFederation entity_xml end - # some of this is from Rails "Inflector.demodulize" and "Inflector.undersore" + # Makes an underscored, lowercase form of the class name + # @return [String] entity name def self.entity_name name.rpartition("::").last.tap do |word| - word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2') - word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') - word.tr!("-", "_") + word.gsub!(/(.)([A-Z])/, '\1_\2') word.downcase! end end diff --git a/lib/diaspora_federation/salmon/xml_payload.rb b/lib/diaspora_federation/salmon/xml_payload.rb index 25d70bb..664ac73 100644 --- a/lib/diaspora_federation/salmon/xml_payload.rb +++ b/lib/diaspora_federation/salmon/xml_payload.rb @@ -47,8 +47,8 @@ module DiasporaFederation raise InvalidStructure unless wrap_valid?(xml) data = xml.at_xpath("post/*[1]") - klass_name = entity_class(data.name) - raise UnknownEntity unless Entities.const_defined?(klass_name) + klass_name = entity_class_name(data.name) + raise UnknownEntity, "'#{klass_name}' not found" unless Entities.const_defined?(klass_name) klass = Entities.const_get(klass_name) populate_entity(klass, data) @@ -66,16 +66,16 @@ module DiasporaFederation # Transform the given String from the lowercase underscored version to a # camelized variant, used later for getting the Class constant. # - # @note some of this is from Rails "Inflector.camelize" - # # @param [String] term "snake_case" class name # @return [String] "CamelCase" class name - def self.entity_class(term) - string = term.to_s - string = string.sub(/^[a-z\d]*/) { $&.capitalize } - string.gsub(%r{(?:_|(\/))([a-z\d]*)}i) { Regexp.last_match[2].capitalize }.gsub("/", "::") + def self.entity_class_name(term) + term.to_s.tap do |string| + raise InvalidEntityName, "'#{string}' is invalid" unless string =~ /^[a-z]*(_[a-z]*)*$/ + string.sub!(/^[a-z]/, &:upcase) + string.gsub!(/_([a-z])/) { Regexp.last_match[1].upcase } + end end - private_class_method :entity_class + private_class_method :entity_class_name # Construct a new instance of the given Entity and populate the properties # with the attributes found in the XML. @@ -114,6 +114,10 @@ module DiasporaFederation class InvalidStructure < RuntimeError end + # Raised, if the entity name in the XML is invalid + class InvalidEntityName < RuntimeError + end + # Raised, if the entity contained within the XML cannot be mapped to a # defined {Entity} subclass. class UnknownEntity < RuntimeError diff --git a/spec/entities.rb b/spec/entities.rb index 2ecb901..4b487bd 100644 --- a/spec/entities.rb +++ b/spec/entities.rb @@ -25,6 +25,10 @@ module DiasporaFederation property :test property :qwer, xml_name: :asdf end + + class Entity < DiasporaFederation::Entity + property :test + end end module Validators diff --git a/spec/lib/diaspora_federation/entity_spec.rb b/spec/lib/diaspora_federation/entity_spec.rb index 085bfb1..8bbd0b1 100644 --- a/spec/lib/diaspora_federation/entity_spec.rb +++ b/spec/lib/diaspora_federation/entity_spec.rb @@ -99,6 +99,10 @@ module DiasporaFederation expect(Entities::TestNestedEntity.entity_name).to eq("test_nested_entity") expect(Entities::OtherEntity.entity_name).to eq("other_entity") end + + it "works with a single word" do + expect(Entities::Entity.entity_name).to eq("entity") + end end context "nested entities" do diff --git a/spec/lib/diaspora_federation/salmon/xml_payload_spec.rb b/spec/lib/diaspora_federation/salmon/xml_payload_spec.rb index 89094b1..b555220 100644 --- a/spec/lib/diaspora_federation/salmon/xml_payload_spec.rb +++ b/spec/lib/diaspora_federation/salmon/xml_payload_spec.rb @@ -67,6 +67,21 @@ XML it "raises an error when the xml is wrong" do xml = <<-XML + + + + asdf + + + +XML + expect { + Salmon::XmlPayload.unpack(Nokogiri::XML::Document.parse(xml).root) + }.to raise_error Salmon::XmlPayload::UnknownEntity, "'UnknownEntity' not found" + end + + it "raises an error when the entity is not found" do + xml = <<-XML @@ -108,6 +123,34 @@ XML expect(entity.asdf).to eq("QWERT") end end + + context ".entity_class_name" do + it "should parse a single word" do + expect(Salmon::XmlPayload.send(:entity_class_name, "entity")).to eq("Entity") + end + + it "should parse with underscore" do + expect(Salmon::XmlPayload.send(:entity_class_name, "test_entity")).to eq("TestEntity") + end + + it "raises an error when the entity name contains special characters" do + expect { + Salmon::XmlPayload.send(:entity_class_name, "te.st-enti/ty") + }.to raise_error Salmon::XmlPayload::InvalidEntityName, "'te.st-enti/ty' is invalid" + end + + it "raises an error when the entity name contains upper case letters" do + expect { + Salmon::XmlPayload.send(:entity_class_name, "TestEntity") + }.to raise_error Salmon::XmlPayload::InvalidEntityName, "'TestEntity' is invalid" + end + + it "raises an error when the entity name contains numbers" do + expect { + Salmon::XmlPayload.send(:entity_class_name, "te5t_ent1ty_w1th_number5") + }.to raise_error Salmon::XmlPayload::InvalidEntityName, "'te5t_ent1ty_w1th_number5' is invalid" + end + end end end end