diff --git a/lib/diaspora_federation/entities/person.rb b/lib/diaspora_federation/entities/person.rb index a368369..ebbcbcc 100644 --- a/lib/diaspora_federation/entities/person.rb +++ b/lib/diaspora_federation/entities/person.rb @@ -8,10 +8,9 @@ module DiasporaFederation property :guid # @!attribute [r] diaspora_id - # @todo refactoring with properties_dsl, xml name should be diaspora_handle # The diaspora ID of the person # @return [String] diaspora ID - property :diaspora_id + property :diaspora_id, xml_name: :diaspora_handle # @!attribute [r] url # @see WebFinger#seed_url diff --git a/lib/diaspora_federation/entities/profile.rb b/lib/diaspora_federation/entities/profile.rb index 6a338f0..c819cff 100644 --- a/lib/diaspora_federation/entities/profile.rb +++ b/lib/diaspora_federation/entities/profile.rb @@ -3,11 +3,10 @@ module DiasporaFederation # this entity contains all the profile data of a person class Profile < Entity # @!attribute [r] diaspora_id - # @todo refactoring with properties_dsl, xml name should be diaspora_handle # The diaspora ID of the person # @see Person#diaspora_id # @return [String] diaspora ID - property :diaspora_id + property :diaspora_id, xml_name: :diaspora_handle # @!attribute [r] first_name # @deprecated diff --git a/lib/diaspora_federation/entity.rb b/lib/diaspora_federation/entity.rb index ffe6be0..cbcda87 100644 --- a/lib/diaspora_federation/entity.rb +++ b/lib/diaspora_federation/entity.rb @@ -15,6 +15,7 @@ module DiasporaFederation # property :prop # property :optional, default: false # property :dynamic_default, default: -> { Time.now } + # property :another_prop, xml_name: :another_name # entity :nested, NestedEntity # entity :multiple, [OtherEntity] # end @@ -59,7 +60,7 @@ module DiasporaFederation # @return [Hash] entity data (mostly equal to the hash used for initialization). def to_h self.class.class_prop_names.each_with_object({}) do |prop, hash| - hash[prop] = send(prop) + hash[prop] = public_send(prop) end end @@ -120,24 +121,28 @@ module DiasporaFederation doc = Nokogiri::XML::DocumentFragment.new(Nokogiri::XML::Document.new) Nokogiri::XML::Element.new(self.class.entity_name, doc).tap do |root_element| self.class.class_props.each do |prop_def| - name = prop_def[:name] - type = prop_def[:type] - if type == String - root_element << simple_node(doc, name) - else - # call #to_xml for each item and append to root - [*send(name)].compact.each do |item| - root_element << item.to_xml - end - end + add_property_to_xml(doc, prop_def, root_element) + end + end + end + + def add_property_to_xml(doc, prop_def, root_element) + property = prop_def[:name] + type = prop_def[:type] + if type == String + root_element << simple_node(doc, prop_def[:xml_name], property) + else + # call #to_xml for each item and append to root + [*public_send(property)].compact.each do |item| + root_element << item.to_xml end end end # create simple node, fill it with text and append to root - def simple_node(doc, name) + def simple_node(doc, name, property) Nokogiri::XML::Element.new(name.to_s, doc).tap do |node| - data = send(name).to_s + data = public_send(property).to_s node.content = data unless data.empty? end end diff --git a/lib/diaspora_federation/properties_dsl.rb b/lib/diaspora_federation/properties_dsl.rb index abfb9fb..12525d7 100644 --- a/lib/diaspora_federation/properties_dsl.rb +++ b/lib/diaspora_federation/properties_dsl.rb @@ -6,6 +6,7 @@ module DiasporaFederation # property :prop # property :optional, default: false # property :dynamic_default, default: -> { Time.now } + # property :another_prop, xml_name: :another_name # entity :nested, NestedEntity # entity :multiple, [OtherEntity] module PropertiesDSL @@ -19,6 +20,7 @@ module DiasporaFederation # @param [Hash] opts further options # @option opts [Object, #call] :default a default value, making the # property optional + # @option opts [Symbol] :xml_name another name used for xml generation def property(name, opts={}) define_property name, String, opts end @@ -69,7 +71,14 @@ module DiasporaFederation def define_property(name, type, opts={}) raise InvalidName unless name_valid?(name) - class_props << {name: name, type: type} + xml_name = name + if opts.has_key? :xml_name + raise ArgumentError, "xml_name is not supported for nested entities" unless type == String + xml_name = opts[:xml_name] + raise InvalidName, "invalid xml_name" unless name_valid?(xml_name) + end + + class_props << {name: name, xml_name: xml_name, type: type} default_props[name] = opts[:default] if opts.has_key? :default instance_eval { attr_reader name } @@ -79,7 +88,7 @@ module DiasporaFederation # @param [String, Symbol] name the name to check # @return [Boolean] def name_valid?(name) - name.instance_of?(Symbol) || name.instance_of?(String) + name.instance_of?(Symbol) end # checks if the type extends {Entity} diff --git a/spec/entities.rb b/spec/entities.rb index ee8f312..8ec2002 100644 --- a/spec/entities.rb +++ b/spec/entities.rb @@ -20,5 +20,10 @@ module DiasporaFederation entity :test, TestEntity entity :multi, [OtherEntity] end + + class TestEntityWithXmlName < DiasporaFederation::Entity + property :test + property :qwer, xml_name: :asdf + end end end diff --git a/spec/lib/diaspora_federation/entity_spec.rb b/spec/lib/diaspora_federation/entity_spec.rb index 408ebed..bc168d3 100644 --- a/spec/lib/diaspora_federation/entity_spec.rb +++ b/spec/lib/diaspora_federation/entity_spec.rb @@ -61,7 +61,9 @@ module DiasporaFederation it "contains nodes for each of the properties" do entity = Entities::TestDefaultEntity.new(data) - entity.to_xml.children.each do |node| + xml_children = entity.to_xml.children + expect(xml_children).to have_exactly(4).items + xml_children.each do |node| expect(%w(test1 test2 test3 test4)).to include(node.name) end end @@ -92,6 +94,7 @@ module DiasporaFederation it "gets xml-ified by #to_xml" do entity = Entities::TestNestedEntity.new(nested_data) xml = entity.to_xml + expect(xml.children).to have_exactly(4).items xml.children.each do |node| expect(%w(asdf test_entity other_entity)).to include(node.name) end @@ -99,5 +102,23 @@ module DiasporaFederation expect(xml.xpath("other_entity")).to have_exactly(2).items end end + + context "xml_name" do + let(:hash) { {test: "test", qwer: "qwer"} } + + it "uses xml_name for the #to_xml" do + entity = Entities::TestEntityWithXmlName.new(hash) + xml_children = entity.to_xml.children + expect(xml_children).to have_exactly(2).items + xml_children.each do |node| + expect(%w(test asdf)).to include(node.name) + end + end + + it "should not use the xml_name for the #to_h" do + entity = Entities::TestEntityWithXmlName.new(hash) + expect(entity.to_h).to eq(hash) + end + end end end diff --git a/spec/lib/diaspora_federation/properties_dsl_spec.rb b/spec/lib/diaspora_federation/properties_dsl_spec.rb index 8a225f2..cd8a287 100644 --- a/spec/lib/diaspora_federation/properties_dsl_spec.rb +++ b/spec/lib/diaspora_federation/properties_dsl_spec.rb @@ -8,19 +8,12 @@ module DiasporaFederation properties = dsl.class_props expect(properties).to have(1).item expect(properties.first[:name]).to eq(:test) - expect(properties.first[:type]).to eq(String) - end - - it "can name simple properties by string" do - dsl.property "test" - properties = dsl.class_props - expect(properties).to have(1).item - expect(properties.first[:name]).to eq("test") + expect(properties.first[:xml_name]).to eq(:test) expect(properties.first[:type]).to eq(String) end it "will not accept other types for names" do - [1234, true, {}].each do |val| + ["test", 1234, true, {}].each do |val| expect { dsl.property val }.to raise_error PropertiesDSL::InvalidName @@ -34,8 +27,26 @@ module DiasporaFederation properties = dsl.class_props expect(properties).to have(3).items expect(properties.map {|e| e[:name] }).to include(:test, :asdf, :zzzz) + expect(properties.map {|e| e[:xml_name] }).to include(:test, :asdf, :zzzz) properties.each {|e| expect(e[:type]).to eq(String) } end + + it "can add an xml name to simple properties with a symbol" do + dsl.property :test, xml_name: :xml_test + properties = dsl.class_props + expect(properties).to have(1).item + expect(properties.first[:name]).to eq(:test) + expect(properties.first[:xml_name]).to eq(:xml_test) + expect(properties.first[:type]).to eq(String) + end + + it "will not accept other types for xml names" do + ["test", 1234, true, {}].each do |val| + expect { + dsl.property :test, xml_name: val + }.to raise_error PropertiesDSL::InvalidName, "invalid xml_name" + end + end end context "nested entities" do @@ -75,6 +86,12 @@ module DiasporaFederation }.to raise_error PropertiesDSL::InvalidType end end + + it "can not add an xml name to a nested entity" do + expect { + dsl.entity :other, Entities::TestEntity, xml_name: :other_name + }.to raise_error ArgumentError, "xml_name is not supported for nested entities" + end end describe ".default_values" do