omg-peanuts 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +12 -8
- data/Rakefile +6 -3
- data/lib/peanuts/converters.rb +2 -2
- data/lib/peanuts/mapper.rb +10 -26
- data/lib/peanuts/mappings.rb +65 -54
- data/lib/peanuts/nuts.rb +91 -106
- data/lib/peanuts/xml.rb +78 -1
- data/lib/peanuts/xml/libxml.rb +22 -33
- data/spec/cat_spec.rb +142 -0
- metadata +5 -6
- data/lib/peanuts/xml/reader.rb +0 -78
- data/test/parsing_test.rb +0 -115
    
        data/README.rdoc
    CHANGED
    
    | @@ -47,18 +47,21 @@ Please report via Github issue tracking. | |
| 47 47 |  | 
| 48 48 | 
             
                  root 'kitteh', :xmlns => :lol
         | 
| 49 49 |  | 
| 50 | 
            -
                  attribute :has_tail, :boolean, :xmlname => 'has-tail', :xmlns =>  | 
| 50 | 
            +
                  attribute :has_tail, :boolean, :xmlname => 'has-tail', :xmlns => :kthnx
         | 
| 51 51 | 
             
                  attribute :ears, :integer
         | 
| 52 52 |  | 
| 53 53 | 
             
                  element :ration, [:string], :xmlname => :eats, :xmlns => :kthnx
         | 
| 54 | 
            -
                  element :name, : | 
| 55 | 
            -
                  elements :paws, : | 
| 54 | 
            +
                  element :name, :xmlns => 'urn:x-lol:kthnx'
         | 
| 55 | 
            +
                  elements :paws, :xmlname => :paw
         | 
| 56 56 |  | 
| 57 | 
            -
                  element :friends, :xmlname => :pals do | 
| 58 | 
            -
                    elements :names, : | 
| 57 | 
            +
                  element :friends, :xmlname => :pals do
         | 
| 58 | 
            +
                    elements :names, :xmlname => :pal
         | 
| 59 59 | 
             
                  end
         | 
| 60 60 |  | 
| 61 61 | 
             
                  element :cheezburger, Cheezburger
         | 
| 62 | 
            +
                  element :moar_cheezburgers do
         | 
| 63 | 
            +
                    elements :cheezburger, Cheezburger
         | 
| 64 | 
            +
                  end
         | 
| 62 65 | 
             
                end
         | 
| 63 66 |  | 
| 64 67 | 
             
                xml_fragment = <<-EOS
         | 
| @@ -83,7 +86,7 @@ Please report via Github issue tracking. | |
| 83 86 | 
             
                      <cheezburger weight='2' />
         | 
| 84 87 | 
             
                    </kitteh>
         | 
| 85 88 | 
             
                EOS
         | 
| 86 | 
            -
                cat = Cat. | 
| 89 | 
            +
                cat = Cat.restore_from(xml_fragment)
         | 
| 87 90 |  | 
| 88 91 | 
             
                assert_equal 'Silly Tom', cat.name
         | 
| 89 92 | 
             
                assert_equal %w(tigers lions), cat.ration
         | 
| @@ -94,12 +97,13 @@ Please report via Github issue tracking. | |
| 94 97 | 
             
                assert_kind_of Cheezburger, cat.cheezburger
         | 
| 95 98 | 
             
                assert_equal 2, cat.cheezburger.weight
         | 
| 96 99 | 
             
                ...
         | 
| 97 | 
            -
                puts cat. | 
| 100 | 
            +
                puts cat.save_to(:string)
         | 
| 98 101 |  | 
| 99 102 |  | 
| 100 103 | 
             
            === See also
         | 
| 101 | 
            -
            * http://github.com/omg/ | 
| 104 | 
            +
            * http://github.com/omg/quack      -- ... here is my handle, here is my spout
         | 
| 102 105 | 
             
            * http://github.com/omg/statelogic -- A simple state machine for ActiveRecord
         | 
| 106 | 
            +
            * http://github.com/omg/threadpool -- Thread pool implementation
         | 
| 103 107 |  | 
| 104 108 |  | 
| 105 109 | 
             
            Copyright (c) 2009 Igor Gunko, released under the MIT license
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -5,7 +5,7 @@ require 'rake' | |
| 5 5 | 
             
            require 'rake/clean'
         | 
| 6 6 | 
             
            require 'rake/gempackagetask'
         | 
| 7 7 | 
             
            require 'rake/rdoctask'
         | 
| 8 | 
            -
            require 'rake/ | 
| 8 | 
            +
            require 'spec/rake/spectask'
         | 
| 9 9 |  | 
| 10 10 | 
             
            Rake::GemPackageTask.new(Gem::Specification.load('peanuts.gemspec')) do |p|
         | 
| 11 11 | 
             
              p.need_tar = true
         | 
| @@ -21,6 +21,9 @@ Rake::RDocTask.new do |rdoc| | |
| 21 21 | 
             
              rdoc.options << '--line-numbers' << '--inline-source'
         | 
| 22 22 | 
             
            end
         | 
| 23 23 |  | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 24 | 
            +
            desc 'Run specs'
         | 
| 25 | 
            +
            task :test => :spec
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            Spec::Rake::SpecTask.new do |t|
         | 
| 28 | 
            +
              t.spec_files = FileList['spec/**/*.rb']
         | 
| 26 29 | 
             
            end
         | 
    
        data/lib/peanuts/converters.rb
    CHANGED
    
    | @@ -83,8 +83,8 @@ module Peanuts | |
| 83 83 | 
             
                  def to_xml(flag)
         | 
| 84 84 | 
             
                    return nil if flag.nil?
         | 
| 85 85 | 
             
                    string = case @format
         | 
| 86 | 
            -
                    when :true_false then flag ? 'true' : 'false'
         | 
| 87 | 
            -
                    when :yes_no then flag ? 'yes' : 'no'
         | 
| 86 | 
            +
                    when :true_false, :truefalse then flag ? 'true' : 'false'
         | 
| 87 | 
            +
                    when :yes_no, :yesno then flag ? 'yes' : 'no'
         | 
| 88 88 | 
             
                    when :numeric then flag ? '0' : '1'
         | 
| 89 89 | 
             
                    end
         | 
| 90 90 | 
             
                    super(string)
         | 
    
        data/lib/peanuts/mapper.rb
    CHANGED
    
    | @@ -4,30 +4,21 @@ module Peanuts | |
| 4 4 | 
             
              class Mapper
         | 
| 5 5 | 
             
                include Enumerable
         | 
| 6 6 |  | 
| 7 | 
            -
                attr_reader :root, :namespaces, : | 
| 7 | 
            +
                attr_reader :root, :namespaces, :ns_context, :default_ns
         | 
| 8 8 | 
             
                attr_accessor :schema
         | 
| 9 9 |  | 
| 10 | 
            -
                def initialize
         | 
| 10 | 
            +
                def initialize(ns_context = nil, default_ns = nil)
         | 
| 11 | 
            +
                  @ns_context, @default_ns = ns_context, default_ns
         | 
| 11 12 | 
             
                  @mappings, @footprints = [], {}
         | 
| 12 | 
            -
                  @namespaces = Hash.new  | 
| 13 | 
            -
                    nscontext && nscontext[k] || raise(IndexError)
         | 
| 14 | 
            -
                  end
         | 
| 13 | 
            +
                  @namespaces = ns_context ? Hash.new {|h, k| ns_context[k] || raise(IndexError) } : {}
         | 
| 15 14 | 
             
                end
         | 
| 16 15 |  | 
| 17 16 | 
             
                def root=(root)
         | 
| 18 17 | 
             
                  raise 'root already defined' if @root
         | 
| 19 | 
            -
                  raise 'root in nested scopes not supported' if nested?
         | 
| 18 | 
            +
                  # TODO raise 'root in nested scopes not supported' if nested?
         | 
| 20 19 | 
             
                  @root = root
         | 
| 21 20 | 
             
                end
         | 
