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