diff --git a/.gitignore b/.gitignore index d51937d8..a4e77a54 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ Gemfile.lock *.swp *.swo bin +.idea diff --git a/lib/representable/xml/binding.rb b/lib/representable/xml/binding.rb index 8f4d1a08..3997c6de 100644 --- a/lib/representable/xml/binding.rb +++ b/lib/representable/xml/binding.rb @@ -37,7 +37,10 @@ def serialize_for(value, parent) end def serialize_node(node, value) - return value if typed? + if typed? + value.name = as if value.is_a?(::Nokogiri::XML::Element) && as != '_self' + return value + end node.content = value node @@ -64,7 +67,7 @@ def xpath def find_nodes(doc) selector = xpath selector = "#{self[:wrap]}/#{xpath}" if self[:wrap] - nodes = doc.xpath(selector) + doc.xpath(selector) end def node_for(parent, name) diff --git a/test/parse_strategy_test.rb b/test/parse_strategy_test.rb index 3601e227..f1e9019c 100644 --- a/test/parse_strategy_test.rb +++ b/test/parse_strategy_test.rb @@ -17,11 +17,12 @@ class ParseStrategySyncTest < BaseTest representer!(:module => mod, :name => :song_representer) do property :title - self.representation_wrap = :song if format == :xml end representer!(:inject => :song_representer, :module => mod) do - property :song, :parse_strategy => :sync, :extend => song_representer + options = { :parse_strategy => :sync, :extend => song_representer } + options[:as] = :song if format == :xml + property :song, options end let (:hit) { hit = OpenStruct.new(:song => song).extend(representer) } @@ -46,7 +47,7 @@ class ParseStrategySyncTest < BaseTest for_formats( :hash => [Representable::Hash, {"songs"=>[{"title"=>"Resist Stance"}]}, {"songs"=>[{"title"=>"Suffer"}]}], #:json => [Representable::JSON, "{\"song\":{\"name\":\"Alive\"}}", "{\"song\":{\"name\":\"You've Taken Everything\"}}"], - :xml => [Representable::XML, "Resist Stance", "Suffer"], + :xml => [Representable::XML, "Resist Stance", "Suffer"], :yaml => [Representable::YAML, "---\nsongs:\n- title: Resist Stance\n", "---\nsongs:\n- title: Suffer\n"], ) do |format, mod, output, input| @@ -54,11 +55,12 @@ class ParseStrategySyncTest < BaseTest let (:format) { format } representer!(:module => mod, :name => :song_representer) do property :title - self.representation_wrap = :song if format == :xml end representer!(:inject => :song_representer, :module => mod) do - collection :songs, :parse_strategy => :sync, :extend => song_representer + options = { :parse_strategy => :sync, :extend => song_representer } + options[:as] = :song if format == :xml + collection :songs, options end let (:album) { OpenStruct.new(:songs => [song]).extend(representer) } @@ -71,12 +73,10 @@ class ParseStrategySyncTest < BaseTest collection_id = album.songs.object_id song = album.songs.first song_id = song.object_id - parse(album, input) - album.songs.first.title.must_equal "Suffer" song.title.must_equal "Suffer" - #album.songs.object_id.must_equal collection_id # TODO: don't replace! + album.songs.object_id.must_equal collection_id # TODO: don't replace! song.object_id.must_equal song_id end end diff --git a/test/xml_test.rb b/test/xml_test.rb index 4c94b61d..c7d7a237 100644 --- a/test/xml_test.rb +++ b/test/xml_test.rb @@ -160,7 +160,7 @@ def name=(v) @album.extend(AlbumRepresenter) assert_xml_equal " - Mr. Charisma + Mr. Charisma I Hate My Brain Mr. Charisma ", @album.to_xml @@ -277,9 +277,9 @@ def to_node(*) album = Album.new(band).extend(AlbumRepresenter) assert_xml_equal %{ - + - + }, album.to_xml end end @@ -481,7 +481,7 @@ class XmlHashTest < MiniTest::Spec describe "with objects" do representer!(module: Representable::XML) do - hash :songs, class: OpenStruct do + hash :songs, class: OpenStruct, as: :open_struct do property :title end end @@ -500,4 +500,61 @@ class XmlHashTest < MiniTest::Spec # FIXME: this NEVER worked! # it { OpenStruct.new.extend(representer).from_xml(doc).songs.must_equal({"first" => "The Gargoyle", "second" => "Bronx"}) } end +end + +class XMLInheritenceTest < Minitest::Spec + class DateEntry + attr_accessor :value, :format + def initialize(value = nil) + @value = value + @format = 'YYYYMMDD' + end + end + + class InvoiceEntry + attr_accessor :start_date, :end_date + def initialize(start_date = nil, end_date = nil) + @start_date = DateEntry.new(start_date) if start_date + @end_date = DateEntry.new(end_date) if end_date + end + end + + class DateDecorator < ::Representable::Decorator + include Representable::XML + property :value, content: true + property :format, as: 'Format', attribute: true + end + + class InvoiceDecorator < ::Representable::Decorator + include Representable::XML + property :start_date, decorator: DateDecorator, class: DateEntry + property :end_date, decorator: DateDecorator, class: DateEntry + end + + let(:doc) { + <<-STR + + 20141212 + 20141216 + + STR + } + + let(:invoice) { + InvoiceEntry.new('20141212', '20141216') + } + + describe '#to_xml' do + it { InvoiceDecorator.new(invoice).to_xml.must_equal_xml doc } + end + + describe '#from_xml' do + it 'should create proper entries' do + invoice_from_xml = InvoiceEntry.new + InvoiceDecorator.new(invoice_from_xml).from_xml(doc) + invoice_from_xml.start_date.value.must_equal '20141212' + invoice_from_xml.end_date.value.must_equal '20141216' + end + end + end \ No newline at end of file