| 22 21 |  | 
| 23 | 
            -
                def set_context(container, nscontext)
         | 
| 24 | 
            -
                  @container, @nscontext = container, nscontext
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                def nested?
         | 
| 28 | 
            -
                  !!container
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
             | 
| 31 22 | 
             
                def each(&block)
         | 
| 32 23 | 
             
                  @mappings.each(&block)
         | 
| 33 24 | 
             
                end
         | 
| @@ -38,24 +29,17 @@ module Peanuts | |
| 38 29 | 
             
                  @mappings << (@footprints[fp] = mapping)
         | 
| 39 30 | 
             
                end
         | 
| 40 31 |  | 
| 41 | 
            -
                def  | 
| 32 | 
            +
                def restore(nut, reader)
         | 
| 42 33 | 
             
                  rdfp = ReaderFootprint.new(reader)
         | 
| 43 34 | 
             
                  reader.each do
         | 
| 44 35 | 
             
                    m = @footprints[rdfp]
         | 
| 45 | 
            -
                    m. | 
| 36 | 
            +
                    m.restore(nut, reader) if m
         | 
| 46 37 | 
             
                  end
         | 
| 47 38 | 
             
                  nut
         | 
| 48 39 | 
             
                end
         | 
| 49 40 |  | 
| 50 | 
            -
                def  | 
| 51 | 
            -
                   | 
| 52 | 
            -
                    @root.to_xml(writer) do
         | 
| 53 | 
            -
                      _save(nut, writer)
         | 
| 54 | 
            -
                    end
         | 
| 55 | 
            -
                  else
         | 
| 56 | 
            -
                    _save(nut, writer)
         | 
| 57 | 
            -
                  end
         | 
| 58 | 
            -
                  writer.result
         | 
| 41 | 
            +
                def save(nut, writer)
         | 
| 42 | 
            +
                  @root ? @root.save(writer) { _save(nut, writer) } : _save(nut, writer)
         | 
| 59 43 | 
             
                end
         | 
| 60 44 |  | 
| 61 45 | 
             
                def clear(nut)
         | 
| @@ -64,7 +48,7 @@ module Peanuts | |
| 64 48 |  | 
| 65 49 | 
             
                private
         | 
| 66 50 | 
             
                def _save(nut, writer)
         | 
