refactored Entity.entity_name and XmlPayload.entity_class_name

write tests and simplified regexes.
This commit is contained in:
Benjamin Neff 2015-09-25 02:33:21 +02:00
parent eb707c2592
commit 6838391cc9
5 changed files with 67 additions and 13 deletions

View file

@ -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

View file

@ -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

View file

@ -25,6 +25,10 @@ module DiasporaFederation
property :test
property :qwer, xml_name: :asdf
end
class Entity < DiasporaFederation::Entity
property :test
end
end
module Validators

View file

@ -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

View file

@ -67,6 +67,21 @@ XML
it "raises an error when the xml is wrong" do
xml = <<-XML
<XML>
<post>
<unknown_entity>
<test>asdf</test>
</test_entity>
</post>
</XML>
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
<root>
<weird/>
</root>
@ -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