| 67 | 
            -
                  @mappings.each {|m| m. | 
| 51 | 
            +
                  @mappings.each {|m| m.save(nut, writer) } if nut
         | 
| 68 52 | 
             
                end
         | 
| 69 53 |  | 
| 70 54 | 
             
                class Footprint
         | 
    
        data/lib/peanuts/mappings.rb
    CHANGED
    
    | @@ -25,7 +25,7 @@ module Peanuts | |
| 25 25 | 
             
                class Root < Mapping
         | 
| 26 26 | 
             
                  node_type :element
         | 
| 27 27 |  | 
| 28 | 
            -
                  def  | 
| 28 | 
            +
                  def save(writer, &block)
         | 
| 29 29 | 
             
                    writer.write(node_type, xmlname, xmlns, prefix, &block)
         | 
| 30 30 | 
             
                  end
         | 
| 31 31 | 
             
                end
         | 
| @@ -37,7 +37,7 @@ module Peanuts | |
| 37 37 | 
             
                    super(options.delete(:xmlname) || name, options)
         | 
| 38 38 | 
             
                    case type
         | 
| 39 39 | 
             
                    when Array
         | 
| 40 | 
            -
                      raise ArgumentError, "invalid value for type: #{type}" if type.length != 1
         | 
| 40 | 
            +
                      raise ArgumentError, "invalid value for type: #{type.inspect}" if type.length != 1
         | 
| 41 41 | 
             
                      options[:item_type] = type.first
         | 
| 42 42 | 
             
                      @converter = Converter.create!(:list, options)
         | 
| 43 43 | 
             
                    when Class
         | 
| @@ -48,12 +48,12 @@ module Peanuts | |
| 48 48 | 
             
                    @name, @setter, @type = name.to_sym, :"#{name}=", type
         | 
| 49 49 | 
             
                  end
         | 
| 50 50 |  | 
| 51 | 
            -
                  def  | 
| 52 | 
            -
                     | 
| 51 | 
            +
                  def save(nut, writer)
         | 
| 52 | 
            +
                    save_value(writer, get(nut))
         | 
| 53 53 | 
             
                  end
         | 
| 54 54 |  | 
| 55 | 
            -
                  def  | 
| 56 | 
            -
                    set(nut,  | 
| 55 | 
            +
                  def restore(nut, reader)
         | 
| 56 | 
            +
                    set(nut, restore_value(reader, get(nut)))
         | 
| 57 57 | 
             
                  end
         | 
| 58 58 |  | 
| 59 59 | 
             
                  def clear(nut)
         | 
| @@ -69,99 +69,110 @@ module Peanuts | |
| 69 69 | 
             
                    nut.send(@setter, value)
         | 
| 70 70 | 
             
                  end
         | 
| 71 71 |  | 
| 72 | 
            -
                  def  | 
| 72 | 
            +
                  def to_xml(value)
         | 
| 73 73 | 
             
                    @converter ? @converter.to_xml(value) : value
         | 
| 74 74 | 
             
                  end
         | 
| 75 75 |  | 
| 76 | 
            -
                  def  | 
| 76 | 
            +
                  def from_xml(text)
         | 
| 77 77 | 
             
                    @converter ? @converter.from_xml(text) : text
         | 
| 78 78 | 
             
                  end
         | 
| 79 79 |  | 
| 80 | 
            -
                  def  | 
| 81 | 
            -
                     | 
| 80 | 
            +
                  def write(writer, &block)
         | 
| 81 | 
            +
                    writer.write(node_type, xmlname, xmlns, prefix, &block)
         | 
| 82 82 | 
             
                  end
         | 
| 83 83 |  | 
| 84 | 
            -
                  def  | 
| 84 | 
            +
                  def restore_object(events)
         | 
| 85 85 | 
             
                    type.send(:_restore, events)
         | 
| 86 86 | 
             
                  end
         | 
| 87 87 |  | 
| 88 | 
            -
                  def  | 
| 88 | 
            +
                  def save_object(nut, writer)
         | 
| 89 89 | 
             
                    type.send(:_save, nut, writer)
         | 
| 90 90 | 
             
                  end
         | 
| 91 91 | 
             
                end
         | 
| 92 92 |  | 
| 93 | 
            -
                 | 
| 94 | 
            -
                  node_type :element
         | 
| 95 | 
            -
             | 
| 93 | 
            +
                module SingleMapping
         | 
| 96 94 | 
             
                  private
         | 
| 97 | 
            -
                  def  | 
| 98 | 
            -
                     | 
| 95 | 
            +
                  def restore_value(reader, acc)
         | 
| 96 | 
            +
                    read_value(reader)
         | 
| 99 97 | 
             
                  end
         | 
| 100 98 |  | 
| 101 | 
            -
                  def  | 
| 102 | 
            -
                     | 
| 103 | 
            -
                      w.value = toxml(value)
         | 
| 104 | 
            -
                    end
         | 
| 99 | 
            +
                  def save_value(writer, value)
         | 
| 100 | 
            +
                    write(writer) {|w| write_value(w, value) }
         | 
| 105 101 | 
             
                  end
         | 
| 106 102 | 
             
                end
         | 
| 107 103 |  | 
| 108 | 
            -
                 | 
| 109 | 
            -
                   | 
| 110 | 
            -
             | 
| 111 | 
            -
                  private
         | 
| 112 | 
            -
                  def getxml(node)
         | 
| 113 | 
            -
                    parse(node)
         | 
| 104 | 
            +
                module MultiMapping
         | 
| 105 | 
            +
                  def restore_value(reader, acc)
         | 
| 106 | 
            +
                    (acc || []) << read_value(reader)
         | 
| 114 107 | 
             
                  end
         | 
| 115 108 |  | 
| 116 | 
            -
                  def  | 
| 117 | 
            -
                     | 
| 118 | 
            -
                       | 
| 109 | 
            +
                  def save_value(writer, values)
         | 
| 110 | 
            +
                    for value in values
         | 
| 111 | 
            +
                      write(writer) {|w| write_value(w, value) }
         | 
| 119 112 | 
             
                    end
         | 
| 120 113 | 
             
                  end
         | 
| 121 114 | 
             
                end
         | 
| 122 115 |  | 
| 123 | 
            -
                 | 
| 124 | 
            -
                   | 
| 116 | 
            +
                module ValueMapping
         | 
| 117 | 
            +
                  private
         | 
| 118 | 
            +
                  def read_value(reader)
         | 
| 119 | 
            +
                    from_xml(reader.value)
         | 
| 120 | 
            +
                  end
         | 
| 125 121 |  | 
| 126 | 
            -
                  def  | 
| 127 | 
            -
                     | 
| 128 | 
            -
                    raise ArgumentError, 'a namespaced attribute must have namespace prefix' if xmlns && !prefix
         | 
| 122 | 
            +
                  def write_value(writer, value)
         | 
| 123 | 
            +
                    writer.value = to_xml(value)
         | 
| 129 124 | 
             
                  end
         | 
| 125 | 
            +
                end
         | 
| 130 126 |  | 
| 127 | 
            +
                module ObjectMapping
         | 
| 131 128 | 
             
                  private
         | 
| 132 | 
            -
                  def  | 
| 133 | 
            -
                     | 
| 129 | 
            +
                  def read_value(reader)
         | 
| 130 | 
            +
                    restore_object(reader)
         | 
| 134 131 | 
             
                  end
         | 
| 135 132 |  | 
| 136 | 
            -
                  def  | 
| 137 | 
            -
                     | 
| 133 | 
            +
                  def write_value(writer, value)
         | 
| 134 | 
            +
                    save_object(value, writer)
         | 
| 138 135 | 
             
                  end
         | 
| 139 136 | 
             
                end
         | 
| 140 137 |  | 
| 141 | 
            -
                class  | 
| 138 | 
            +
                class ElementValue < MemberMapping
         | 
| 139 | 
            +
                  include SingleMapping
         | 
| 140 | 
            +
                  include ValueMapping
         | 
| 141 | 
            +
             | 
| 142 142 | 
             
                  node_type :element
         | 
| 143 | 
            +
                end
         | 
| 143 144 |  | 
| 144 | 
            -
             | 
| 145 | 
            -
                   | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 145 | 
            +
                class Element < MemberMapping
         | 
| 146 | 
            +
                  include SingleMapping
         | 
| 147 | 
            +
                  include ObjectMapping
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  node_type :element
         | 
| 150 | 
            +
                end
         | 
| 148 151 |  | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 152 | 
            +
                class Attribute < MemberMapping
         | 
| 153 | 
            +
                  include SingleMapping
         | 
| 154 | 
            +
                  include ValueMapping
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                  node_type :attribute
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                  def initialize(name, type, options)
         | 
| 159 | 
            +
                    super
         | 
| 160 | 
            +
                    raise ArgumentError, 'a namespaced attribute must have namespace prefix' if xmlns && !prefix
         | 
| 151 161 | 
             
                  end
         | 
| 152 162 | 
             
                end
         | 
| 153 163 |  | 
| 154 | 
            -
                class  | 
| 164 | 
            +
                class ElementValues < MemberMapping
         | 
| 165 | 
            +
                  include MultiMapping
         | 
| 166 | 
            +
                  include ValueMapping
         | 
| 167 | 
            +
             | 
| 155 168 | 
             
                  node_type :element
         | 
| 169 | 
            +
                end
         | 
| 156 170 |  | 
| 157 | 
            -
             | 
| 158 | 
            -
                   | 
| 159 | 
            -
             | 
| 160 | 
            -
                  end
         | 
| 171 | 
            +
                class Elements < MemberMapping
         | 
| 172 | 
            +
                  include MultiMapping
         | 
| 173 | 
            +
                  include ObjectMapping
         | 
| 161 174 |  | 
| 162 | 
            -
                   | 
| 163 | 
            -
                    elements.each {|e| build(node, e, add_element(node)) } if elements
         | 
| 164 | 
            -
                  end
         | 
| 175 | 
            +
                  node_type :element
         | 
| 165 176 | 
             
                end
         | 
| 166 177 | 
             
              end
         | 
| 167 178 | 
             
            end
         | 
    
        data/lib/peanuts/nuts.rb
    CHANGED
    
    | @@ -1,27 +1,28 @@ | |
| 1 1 | 
             
            require 'peanuts/mappings'
         | 
| 2 2 | 
             
            require 'peanuts/mapper'
         | 
| 3 | 
            -
            require 'peanuts/xml/reader'
         | 
| 4 3 |  | 
| 5 4 | 
             
            module Peanuts #:nodoc:
         | 
| 6 | 
            -
              # See also +ClassMethods+
         | 
| 7 5 | 
             
              def self.included(other) #:nodoc:
         | 
| 8 | 
            -
                other | 
| 6 | 
            +
                init(other)
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def self.init(cls, ns_context = nil, default_ns = nil, &block) #:nodoc:
         | 
| 10 | 
            +
                cls.instance_eval do
         | 
| 11 | 
            +
                  include InstanceMethods
         | 
| 12 | 
            +
                  extend ClassMethods
         | 
| 13 | 
            +
                  @mapper = Mapper.new(ns_context, default_ns)
         | 
| 14 | 
            +
                  instance_eval(&block) if block_given?
         | 
| 15 | 
            +
                end
         | 
| 9 16 | 
             
              end
         | 
| 10 17 |  | 
| 11 | 
            -
              # See also + | 
| 18 | 
            +
              # See also +InstanceMethods+.
         | 
| 12 19 | 
             
              module ClassMethods
         | 
| 13 20 | 
             
                include Mappings
         | 
| 14 21 |  | 
| 15 | 
            -
                 | 
| 16 | 
            -
                  other.instance_eval do
         | 
| 17 | 
            -
                    @mappings = Mapper.new
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
                end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                #    mappings -> Mapper
         | 
| 22 | 
            +
                #    mapper -> Mapper
         | 
| 22 23 | 
             
                #
         | 
| 23 | 
            -
                # Returns  | 
| 24 | 
            -
                attr_reader : | 
| 24 | 
            +
                # Returns the mapper for the class.
         | 
| 25 | 
            +
                attr_reader :mapper
         | 
| 25 26 |  | 
| 26 27 | 
             
                #    namespaces(hash) -> Hash
         | 
| 27 28 | 
             
                #    namespaces       -> Hash
         | 
| @@ -36,8 +37,8 @@ module Peanuts #:nodoc: | |
| 36 37 | 
             
                #      namespaces :lol => 'urn:lol', ...
         | 
| 37 38 | 
             
                #      ...
         | 
| 38 39 | 
             
                #    end
         | 
| 39 | 
            -
                def namespaces( | 
| 40 | 
            -
                   | 
| 40 | 
            +
                def namespaces(map = nil)
         | 
| 41 | 
            +
                  map ? mapper.namespaces.update(map) : mapper.namespaces
         | 
| 41 42 | 
             
                end
         | 
| 42 43 |  | 
| 43 44 | 
             
                #    root(xmlname[, :xmlns => ...]) -> Mappings::Root
         | 
| @@ -58,8 +59,8 @@ module Peanuts #:nodoc: | |
| 58 59 | 
             
                #      ...
         | 
| 59 60 | 
             
                #    end
         | 
| 60 61 | 
             
                def root(xmlname = nil, options = {})
         | 
| 61 | 
            -
                   | 
| 62 | 
            -
                   | 
| 62 | 
            +
                  mapper.root = Root.new(xmlname, prepare_options(options)) if xmlname
         | 
| 63 | 
            +
                  mapper.root
         | 
| 63 64 | 
             
                end
         | 
| 64 65 |  | 
| 65 66 | 
             
                #    element(name, [type[, options]])   -> Mappings::Element or Mappings::ElementValue
         | 
| @@ -81,10 +82,10 @@ module Peanuts #:nodoc: | |
| 81 82 | 
             
                #      element :cheeseburger, Cheeseburger, :xmlname => :cheezburger
         | 
| 82 83 | 
             
                #      ...
         | 
| 83 84 | 
             
                #    end
         | 
| 84 | 
            -
                def element(name,  | 
| 85 | 
            -
                  prepare_args( | 
| 85 | 
            +
                def element(name, *args, &block)
         | 
| 86 | 
            +
                  prepare_args(args, block) do |type, options|
         | 
| 86 87 | 
             
                    define_accessor name
         | 
| 87 | 
            -
                    ( | 
| 88 | 
            +
                    (mapper << (type.is_a?(Class) ? Element : ElementValue).new(name, type, options)).last
         | 
| 88 89 | 
             
                  end
         | 
| 89 90 | 
             
                end
         | 
| 90 91 |  | 
| @@ -107,10 +108,10 @@ module Peanuts #:nodoc: | |
| 107 108 | 
             
                #      elements :cheeseburgers, Cheeseburger, :xmlname => :cheezburger
         | 
| 108 109 | 
             
                #      ...
         | 
| 109 110 | 
             
                #    end
         | 
| 110 | 
            -
                def elements(name,  | 
| 111 | 
            -
                  prepare_args( | 
| 111 | 
            +
                def elements(name, *args, &block)
         | 
| 112 | 
            +
                  prepare_args(args, block) do |type, options|
         | 
| 112 113 | 
             
                    define_accessor name
         | 
| 113 | 
            -
                    ( | 
| 114 | 
            +
                    (mapper << (type.is_a?(Class) ? Elements : ElementValues).new(name, type, options)).last
         | 
| 114 115 | 
             
                  end
         | 
| 115 116 | 
             
                end
         | 
| 116 117 |  | 
| @@ -131,14 +132,16 @@ module Peanuts #:nodoc: | |
| 131 132 | 
             
                #      element :cheeseburger, Cheeseburger, :xmlname => :cheezburger
         | 
| 132 133 | 
             
                #      ...
         | 
| 133 134 | 
             
                #    end
         | 
| 134 | 
            -
                def attribute(name,  | 
| 135 | 
            -
                   | 
| 136 | 
            -
             | 
| 135 | 
            +
                def attribute(name, *args)
         | 
| 136 | 
            +
                  prepare_args(args, nil, :xmlns => nil) do |type, options|
         | 
| 137 | 
            +
                    define_accessor name
         | 
| 138 | 
            +
                    mapper << Attribute.new(name, type, options)
         | 
| 139 | 
            +
                  end
         | 
| 137 140 | 
             
                end
         | 
| 138 141 |  | 
| 139 142 | 
             
                def schema(schema = nil)
         | 
| 140 | 
            -
                   | 
| 141 | 
            -
                   | 
| 143 | 
            +
                  mapper.schema = schema if schema
         | 
| 144 | 
            +
                  mapper.schema
         | 
| 142 145 | 
             
                end
         | 
| 143 146 |  | 
| 144 147 | 
             
                def restore(reader)
         | 
| @@ -146,70 +149,49 @@ module Peanuts #:nodoc: | |
| 146 149 | 
             
                  e && _restore(e)
         | 
| 147 150 | 
             
                end
         | 
| 148 151 |  | 
| 149 | 
            -
                def restore_from( | 
| 150 | 
            -
                  _source_or_dest( | 
| 152 | 
            +
                def restore_from(*args)
         | 
| 153 | 
            +
                  _source_or_dest(*args) do |source_type, source, options|
         | 
| 151 154 | 
             
                    restore(XML::Reader.new(source, source_type, options))
         | 
| 152 155 | 
             
                  end
         | 
| 153 156 | 
             
                end
         | 
| 154 157 |  | 
| 155 158 | 
             
                def save(nut, writer)
         | 
| 156 159 | 
             
                  _save(nut, writer)
         | 
| 160 | 
            +
                  writer.result
         | 
| 157 161 | 
             
                end
         | 
| 158 162 |  | 
| 159 | 
            -
                def  | 
| 160 | 
            -
                  options | 
| 161 | 
            -
                   | 
| 162 | 
            -
                   | 
| 163 | 
            -
                   | 
| 164 | 
            -
                end
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                def build_node(nut, node) #:nodoc:
         | 
| 167 | 
            -
                  backend.add_namespaces(node, namespaces)
         | 
| 168 | 
            -
                  callem(:to_xml, nut, node)
         | 
| 169 | 
            -
                  node
         | 
| 170 | 
            -
                end
         | 
| 171 | 
            -
             | 
| 172 | 
            -
                def parse_events(nut, events) #:nodoc:
         | 
| 173 | 
            -
                  @mappings.parse(nut, events)
         | 
| 174 | 
            -
                end
         | 
| 175 | 
            -
             | 
| 176 | 
            -
                def _source_or_dest(a, b)
         | 
| 177 | 
            -
                  a, b = :string, a unless a.is_a?(Symbol)
         | 
| 178 | 
            -
                  yield a, b
         | 
| 163 | 
            +
                def _source_or_dest(*args)
         | 
| 164 | 
            +
                  options = args.last.is_a?(Hash) ? args.pop : {}
         | 
| 165 | 
            +
                  type, source = *args
         | 
| 166 | 
            +
                  type, source = :string, type unless type.is_a?(Symbol)
         | 
| 167 | 
            +
                  yield type, source, options
         | 
| 179 168 | 
             
                end
         | 
| 180 169 |  | 
| 181 170 | 
             
                private
         | 
| 182 | 
            -
                def _restore( | 
| 183 | 
            -
                  nut = new
         | 
| 184 | 
            -
                  @mappings.parse(nut, events)
         | 
| 171 | 
            +
                def _restore(reader)
         | 
| 172 | 
            +
                  mapper.restore(nut = new, reader)
         | 
| 185 173 | 
             
                  nut
         | 
| 186 174 | 
             
                end
         | 
| 187 175 |  | 
| 188 | 
            -
                def _save(nut,  | 
| 189 | 
            -
                   | 
| 176 | 
            +
                def _save(nut, writer)
         | 
| 177 | 
            +
                  mapper.save(nut, writer)
         | 
| 190 178 | 
             
                end
         | 
| 191 179 |  | 
| 192 | 
            -
                def prepare_args( | 
| 193 | 
            -
                   | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 201 | 
            -
                      end
         | 
| 202 | 
            -
                    end
         | 
| 203 | 
            -
                  else
         | 
| 204 | 
            -
                    options = prepare_options(options)
         | 
| 205 | 
            -
                    yield type, options
         | 
| 206 | 
            -
                  end
         | 
| 180 | 
            +
                def prepare_args(args, blk, defopt = nil)
         | 
| 181 | 
            +
                  type, options = *args
         | 
| 182 | 
            +
                  type, options = (blk ? Class.new : :string), type if type.nil? || type.is_a?(Hash)
         | 
| 183 | 
            +
                  options ||= {}
         | 
| 184 | 
            +
                  options = defopt.merge(options) if defopt
         | 
| 185 | 
            +
                  options = prepare_options(options)
         | 
| 186 | 
            +
                  m = yield(type, options)
         | 
| 187 | 
            +
                  Peanuts.init(type, mapper.namespaces, m.xmlns, &blk) if blk
         | 
| 188 | 
            +
                  m
         | 
| 207 189 | 
             
                end
         | 
| 208 190 |  | 
| 209 191 | 
             
                def prepare_options(options)
         | 
| 210 | 
            -
                  ns = options.fetch(:xmlns) {|k| options[k] = root && root.xmlns ||  | 
| 192 | 
            +
                  ns = options.fetch(:xmlns) {|k| options[k] = root && root.xmlns || mapper.default_ns }
         | 
| 211 193 | 
             
                  if ns.is_a?(Symbol)
         | 
| 212 | 
            -
                    raise ArgumentError, "undefined prefix: #{ns}" unless options[:xmlns] = namespaces[ns]
         | 
| 194 | 
            +
                    raise ArgumentError, "undefined prefix: #{ns}" unless options[:xmlns] = mapper.namespaces[ns]
         | 
| 213 195 | 
             
                    options[:prefix] = ns
         | 
| 214 196 | 
             
                  end
         | 
| 215 197 | 
             
                  options
         | 
| @@ -217,47 +199,50 @@ module Peanuts #:nodoc: | |
| 217 199 |  | 
| 218 200 | 
             
                def define_accessor(name)
         | 
| 219 201 | 
             
                  if method_defined?(name) || method_defined?("#{name}=")
         | 
| 220 | 
            -
                    raise ArgumentError, "#{name}: name already defined or reserved"
         | 
| 202 | 
            +
                    raise ArgumentError, "#{name.inspect}: name already defined or reserved"
         | 
| 221 203 | 
             
                  end
         | 
| 222 204 | 
             
                  attr_accessor name
         | 
| 223 205 | 
             
                end
         | 
| 224 206 | 
             
              end
         | 
| 225 207 |  | 
| 226 | 
            -
               | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 208 | 
            +
              # See also +ClassMethods+
         | 
| 209 | 
            +
              module InstanceMethods
         | 
| 210 | 
            +
                def parse(source, options = {})
         | 
| 211 | 
            +
                  backend.parse(source, options) {|node| parse_node(node) }
         | 
| 212 | 
            +
                end
         | 
| 229 213 |  | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 214 | 
            +
                def save(writer)
         | 
| 215 | 
            +
                  self.class.save(self, writer)
         | 
| 216 | 
            +
                end
         | 
| 233 217 |  | 
| 234 | 
            -
             | 
| 235 | 
            -
             | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
             | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 251 | 
            -
             | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
             | 
| 260 | 
            -
             | 
| 218 | 
            +
                #    build([options])              -> root element or string
         | 
| 219 | 
            +
                #    build([options])              -> root element or string
         | 
| 220 | 
            +
                #    build(destination[, options]) -> destination
         | 
| 221 | 
            +
                #
         | 
| 222 | 
            +
                # Defines attribute mapping.
         | 
| 223 | 
            +
                #
         | 
| 224 | 
            +
                # === Arguments
         | 
| 225 | 
            +
                # [+destination+]
         | 
| 226 | 
            +
                #   Can be given a symbol a backend-specific object, an instance of String or IO classes.
         | 
| 227 | 
            +
                #   [<tt>:string</tt>]   will return an XML string.
         | 
| 228 | 
            +
                #   [<tt>:document</tt>] will return a backend specific document object.
         | 
| 229 | 
            +
                #   [<tt>:object</tt>]   will return a backend specific object. New document will be created.
         | 
| 230 | 
            +
                #   [an instance of +String+] the contents of the string will be replaced with the generated XML.
         | 
| 231 | 
            +
                #   [an instance of +IO+]     the IO will be written to.
         | 
| 232 | 
            +
                # [+options+] Backend-specific options
         | 
| 233 | 
            +
                #
         | 
| 234 | 
            +
                # === Example:
         | 
| 235 | 
            +
                #    cat = Cat.new
         | 
| 236 | 
            +
                #    cat.name = 'Pussy'
         | 
| 237 | 
            +
                #    puts cat.save_to(:string)
         | 
| 238 | 
            +
                #    ...
         | 
| 239 | 
            +
                #    doc = LibXML::XML::Document.new
         | 
| 240 | 
            +
                #    cat.save_to(doc)
         | 
| 241 | 
            +
                #    puts doc.to_s
         | 
| 242 | 
            +
                def save_to(*args)
         | 
| 243 | 
            +
                  self.class._source_or_dest(*args) do |dest_type, dest, options|
         | 
| 244 | 
            +
                    save(XML::Writer.new(dest, dest_type, options))
         | 
| 245 | 
            +
                  end
         | 
| 261 246 | 
             
                end
         | 
| 262 247 | 
             
              end
         | 
| 263 248 | 
             
            end
         | 
    
        data/lib/peanuts/xml.rb
    CHANGED
    
    | @@ -1 +1,78 @@ | |
| 1 | 
            -
            require ' | 
| 1 | 
            +
            require 'enumerator'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Hash
         | 
| 4 | 
            +
              def from_namespace(ns)
         | 
| 5 | 
            +
                rx = /^#{Regexp.quote(ns.to_s)}_(.*)$/
         | 
| 6 | 
            +
                inject({}) do |a, p|
         | 
| 7 | 
            +
                  a[$1.to_sym] = p[1] if p[0].to_s =~ rx
         | 
| 8 | 
            +
                  a
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def from_namespace!(ns)
         | 
| 13 | 
            +
                h = from_namespace(ns)
         | 
| 14 | 
            +
                h.each_key {|k| delete(:"#{ns}_#{k}") }
         | 
| 15 | 
            +
                h
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            module Peanuts
         | 
| 20 | 
            +
              module XML
         | 
| 21 | 
            +
                autoload :LibXML, 'peanuts/xml/libxml'
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def self.default
         | 
| 24 | 
            +
                  @@default ||= LibXML
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def self.schema(schema_type, source, source_type = :string)
         | 
| 28 | 
            +
                  default.schema(schema_type, source, source_type)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def self.method_missing(method, *args, &block)
         | 
| 32 | 
            +
                  case method.to_s
         | 
| 33 | 
            +
                  when /^(.*)_schema_from_(.*)$/
         | 
| 34 | 
            +
                    XML.schema($1.to_sym, args.first, $2.to_sym)
         | 
| 35 | 
            +
                  else
         | 
| 36 | 
            +
                    super
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                class Reader
         | 
| 41 | 
            +
                  include Enumerable
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def self.new(*args, &block)
         | 
| 44 | 
            +
                    cls = self == Reader ? XML.default::Reader : self
         | 
| 45 | 
            +
                    obj = cls.allocate
         | 
| 46 | 
            +
                    obj.send(:initialize, *args, &block)
         | 
| 47 | 
            +
                    obj
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  def self.method_missing(method, *args, &block)
         | 
| 51 | 
            +
                    case method.to_s
         | 
| 52 | 
            +
                    when /^from_(.*)$/
         | 
| 53 | 
            +
                      new(args.first, $1.to_sym, &block)
         | 
| 54 | 
            +
                    else
         | 
| 55 | 
            +
                      super
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                class Writer
         | 
| 61 | 
            +
                  def self.new(*args, &block)
         | 
| 62 | 
            +
                    cls = self == Writer ? XML.default::Writer : self
         | 
| 63 | 
            +
                    obj = cls.allocate
         | 
| 64 | 
            +
                    obj.send(:initialize, *args, &block)
         | 
| 65 | 
            +
                    obj
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                  def self.method_missing(method, *args, &block)
         | 
| 69 | 
            +
                    case method.to_s
         | 
| 70 | 
            +
                    when /^from_(.*)$/
         | 
| 71 | 
            +
                      new(args.first, $1.to_sym, &block)
         | 
| 72 | 
            +
                    else
         | 
| 73 | 
            +
                      super
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
            end
         | 
    
        data/lib/peanuts/xml/libxml.rb
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            require 'libxml'
         | 
| 2 2 | 
             
            require 'forwardable'
         | 
| 3 | 
            -
            require 'peanuts/xml | 
| 3 | 
            +
            require 'peanuts/xml'
         | 
| 4 4 |  | 
| 5 5 | 
             
            module Peanuts
         | 
| 6 6 | 
             
              module XML
         | 
| @@ -14,7 +14,7 @@ module Peanuts | |
| 14 14 | 
             
                      when :io
         | 
| 15 15 | 
             
                        dest
         | 
| 16 16 | 
             
                      when :document
         | 
| 17 | 
            -
                        dest || LibXML::XML::Document.new
         | 
| 17 | 
            +
                        dest || ::LibXML::XML::Document.new
         | 
| 18 18 | 
             
                      else
         | 
| 19 19 | 
             
                        raise ArgumentError, "unrecognized destination type #{dest_type.inspect}"
         | 
| 20 20 | 
             
                      end
         | 
| @@ -24,31 +24,31 @@ module Peanuts | |
| 24 24 | 
             
                      @dest
         | 
| 25 25 | 
             
                    end
         | 
| 26 26 |  | 
| 27 | 
            -
                     | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 27 | 
            +
                    def value=(value)
         | 
| 28 | 
            +
                      case @node
         | 
| 29 | 
            +
                      when ::LibXML::XML::Attr
         | 
| 30 | 
            +
                        @node.value = value || ''
         | 
| 31 | 
            +
                      else
         | 
| 32 | 
            +
                        @node.content = value || ''
         | 
| 33 | 
            +
                      end
         | 
| 31 34 | 
             
                    end
         | 
| 32 35 |  | 
| 33 36 | 
             
                    def write(node_type, local_name = nil, namespace_uri = nil, prefix = nil)
         | 
| 34 | 
            -
                       | 
| 35 | 
            -
             | 
| 37 | 
            +
                      case node_type
         | 
| 38 | 
            +
                      when :element
         | 
| 39 | 
            +
                        @node = ::LibXML::XML::Node.new(local_name)
         | 
| 40 | 
            +
                        @parent << @node if @parent
         | 
| 41 | 
            +
                        @node.namespaces.namespace = mkns(@node, namespace_uri, prefix) if namespace_uri
         | 
| 42 | 
            +
                      when :attribute
         | 
| 43 | 
            +
                        @node = ::LibXML::XML::Attr.new(@parent, local_name, '', namespace_uri && mkns(@parent, namespace_uri, prefix))
         | 
| 36 44 | 
             
                      else
         | 
| 37 | 
            -
                         | 
| 45 | 
            +
                        raise "unsupported node type #{node_type.inspect}"
         | 
| 38 46 | 
             
                      end
         | 
| 39 47 |  | 
| 40 | 
            -
                      @node_type = node_type
         | 
| 41 | 
            -
                      @local_name, @namespace_uri, @prefix = local_name, namespace_uri, prefix && prefix.to_s
         | 
| 42 | 
            -
             | 
| 43 48 | 
             
                      exparent, @parent = @parent, @node
         | 
| 44 49 |  | 
| 45 50 | 
             
                      yield self
         | 
| 46 51 |  | 
| 47 | 
            -
                      if @node_type
         | 
| 48 | 
            -
                        mknode
         | 
| 49 | 
            -
                      end
         | 
| 50 | 
            -
                      @node = nil
         | 
| 51 | 
            -
             | 
| 52 52 | 
             
                      if exparent.nil?
         | 
| 53 53 | 
             
                        case @dest_type
         | 
| 54 54 | 
             
                        when :string, :io
         | 
| @@ -62,22 +62,11 @@ module Peanuts | |
| 62 62 | 
             
                    end
         | 
| 63 63 |  | 
| 64 64 | 
             
                    private
         | 
| 65 | 
            -
                    def  | 
| 66 | 
            -
                       | 
| 67 | 
            -
                       | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
                          ns = @parent && @parent.namespaces.find_by_href(@namespace_uri)
         | 
| 71 | 
            -
                          n.namespaces.namespace = ns && ns.prefix == @prefix ? ns : ::LibXML::XML::Namespace.new(n, @prefix, @namespace_uri)
         | 
| 72 | 
            -
                        end
         | 
| 73 | 
            -
                        @parent << n if @parent
         | 
| 74 | 
            -
                        n
         | 
| 75 | 
            -
                      when :attribute
         | 
| 76 | 
            -
                        ::LibXML::XML::Attr.new(@parent, @local_name, @value, @namespace_uri)
         | 
| 77 | 
            -
                      else
         | 
| 78 | 
            -
                        raise "unsupported node type #{@node_type.inspect}"
         | 
| 79 | 
            -
                      end
         | 
| 80 | 
            -
                      clear
         | 
| 65 | 
            +
                    def mkns(node, namespace_uri, prefix)
         | 
| 66 | 
            +
                      prefix = prefix && prefix.to_s
         | 
| 67 | 
            +
                      ns = node && node.namespaces.find_by_href(namespace_uri)
         | 
| 68 | 
            +
                      ns = ::LibXML::XML::Namespace.new(node, prefix, namespace_uri) unless ns && ns.prefix == prefix
         | 
| 69 | 
            +
                      ns
         | 
| 81 70 | 
             
                    end
         | 
| 82 71 | 
             
                  end
         | 
| 83 72 |  | 
    
        data/spec/cat_spec.rb
    ADDED
    
    | @@ -0,0 +1,142 @@ | |
| 1 | 
            +
            $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'bigdecimal'
         | 
| 4 | 
            +
            require 'test/unit'
         | 
| 5 | 
            +
            require 'rubygems'
         | 
| 6 | 
            +
            require 'shoulda'
         | 
| 7 | 
            +
            require 'peanuts'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
             | 
| 10 | 
            +
            class Cheezburger
         | 
| 11 | 
            +
              include Peanuts
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              attribute :weight, :float
         | 
| 14 | 
            +
              attribute :price, :decimal
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              def initialize(weight = nil, price = nil)
         | 
| 17 | 
            +
                @weight, @price = weight, price
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def eql?(other)
         | 
| 21 | 
            +
                other && weight == other.weight && price == other.price
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              alias == eql?
         | 
| 25 | 
            +
            end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            class Cat
         | 
| 28 | 
            +
              include Peanuts
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              namespaces :lol => 'urn:x-lol', :kthnx => 'urn:x-lol:kthnx'
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              root 'kitteh', :xmlns => :lol
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              attribute :has_tail, :boolean, :xmlname => 'has-tail', :xmlns => :kthnx
         | 
| 35 | 
            +
              attribute :ears, :integer
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              element :ration, [:string], :xmlname => :eats, :xmlns => :kthnx
         | 
| 38 | 
            +
              element :name, :xmlns => 'urn:x-lol:kthnx'
         | 
| 39 | 
            +
              elements :paws, :xmlname => :paw
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              element :friends, :xmlname => :pals do
         | 
| 42 | 
            +
                elements :names, :xmlname => :pal
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              element :cheezburger, Cheezburger
         | 
| 46 | 
            +
              element :moar_cheezburgers do
         | 
| 47 | 
            +
                elements :cheezburger, Cheezburger
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            shared_examples_for 'my cat' do
         | 
| 52 | 
            +
              it 'should be named Silly Tom' do
         | 
| 53 | 
            +
                @cat.name.should eql 'Silly Tom'
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              it 'should eat tigers and lions' do
         | 
| 57 | 
            +
                @cat.ration.should eql %w(tigers lions)
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              it 'should be a friend of Chrissy, Missy & Sissy' do
         | 
| 61 | 
            +
                @cat.friends.names.should eql ['Chrissy', 'Missy', 'Sissy']
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              it 'should have 2 ears' do
         | 
| 65 | 
            +
                @cat.ears.should eql 2
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              it 'should have a tail' do
         | 
| 69 | 
            +
                @cat.has_tail.should be_true
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              it 'should have four paws' do
         | 
| 73 | 
            +
                @cat.paws.should eql %w(one two three four)
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              it 'should has cheezburger' do
         | 
| 77 | 
            +
                @cat.cheezburger.should be_kind_of Cheezburger
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
              it 'should has 2 moar good cheezburgerz' do
         | 
| 81 | 
            +
                @cat.moar_cheezburgers.cheezburger.should eql [
         | 
| 82 | 
            +
                  Cheezburger.new(685.940, BigDecimal('19')),
         | 
| 83 | 
            +
                  Cheezburger.new(9356.7, BigDecimal('7.40'))]
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
            end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            shared_examples_for 'my cheezburger' do
         | 
| 88 | 
            +
              it 'should weigh 14.5547 pounds' do
         | 
| 89 | 
            +
                @cheezburger.weight.should eql 14.5547
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
              it 'should cost $2.05' do
         | 
| 93 | 
            +
                @cheezburger.price.should eql BigDecimal('2.05')
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
            end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            shared_examples_for 'sample kitteh' do
         | 
| 98 | 
            +
              before :all do
         | 
| 99 | 
            +
                @xml_fragment = <<-EOS
         | 
| 100 | 
            +
                    <kitteh xmlns='urn:x-lol' xmlns:kthnx='urn:x-lol:kthnx' ears=' 2 ' kthnx:has-tail=' yes  '>
         | 
| 101 | 
            +
                      <name xmlns='urn:x-lol:kthnx'>
         | 
| 102 | 
            +
                          Silly
         | 
| 103 | 
            +
                          Tom
         | 
| 104 | 
            +
                      </name>
         | 
| 105 | 
            +
                      <kthnx:eats>
         | 
| 106 | 
            +
                        tigers
         | 
| 107 | 
            +
                        lions
         | 
| 108 | 
            +
                      </kthnx:eats>
         | 
| 109 | 
            +
                      <pals>
         | 
| 110 | 
            +
                        <pal>Chrissy</pal>
         | 
| 111 | 
            +
                        <pal>Missy</pal>
         | 
| 112 | 
            +
                        <pal>Sissy</pal>
         | 
| 113 | 
            +
                      </pals>
         | 
| 114 | 
            +
                      <paw>  one</paw>
         | 
| 115 | 
            +
                      <paw> two </paw>
         | 
| 116 | 
            +
                      <paw>three</paw>
         | 
| 117 | 
            +
                      <paw>four</paw>
         | 
| 118 | 
            +
                      <cheezburger price='2.05' weight='14.5547' />
         | 
| 119 | 
            +
                      <moar_cheezburgers>
         | 
| 120 | 
            +
                        <cheezburger price='19' weight='685.940' />
         | 
| 121 | 
            +
                        <cheezburger price='7.40' weight='9356.7' />
         | 
| 122 | 
            +
                      </moar_cheezburgers>
         | 
| 123 | 
            +
                    </kitteh>
         | 
| 124 | 
            +
                EOS
         | 
| 125 | 
            +
                @cat = Cat.restore_from(@xml_fragment)
         | 
| 126 | 
            +
                @cheezburger = @cat.cheezburger
         | 
| 127 | 
            +
              end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
              it_should_behave_like 'my cat', 'my cheezburger'
         | 
| 130 | 
            +
            end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
            describe 'My cat' do
         | 
| 133 | 
            +
              it_should_behave_like 'sample kitteh'
         | 
| 134 | 
            +
            end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
            describe 'My cat saved and restored' do
         | 
| 137 | 
            +
              it_should_behave_like 'sample kitteh'
         | 
| 138 | 
            +
             | 
| 139 | 
            +
              before :all do
         | 
| 140 | 
            +
                @cat = Cat.restore_from(@cat.save_to(:string))
         | 
| 141 | 
            +
              end
         | 
| 142 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: omg-peanuts
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              version: 2.0. | 
| 4 | 
            +
              version: 2.0.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - Igor Gunko
         | 
| @@ -9,7 +9,7 @@ autorequire: | |
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 11 |  | 
| 12 | 
            -
            date: 2009-09- | 
| 12 | 
            +
            date: 2009-09-25 00:00:00 -07:00
         | 
| 13 13 | 
             
            default_executable: 
         | 
| 14 14 | 
             
            dependencies: 
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -23,14 +23,14 @@ dependencies: | |
| 23 23 | 
             
                    version: 1.1.3
         | 
| 24 24 | 
             
                version: 
         | 
| 25 25 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 26 | 
            -
              name:  | 
| 26 | 
            +
              name: rspec
         | 
| 27 27 | 
             
              type: :development
         | 
| 28 28 | 
             
              version_requirement: 
         | 
| 29 29 | 
             
              version_requirements: !ruby/object:Gem::Requirement 
         | 
| 30 30 | 
             
                requirements: 
         | 
| 31 31 | 
             
                - - ">="
         | 
| 32 32 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 33 | 
            -
                    version: 2. | 
| 33 | 
            +
                    version: 1.2.8
         | 
| 34 34 | 
             
                version: 
         | 
| 35 35 | 
             
            description: Peanuts is an XML to Ruby and back again mapping library.
         | 
| 36 36 | 
             
            email: tekmon@gmail.com
         | 
| @@ -52,7 +52,6 @@ files: | |
| 52 52 | 
             
            - lib/peanuts/converters.rb
         | 
| 53 53 | 
             
            - lib/peanuts/mapper.rb
         | 
| 54 54 | 
             
            - lib/peanuts/xml.rb
         | 
| 55 | 
            -
            - lib/peanuts/xml/reader.rb
         | 
| 56 55 | 
             
            - lib/peanuts/xml/libxml.rb
         | 
| 57 56 | 
             
            has_rdoc: true
         | 
| 58 57 | 
             
            homepage: http://github.com/omg/peanuts
         | 
| @@ -84,4 +83,4 @@ signing_key: | |
| 84 83 | 
             
            specification_version: 2
         | 
| 85 84 | 
             
            summary: Making XML <-> Ruby binding easy
         | 
| 86 85 | 
             
            test_files: 
         | 
| 87 | 
            -
            -  | 
| 86 | 
            +
            - spec/cat_spec.rb
         | 
    
        data/lib/peanuts/xml/reader.rb
    DELETED
    
    | @@ -1,78 +0,0 @@ | |
| 1 | 
            -
            require 'enumerator'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            class Hash
         | 
| 4 | 
            -
              def from_namespace(ns)
         | 
| 5 | 
            -
                rx = /^#{Regexp.quote(ns.to_s)}_(.*)$/
         | 
| 6 | 
            -
                inject({}) do |a, p|
         | 
| 7 | 
            -
                  a[$1.to_sym] = p[1] if p[0].to_s =~ rx
         | 
| 8 | 
            -
                  a
         | 
| 9 | 
            -
                end
         | 
| 10 | 
            -
              end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
              def from_namespace!(ns)
         | 
| 13 | 
            -
                h = from_namespace(ns)
         | 
| 14 | 
            -
                h.each_key {|k| delete(:"#{ns}_#{k}") }
         | 
| 15 | 
            -
                h
         | 
| 16 | 
            -
              end
         | 
| 17 | 
            -
            end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
            module Peanuts
         | 
| 20 | 
            -
              module XML
         | 
| 21 | 
            -
                autoload :LibXML, 'peanuts/xml/libxml'
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                def self.default
         | 
| 24 | 
            -
                  @@default ||= LibXML
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                def self.schema(schema_type, source, source_type = :string)
         | 
| 28 | 
            -
                  default.schema(schema_type, source, source_type)
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
             
         | 
| 31 | 
            -
                def self.method_missing(method, *args, &block)
         | 
| 32 | 
            -
                  case method.to_s
         | 
| 33 | 
            -
                  when /^(.*)_schema_from_(.*)$/
         | 
| 34 | 
            -
                    XML.schema($1.to_sym, args.first, $2.to_sym)
         | 
| 35 | 
            -
                  else
         | 
| 36 | 
            -
                    super
         | 
| 37 | 
            -
                  end
         | 
| 38 | 
            -
                end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                class Reader
         | 
| 41 | 
            -
                  include Enumerable
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                  def self.new(*args, &block)
         | 
| 44 | 
            -
                    cls = self == Reader ? XML.default::Reader : self
         | 
| 45 | 
            -
                    obj = cls.allocate
         | 
| 46 | 
            -
                    obj.send(:initialize, *args, &block)
         | 
| 47 | 
            -
                    obj
         | 
| 48 | 
            -
                  end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  def self.method_missing(method, *args, &block)
         | 
| 51 | 
            -
                    case method.to_s
         | 
| 52 | 
            -
                    when /^from_(.*)$/
         | 
| 53 | 
            -
                      new(args.first, $1.to_sym, &block)
         | 
| 54 | 
            -
                    else
         | 
| 55 | 
            -
                      super
         | 
| 56 | 
            -
                    end
         | 
| 57 | 
            -
                  end
         | 
| 58 | 
            -
                end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                class Writer
         | 
| 61 | 
            -
                  def self.new(*args, &block)
         | 
| 62 | 
            -
                    cls = self == Writer ? XML.default::Writer : self
         | 
| 63 | 
            -
                    obj = cls.allocate
         | 
| 64 | 
            -
                    obj.send(:initialize, *args, &block)
         | 
| 65 | 
            -
                    obj
         | 
| 66 | 
            -
                  end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                  def self.method_missing(method, *args, &block)
         | 
| 69 | 
            -
                    case method.to_s
         | 
| 70 | 
            -
                    when /^from_(.*)$/
         | 
| 71 | 
            -
                      new(args.first, $1.to_sym, &block)
         | 
| 72 | 
            -
                    else
         | 
| 73 | 
            -
                      super
         | 
| 74 | 
            -
                    end
         | 
| 75 | 
            -
                  end
         | 
| 76 | 
            -
                end
         | 
| 77 | 
            -
              end
         | 
| 78 | 
            -
            end
         | 
    
        data/test/parsing_test.rb
    DELETED
    
    | @@ -1,115 +0,0 @@ | |
| 1 | 
            -
            #$:.unshift File.join(File.dirname(__FILE__),'..','lib')
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require 'bigdecimal'
         | 
| 4 | 
            -
            require 'test/unit'
         | 
| 5 | 
            -
            require 'rubygems'
         | 
| 6 | 
            -
            require 'shoulda'
         | 
| 7 | 
            -
            require 'lib/peanuts'
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
            class Cheezburger
         | 
| 11 | 
            -
              include Peanuts
         | 
| 12 | 
            -
             | 
| 13 | 
            -
              attribute :weight, :float
         | 
| 14 | 
            -
              attribute :price, :decimal
         | 
| 15 | 
            -
            end
         | 
| 16 | 
            -
             | 
| 17 | 
            -
            class Cat
         | 
| 18 | 
            -
              include Peanuts
         | 
| 19 | 
            -
             | 
| 20 | 
            -
              namespaces :lol => 'urn:x-lol', :kthnx => 'urn:x-lol:kthnx'
         | 
| 21 | 
            -
             | 
| 22 | 
            -
              root 'kitteh', :xmlns => :lol
         | 
| 23 | 
            -
             | 
| 24 | 
            -
              attribute :has_tail, :boolean, :xmlname => 'has-tail', :xmlns => :kthnx
         | 
| 25 | 
            -
              attribute :ears, :integer
         | 
| 26 | 
            -
             | 
| 27 | 
            -
              element :ration, [:string], :xmlname => :eats, :xmlns => :kthnx
         | 
| 28 | 
            -
              element :name, :string, :xmlns => 'urn:x-lol:kthnx'
         | 
| 29 | 
            -
              elements :paws, :string, :xmlname => :paw
         | 
| 30 | 
            -
             | 
| 31 | 
            -
              element :friends, :xmlname => :pals do
         | 
| 32 | 
            -
                elements :names, :string, :xmlname => :pal
         | 
| 33 | 
            -
              end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
              element :cheezburger, Cheezburger
         | 
| 36 | 
            -
              element :moar_cheezburgers do
         | 
| 37 | 
            -
                elements :cheezburger, Cheezburger
         | 
| 38 | 
            -
              end
         | 
| 39 | 
            -
            end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
            class ParsingTest < Test::Unit::TestCase
         | 
| 42 | 
            -
              def setup
         | 
| 43 | 
            -
                @xml_fragment = <<-EOS
         | 
| 44 | 
            -
                    <kitteh xmlns='urn:x-lol' xmlns:kthnx='urn:x-lol:kthnx' ears=' 2 ' kthnx:has-tail=' yes  '>
         | 
| 45 | 
            -
                      <name xmlns='urn:x-lol:kthnx'>
         | 
| 46 | 
            -
                          Silly
         | 
| 47 | 
            -
                          Tom
         | 
| 48 | 
            -
                      </name>
         | 
| 49 | 
            -
                      <kthnx:eats>
         | 
| 50 | 
            -
                        tigers
         | 
| 51 | 
            -
                        lions
         | 
| 52 | 
            -
                      </kthnx:eats>
         | 
| 53 | 
            -
                      <pals>
         | 
| 54 | 
            -
                        <pal>Chrissy</pal>
         | 
| 55 | 
            -
                        <pal>Missy</pal>
         | 
| 56 | 
            -
                        <pal>Sissy</pal>
         | 
| 57 | 
            -
                      </pals>
         | 
| 58 | 
            -
                      <paw>  one</paw>
         | 
| 59 | 
            -
                      <paw> two </paw>
         | 
| 60 | 
            -
                      <paw>three</paw>
         | 
| 61 | 
            -
                      <paw>four</paw>
         | 
| 62 | 
            -
                      <cheezburger price='2.05' weight='14.5547' />
         | 
| 63 | 
            -
                      <moar_cheezburgers>
         | 
| 64 | 
            -
                        <cheezburger price='19' weight='685.940' />
         | 
| 65 | 
            -
                        <cheezburger price='7.40' weight='9356.7' />
         | 
| 66 | 
            -
                      </moar_cheezburgers>
         | 
| 67 | 
            -
                    </kitteh>
         | 
| 68 | 
            -
                EOS
         | 
| 69 | 
            -
                @cat = Cat.restore_from(@xml_fragment)
         | 
| 70 | 
            -
              end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
              context "A cat" do
         | 
| 73 | 
            -
                should 'be named Silly Tom' do
         | 
| 74 | 
            -
                  assert_equal 'Silly Tom', @cat.name
         | 
| 75 | 
            -
                end
         | 
| 76 | 
            -
             | 
| 77 | 
            -
                should 'eat tigers and lions' do
         | 
| 78 | 
            -
                  assert_equal %w(tigers lions), @cat.ration
         | 
| 79 | 
            -
                end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                should 'be a friend of Chrissy, Missy & Sissy' do
         | 
| 82 | 
            -
                  assert_equal ['Chrissy', 'Missy', 'Sissy'], @cat.friends.names
         | 
| 83 | 
            -
                end
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                should 'have 2 ears' do
         | 
| 86 | 
            -
                  assert_equal 2, @cat.ears
         | 
| 87 | 
            -
                end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                should 'have a tail' do
         | 
| 90 | 
            -
                  assert @cat.has_tail
         | 
| 91 | 
            -
                end
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                should 'have four paws' do
         | 
| 94 | 
            -
                  assert_equal %w(one two three four), @cat.paws
         | 
| 95 | 
            -
                end
         | 
| 96 | 
            -
             | 
| 97 | 
            -
                should 'has cheezburger' do
         | 
| 98 | 
            -
                  assert_kind_of Cheezburger, @cat.cheezburger
         | 
| 99 | 
            -
                end
         | 
| 100 | 
            -
              end
         | 
| 101 | 
            -
             | 
| 102 | 
            -
              context 'A cheezburger' do
         | 
| 103 | 
            -
                setup do
         | 
| 104 | 
            -
                  @burger = @cat.cheezburger
         | 
| 105 | 
            -
                end
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                should 'weigh 14.5547 pounds' do
         | 
| 108 | 
            -
                  assert_equal 14.5547, @burger.weight
         | 
| 109 | 
            -
                end
         | 
| 110 | 
            -
             | 
| 111 | 
            -
                should 'cost $2.05' do
         | 
| 112 | 
            -
                  assert_equal BigDecimal('2.05'), @burger.price
         | 
| 113 | 
            -
                end
         | 
| 114 | 
            -
              end
         | 
| 115 | 
            -
            end
         |