oxmlk 0.2.3 → 0.3.0

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.3.0
data/examples/example.rb CHANGED
@@ -3,8 +3,8 @@ class Number
3
3
 
4
4
  ox_tag :number
5
5
 
6
- ox_attr :group, :from => :attr
7
- ox_attr(:value, :from => :content)
6
+ ox_attr :group
7
+ ox_elem(:value, :from => :content)
8
8
  end
9
9
 
10
10
  class Email
@@ -12,8 +12,8 @@ class Email
12
12
 
13
13
  ox_tag :email
14
14
 
15
- ox_attr :group, :from => :attr
16
- ox_attr(:value, :from => :content)
15
+ ox_attr :group
16
+ ox_elem(:value, :from => :content)
17
17
  end
18
18
 
19
19
  class Person
@@ -21,12 +21,12 @@ class Person
21
21
 
22
22
  ox_tag :person
23
23
 
24
- ox_attr(:category, :from => :attr)
25
- ox_attr(:alt, :from => '@alt')
24
+ ox_attr :category
25
+ ox_attr :alternate, :from => 'alt'
26
26
 
27
- ox_attr(:name)
28
- ox_attr(:contacts, :as => [Number,Email], :freeze => true)
29
- ox_attr(:friends, :as => [Person], :in => :friends, :freeze => false)
27
+ ox_elem :name
28
+ ox_elem :contacts, :as => [Number,Email]
29
+ ox_elem :friends, :as => [Person], :in => :friends
30
30
 
31
31
  def say_hello(xml)
32
32
  'hello'
data/lib/oxmlk/attr.rb ADDED
@@ -0,0 +1,34 @@
1
+ module OxMlk
2
+ class Attr
3
+ PROCS = (Hash.new {|h,k| k.to_proc rescue nil}).merge(
4
+ Integer => :to_i.to_proc,
5
+ Float => :to_f.to_proc,
6
+ String => :to_s.to_proc,
7
+ Symbol => :to_sym.to_proc,
8
+ :bool => proc {|a| fetch_bool(a)})
9
+
10
+ attr_reader :accessor, :setter,:from, :as, :procs, :tag
11
+
12
+ def initialize(name,o={},&block)
13
+ name = name.to_s
14
+ @accessor = name.chomp('?').intern
15
+ @setter = "#{@accessor}=".intern
16
+ @from = o.delete(:from)
17
+ @tag = (from || accessor).to_s
18
+ @as = o.delete(:as) || (:bool if name.ends_with?('?'))
19
+ @procs = ([*as].map {|k| PROCS[k]} + [block]).compact
20
+ end
21
+
22
+ def from_xml(data)
23
+ procs.inject(XML::Node.from(data)[tag]) {|d,p| p.call(d) rescue d}
24
+ end
25
+
26
+ def self.fetch_bool(value)
27
+ value = value.to_s.downcase
28
+ return true if %w{true yes 1 t}.include? value
29
+ return false if %w{false no 0 f}.include? value
30
+ value
31
+ end
32
+
33
+ end
34
+ end
data/lib/oxmlk/elem.rb ADDED
@@ -0,0 +1,97 @@
1
+ module OxMlk
2
+ class Elem
3
+ PROCS = (Hash.new {|h,k| default_proc(k)}).merge(
4
+ Integer => :to_i.to_proc,
5
+ Float => :to_f.to_proc,
6
+ String => :to_s.to_proc,
7
+ Symbol => :to_sym.to_proc,
8
+ :raw => proc {|e| e},
9
+ :name => proc {|e| e.name},
10
+ :value => proc {|e| e.value},
11
+ :bool => proc {|e| fetch_bool(e.value)})
12
+
13
+ attr_reader :accessor, :setter, :collection, :from, :as, :in, :procs, :block, :tag
14
+
15
+ def initialize(name,o={},&blk)
16
+ @tag = name.to_s
17
+ @accessor = @tag.chomp('?').intern
18
+ @setter = "#{@accessor}=".intern
19
+ @collection = o[:as].is_a?(Array)
20
+
21
+ @from = o[:from]
22
+ @as = [*o.delete(:as)].compact
23
+ @in = o.delete(:in)
24
+
25
+ @procs = as.map {|k| PROCS[k]}
26
+ @procs = [PROCS[:value]] + procs unless [:raw,:name,:value].include?(as.first) || ox?
27
+ @block = blk || (collection ? proc {|x| x} : proc {|x| x.first})
28
+ end
29
+
30
+ def ox?
31
+ return false if as.empty?
32
+ as.all? {|x| x.ox? rescue false}
33
+ end
34
+
35
+ def content?
36
+ @from == :content || @from == '.'
37
+ end
38
+
39
+ def from_xml(data)
40
+ xml = XML::Node.from(data)
41
+ block.call(xml.find(xpath).map do |node|
42
+ procs.inject(node) do |n,p|
43
+ p.call(n)
44
+ end
45
+ end)
46
+ end
47
+
48
+ def to_xml(data)
49
+ value = data.send(accessor)
50
+
51
+ return [] if value.nil?
52
+
53
+ nodes = [*value].map do |node|
54
+ if node.respond_to?(:to_xml)
55
+ node.to_xml
56
+ elsif content?
57
+ XML::Node.new_text(node.to_s)
58
+ else
59
+ XML::Node.new(tag, node.to_s)
60
+ end
61
+ end
62
+ return [] if nodes.empty?
63
+ @in ? [nodes.inject(XML::Node.new(@in)) {|o,n| o << n}] : nodes
64
+ end
65
+
66
+ def xpath
67
+ wrap case @from
68
+ when nil
69
+ ox? ? as.map(&:ox_tag).join('|') : tag
70
+ when String
71
+ from
72
+ when :content
73
+ '.'
74
+ end
75
+ end
76
+
77
+ def self.fetch_bool(value)
78
+ value = value.to_s.downcase
79
+ return true if %w{true yes 1 t}.include? value
80
+ return false if %w{false no 0 f}.include? value
81
+ value
82
+ end
83
+
84
+ def self.default_proc(value)
85
+ return value if value.is_a?(Proc)
86
+ return proc {|x| value.from_xml(x) rescue x} if (value.ox? rescue false)
87
+ return value.to_proc rescue proc {|x| x} if value.respond_to?(:to_proc)
88
+ proc {|x| x.value}
89
+ end
90
+
91
+ private
92
+
93
+ def wrap(xpath)
94
+ (xpath.split('|').map {|x| [@in,x].compact.join('/') }).join('|')
95
+ end
96
+ end
97
+ end
data/lib/oxmlk/xml.rb CHANGED
@@ -28,13 +28,6 @@ module OxMlk
28
28
  raise 'Invalid XML data'
29
29
  end
30
30
  end
31
-
32
- def self.build(name,nodes=[],attributes={})
33
- node = new(name)
34
- nodes.each {|n| node << n}
35
- attributes.each {|x| node[x.first.to_s] = x.last.to_s unless x.last.to_s.blank?}
36
- node
37
- end
38
31
  end
39
32
  end
40
33
  end
data/lib/oxmlk.rb CHANGED
@@ -1,14 +1,20 @@
1
1
  dir = File.dirname(__FILE__)
2
- require File.join(dir, 'oxmlk/xml')
3
- require File.join(dir, 'oxmlk/description')
2
+
3
+ require 'rubygems'
4
4
  require 'activesupport'
5
5
 
6
+ require File.join(dir, 'oxmlk/xml')
7
+ require File.join(dir, 'oxmlk/attr')
8
+ require File.join(dir, 'oxmlk/elem')
9
+
6
10
  module OxMlk
7
11
 
8
12
  def self.included(base)
9
13
  base.class_eval do
10
14
  include InstanceMethods
11
15
  extend ClassMethods
16
+
17
+ @ox_attrs, @ox_elems = [], []
12
18
  end
13
19
  end
14
20
 
@@ -19,32 +25,26 @@ module OxMlk
19
25
  end
20
26
 
21
27
  module ClassMethods
22
- def ox_attrs
23
- @ox_attrs ||= []
24
- end
28
+ attr_accessor :ox_attrs, :ox_elems
25
29
 
26
30
  def ox_attr(name,o={})
27
- new_attr = Description.new(name, o)
28
- ox_attrs << new_attr
29
- attr new_attr.accessor, new_attr.writable?
31
+ new_attr = Attr.new(name, o)
32
+ (@ox_attrs ||= []) << new_attr
33
+ attr_accessor new_attr.accessor
30
34
  end
31
35
 
32
- def ox_attributes
33
- ox_attrs.select {|x| x.attribute?}
34
- end
35
-
36
- def ox_elems
37
- ox_attrs.select {|x| x.elem?}
36
+ def ox_elem(name,o={})
37
+ new_elem = Elem.new(name, o)
38
+ (@ox_elems ||= []) << new_elem
39
+ attr_accessor new_elem.accessor
38
40
  end
39
41
 
40
42
  def ox_tag(tag=false)
41
43
  @ox_tag ||= (tag || self).to_s.split('::').last
42
44
  end
43
45
 
44
- def xml_array(data)
45
- [ ox_tag,
46
- ox_elems.map {|x| x.to_xml(data)}.flatten,
47
- ox_attributes.map {|x| x.to_xml(data)} ]
46
+ def ox?
47
+ true
48
48
  end
49
49
 
50
50
  def from_xml(data)
@@ -52,19 +52,20 @@ module OxMlk
52
52
  raise 'invalid XML' unless xml.name == ox_tag
53
53
 
54
54
  ox = new
55
- ox_attrs.each do |a|
56
- value = a.from_xml(xml,ox)
57
- if ox.respond_to?(a.setter)
58
- ox.send(a.setter,value)
59
- else
60
- ox.instance_variable_set(a.instance_variable,value)
61
- end
62
- end
55
+ (ox_attrs + ox_elems).each {|e| ox.send(e.setter,e.from_xml(xml))}
63
56
  ox
64
57
  end
65
58
 
66
59
  def to_xml(data)
67
- XML::Node.build(*xml_array(data))
60
+ ox = XML::Node.new(ox_tag)
61
+ ox_elems.each do |elem|
62
+ elem.to_xml(data).each{|e| ox << e}
63
+ end
64
+ ox_attrs.each do |a|
65
+ val = data.send(a.accessor).to_s
66
+ ox[a.tag]= val if val.present?
67
+ end
68
+ ox
68
69
  end
69
70
 
70
71
  end
data/oxmlk.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{oxmlk}
8
- s.version = "0.2.3"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Josh Robinson"]
12
- s.date = %q{2009-08-26}
12
+ s.date = %q{2009-09-01}
13
13
  s.description = %q{OxMlk gives you a simple way to map you ruby objects to XML and then convert one to the other.}
14
14
  s.email = %q{hexorx@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -28,10 +28,12 @@ Gem::Specification.new do |s|
28
28
  "examples/xml/example.xml",
29
29
  "examples/xml/posts.xml",
30
30
  "lib/oxmlk.rb",
31
- "lib/oxmlk/description.rb",
31
+ "lib/oxmlk/attr.rb",
32
+ "lib/oxmlk/elem.rb",
32
33
  "lib/oxmlk/xml.rb",
33
34
  "oxmlk.gemspec",
34
- "spec/description_spec.rb",
35
+ "spec/oxmlk/attr_spec.rb",
36
+ "spec/oxmlk/elem_spec.rb",
35
37
  "spec/oxmlk_spec.rb",
36
38
  "spec/spec.opts",
37
39
  "spec/spec_helper.rb",
@@ -40,10 +42,11 @@ Gem::Specification.new do |s|
40
42
  s.homepage = %q{http://github.com/hexorx/oxmlk}
41
43
  s.rdoc_options = ["--charset=UTF-8"]
42
44
  s.require_paths = ["lib"]
43
- s.rubygems_version = %q{1.3.3}
45
+ s.rubygems_version = %q{1.3.5}
44
46
  s.summary = %q{Object 2 XML kit for ruby}
45
47
  s.test_files = [
46
- "spec/description_spec.rb",
48
+ "spec/oxmlk/attr_spec.rb",
49
+ "spec/oxmlk/elem_spec.rb",
47
50
  "spec/oxmlk_spec.rb",
48
51
  "spec/spec_helper.rb",
49
52
  "spec/xml_spec.rb",
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe OxMlk::Attr do
4
+ describe '#accessor' do
5
+ it 'should be attr name as Symbol' do
6
+ ox_attr.accessor.should == :name
7
+ end
8
+ end
9
+
10
+ describe '#setter' do
11
+ it 'should be name + = as Symbol' do
12
+ ox_attr.setter.should == :'name='
13
+ end
14
+ end
15
+
16
+ describe '#from_xml' do
17
+ it 'should return attr with name by default' do
18
+ ox_attr.from_xml('<test name="joe"/>').should == 'joe'
19
+ end
20
+
21
+ it 'should return attr by :from if specified' do
22
+ ox_attr(:name, :from => 'firstName').from_xml('<test firstName="joe"/>').should == 'joe'
23
+ end
24
+
25
+ it 'should return type specified in :as' do
26
+ ox_attr(:age, :as => Integer).from_xml('<test age="30"/>').should == 30
27
+ ox_attr(:age, :as => Float).from_xml('<test age="30"/>').should == 30.0
28
+ ox_attr(:age, :as => String).from_xml('<test age="30"/>').should == '30'
29
+ ox_attr(:age, :as => Symbol).from_xml('<test age="30"/>').should == :'30'
30
+ end
31
+
32
+ it 'should return true or false if :as is :bool' do
33
+ ox_attr(:odd, :as => :bool).from_xml('<test odd="true"/>').should == true
34
+ ox_attr(:odd, :as => :bool).from_xml('<test odd="false"/>').should == false
35
+ end
36
+
37
+ it 'should act like a bool if name ends in ? and :as is not set' do
38
+ ox_attr(:odd?).from_xml('<test odd="true"/>').should == true
39
+ ox_attr(:odd?).from_xml('<test odd="false"/>').should == false
40
+ end
41
+ end
42
+
43
+ describe '#tag' do
44
+ it 'should be :from if set' do
45
+ ox_attr(:name, :from => 'FullName').tag.should == 'FullName'
46
+ end
47
+
48
+ it 'should default to name cleaned up' do
49
+ ox_attr(:name).tag.should == 'name'
50
+ end
51
+ end
52
+ end
53
+
54
+ def ox_attr(name=:name,o={})
55
+ OxMlk::Attr.new(name,o)
56
+ end
@@ -0,0 +1,142 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe OxMlk::Elem do
4
+ describe '#accessor' do
5
+ it 'should be attr name as Symbol' do
6
+ ox_elem.accessor.should == :name
7
+ end
8
+ end
9
+
10
+ describe '#setter' do
11
+ it 'should be name + = as Symbol' do
12
+ ox_elem.setter.should == :'name='
13
+ end
14
+ end
15
+
16
+ describe '#ox?' do
17
+ it 'should be true if :as class is ox?' do
18
+ ox_elem(:name, :as => OxKlass).ox?.should be_true
19
+ end
20
+
21
+ it 'should be true if :as is an array of ox objects' do
22
+ ox_elem(:name, :as => [OxKlass]).ox?.should be_true
23
+ end
24
+
25
+ it 'should be false if :as does not responds to ox?' do
26
+ ox_elem(:name, :as => 1).ox?.should be_false
27
+ end
28
+
29
+ it 'should be false if any of the items in :as array do not respond to from_xml' do
30
+ ox_elem(:name, :as => [OxKlass,1]).ox?.should be_false
31
+ end
32
+ end
33
+
34
+ describe '#from_xml' do
35
+ before(:all) do
36
+ @xml = OxMlk::XML::Node.from(xml_for(:example))
37
+ end
38
+
39
+ it 'should default to :value' do
40
+ ox_elem.from_xml(@xml).should == 'Joe'
41
+ end
42
+
43
+ it 'should return a :value if :as is :value' do
44
+ ox_elem(:name, :as => :value).from_xml(@xml).should == 'Joe'
45
+ end
46
+
47
+ it 'should return an Integer if :as is Integer' do
48
+ ox_elem(:name, :as => Integer).from_xml(@xml).should be_an(Integer)
49
+ end
50
+
51
+ it 'should return an Float if :as is Float' do
52
+ ox_elem(:name, :as => Float).from_xml(@xml).should be_an(Float)
53
+ end
54
+
55
+ it 'should return an Array of Integers if :as is [Integer]' do
56
+ ox_elem(:name, :as => [Integer]).from_xml(@xml).each do |x|
57
+ x.should be_an(Integer)
58
+ end
59
+ end
60
+
61
+ it 'should run procs passed to :as' do
62
+ ox_elem(:name, :as => proc {|x| 'hi'}).from_xml(@xml).should == 'hi'
63
+ end
64
+
65
+ it 'should return an OxMlk object if one is passed to :as' do
66
+ ox_elem(:name, :as => OxKlass).from_xml(@xml).should be_a(OxKlass)
67
+ end
68
+
69
+ it 'should match class to ox_tag if array of ox_objects is passed to :as' do
70
+ ox_elem(:contact, :as => [Email,Number]).from_xml(@xml).first.should be_a(Number)
71
+ end
72
+
73
+ it 'should turn symbol to proc if possible' do
74
+ ox_elem(:name, :as => :to_i).from_xml(@xml).should be_a(Integer)
75
+ end
76
+ end
77
+
78
+ describe '#to_xml' do
79
+ before(:all) do
80
+ require example(:example)
81
+ @ox = Person.from_xml(xml_for(:example))
82
+ @elem = Person.ox_elems.first
83
+ end
84
+
85
+ it 'should return an Array of nodes if it is an elem' do
86
+ @elem.to_xml(@ox).should be_a(Array)
87
+ @elem.to_xml(@ox).first.should be_a(OxMlk::XML::Node)
88
+ end
89
+ end
90
+
91
+ describe '#xpath' do
92
+ it 'should be name by default' do
93
+ ox_elem.xpath.should == 'name'
94
+ end
95
+
96
+ it 'should be the string if :from is a string' do
97
+ ox_elem(:name, :from => 'String').xpath.should == 'String'
98
+ end
99
+
100
+ it 'should be . if :from is :content' do
101
+ ox_elem(:name, :from => :content).xpath.should == '.'
102
+ end
103
+
104
+ it 'should be ox_tag if :as is a ox_object' do
105
+ ox_elem(:name, :as => OxKlass).xpath.should == 'name'
106
+ end
107
+
108
+ it 'should be list of ox_tag if :as is an array of ox_objects' do
109
+ ox_elem(:name, :as => [OxKlass,OxKlass]).xpath.should == 'name|name'
110
+ end
111
+
112
+ it 'should add :in + / to xpath if :in is passed' do
113
+ ox_elem(:name, :in => :friends).xpath.should == 'friends/name'
114
+ end
115
+
116
+ it 'should add :in + / to all items in array of ox objects' do
117
+ ox_elem(:name, :as => [OxKlass,OxKlass], :in => :friends).xpath.should == 'friends/name|friends/name'
118
+ end
119
+ end
120
+ end
121
+
122
+ def ox_elem(name=:name,o={})
123
+ OxMlk::Elem.new(name,o)
124
+ end
125
+
126
+ class OxKlass
127
+ include OxMlk
128
+
129
+ ox_tag :name
130
+ end
131
+
132
+ class Number
133
+ include OxMlk
134
+
135
+ ox_tag :number
136
+ end
137
+
138
+ class Email
139
+ include OxMlk
140
+
141
+ ox_tag :email
142
+ end
data/spec/oxmlk_spec.rb CHANGED
@@ -40,6 +40,12 @@ describe OxMlk::InstanceMethods do
40
40
  @oxml.to_s.should == OxMlk::XML::Node.from(@xml).to_s
41
41
  end
42
42
  end
43
+
44
+ describe '#ox?' do
45
+ it 'should return true' do
46
+ Person.ox?.should be_true
47
+ end
48
+ end
43
49
  end
44
50
 
45
51
  describe OxMlk::ClassMethods do
@@ -49,25 +55,31 @@ describe OxMlk::ClassMethods do
49
55
  @klass = Person
50
56
  end
51
57
 
52
- describe '#ox_attr' do
53
- it 'should add an OxMlk::Description to the class' do
54
- @klass.ox_attrs.first.should be_a(OxMlk::Description)
58
+ describe '#ox_elem' do
59
+ it 'should add an OxMlk::Description to the ox_elems list' do
60
+ @klass.ox_elems.first.should be_a(OxMlk::Elem)
55
61
  end
56
62
 
57
63
  it 'should add a reader method' do
58
64
  @klass.new.should respond_to(:name)
59
65
  end
60
66
 
61
- it 'should add a writter method by default' do
67
+ it 'should add a writter method' do
62
68
  @klass.new.should respond_to(:name=)
63
69
  end
64
-
65
- it 'should add not a writter method when :freeze => true' do
66
- @klass.new.should_not respond_to(:contacts=)
70
+ end
71
+
72
+ describe '#ox_attr' do
73
+ it 'should add an OxMlk::Attr to the ox_attrs list' do
74
+ @klass.ox_attrs.first.should be_a(OxMlk::Attr)
75
+ end
76
+
77
+ it 'should add a reader method' do
78
+ @klass.new.should respond_to(:alternate)
67
79
  end
68
80
 
69
- it 'should add a writter method when :freeze => false' do
70
- @klass.new.should respond_to(:friends=)
81
+ it 'should add a writter method' do
82
+ @klass.new.should respond_to(:alternate=)
71
83
  end
72
84
  end
73
85
 
@@ -105,9 +117,9 @@ describe OxMlk::ClassMethods do
105
117
  end
106
118
  end
107
119
 
108
- describe '#ox_attributes' do
120
+ describe '#ox_attrs' do
109
121
  it 'should return a list of attributes' do
110
- @klass.ox_attributes.size.should == 2
122
+ @klass.ox_attrs.size.should == 2
111
123
  end
112
124
  end
113
125
 
data/spec/xml_spec.rb CHANGED
@@ -38,31 +38,6 @@ describe OxMlk::XML::Node, '#from' do
38
38
  end
39
39
  end
40
40
 
41
- describe OxMlk::XML::Node, '#build' do
42
- before(:all) do
43
- @node = OxMlk::XML::Node
44
- @nodes = [@node.new('one'),@node.new('two'),@node.new('three')]
45
- @attributes = [[1,2],[3,4]]
46
- @args = ['name',@nodes,@attributes]
47
- end
48
-
49
- it 'should return a new node' do
50
- @node.build(*@args).should be_a(@node)
51
- end
52
-
53
- it 'should set its name to the first argument' do
54
- @node.build(*@args).name.should == 'name'
55
- end
56
-
57
- it 'should set its children to second argument' do
58
- @node.build(*@args).children.should == @nodes
59
- end
60
-
61
- it 'should set its attributes to the third argument' do
62
- @node.build(*@args).should be_attributes
63
- end
64
- end
65
-
66
41
  describe OxMlk::XML::Node, '#value' do
67
42
  before(:all) do
68
43
  @node = OxMlk::XML::Node.new('test')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oxmlk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Robinson
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-26 00:00:00 -06:00
12
+ date: 2009-09-01 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -63,10 +63,12 @@ files:
63
63
  - examples/xml/example.xml
64
64
  - examples/xml/posts.xml
65
65
  - lib/oxmlk.rb
66
- - lib/oxmlk/description.rb
66
+ - lib/oxmlk/attr.rb
67
+ - lib/oxmlk/elem.rb
67
68
  - lib/oxmlk/xml.rb
68
69
  - oxmlk.gemspec
69
- - spec/description_spec.rb
70
+ - spec/oxmlk/attr_spec.rb
71
+ - spec/oxmlk/elem_spec.rb
70
72
  - spec/oxmlk_spec.rb
71
73
  - spec/spec.opts
72
74
  - spec/spec_helper.rb
@@ -95,12 +97,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
97
  requirements: []
96
98
 
97
99
  rubyforge_project:
98
- rubygems_version: 1.3.3
100
+ rubygems_version: 1.3.5
99
101
  signing_key:
100
102
  specification_version: 3
101
103
  summary: Object 2 XML kit for ruby
102
104
  test_files:
103
- - spec/description_spec.rb
105
+ - spec/oxmlk/attr_spec.rb
106
+ - spec/oxmlk/elem_spec.rb
104
107
  - spec/oxmlk_spec.rb
105
108
  - spec/spec_helper.rb
106
109
  - spec/xml_spec.rb
@@ -1,144 +0,0 @@
1
- module OxMlk
2
-
3
- class Description
4
- PROCESSORS = {
5
- :value => proc {|x| x.value rescue nil},
6
- Integer => proc {|x| x.value.to_i rescue nil},
7
- Float => proc {|x| x.value.to_f rescue nil}
8
- }
9
-
10
- attr_reader :xpath
11
-
12
- def initialize(name,o={},&block)
13
- @froze = o.delete(:freeze)
14
- @from = o.delete(:from)
15
- @as = o.delete(:as)
16
- @in = o.delete(:in)
17
- @tag = o.delete(:tag)
18
- @name = name.to_s
19
-
20
- @is_attribute = computed_is_attribute
21
- @processors = [coputed_processor, block].compact
22
- @xpath = computed_xpath
23
- end
24
-
25
- def accessor
26
- @accessor ||= @name.intern
27
- end
28
-
29
- def setter
30
- :"#{accessor}="
31
- end
32
-
33
- def instance_variable
34
- :"@#{accessor}"
35
- end
36
-
37
- def froze?
38
- @froze ||= false
39
- end
40
-
41
- def writable?
42
- !froze?
43
- end
44
-
45
- def attribute?
46
- @is_attribute ||= false
47
- end
48
-
49
- def elem?
50
- !attribute?
51
- end
52
-
53
- def ox_type
54
- elem? ? :elem : :attribute
55
- end
56
-
57
- def collection?
58
- @as.is_a?(Array)
59
- end
60
-
61
- def content?
62
- @from == :content || @from == '.'
63
- end
64
-
65
- def ox_object?
66
- return false if [*@as].empty?
67
- [*@as].all? {|x| x.respond_to?(:from_xml)}
68
- end
69
-
70
- def process(node,instance)
71
- @processors.inject(node) do |memo,processor|
72
- case processor
73
- when Proc
74
- processor.call(memo)
75
- when Symbol
76
- instance.send(processor,memo)
77
- else
78
- processor.from_xml(memo)
79
- end
80
- end
81
- end
82
-
83
- def from_xml(data,instance)
84
- xml = XML::Node.from(data)
85
- nodes = xml.find(@xpath)
86
- return nil if nodes.first.nil?
87
- return process(nodes.first,instance) unless collection?
88
- (nodes).map {|n| process(n,instance)}
89
- end
90
-
91
- def to_xml(data)
92
- value = data.send(accessor)
93
-
94
- return [] if value.nil?
95
- return [accessor.to_s,value.to_s] if attribute?
96
-
97
- nodes = [*value].map do |node|
98
- if node.respond_to?(:to_xml)
99
- node.to_xml
100
- elsif content?
101
- XML::Node.new_text(node.to_s)
102
- else
103
- XML::Node.new(accessor, node.to_s)
104
- end
105
- end
106
- @in ? XML::Node.build(@in, nodes) : nodes
107
- end
108
-
109
- protected
110
-
111
- def computed_xpath
112
- wrap case @from
113
- when nil
114
- if ox_object?
115
- [*@as].map(&:ox_tag).join('|')
116
- elsif collection?
117
- @name.to_s.singularize
118
- else
119
- @name.to_s
120
- end
121
- when String
122
- @from
123
- when :attr
124
- "@#{accessor}"
125
- when :content
126
- '.'
127
- end
128
- end
129
-
130
- def computed_is_attribute
131
- @from.to_s[0,1] == '@' || @from == :attr
132
- end
133
-
134
- def coputed_processor
135
- return proc {|x| Hash[*@as.map{|o| [o.ox_tag,o]}.flatten][x.name].from_xml(x) } if collection? && ox_object?
136
- processor = [*@as].first || :value
137
- PROCESSORS[processor] || processor
138
- end
139
-
140
- def wrap(xpath=nil)
141
- (xpath.split('|').map {|x| [@in,x].compact.join('/') }).join('|')
142
- end
143
- end
144
- end
@@ -1,266 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe OxMlk::Description do
4
-
5
- before(:all) do
6
- require example(:example)
7
-
8
- @xml = OxMlk::XML::Node.from(xml_for(:example))
9
- @klass = Person
10
- end
11
-
12
- describe '#xpath' do
13
- it 'should be name by default' do
14
- @desc = OxMlk::Description.new(:name)
15
- @desc.xpath.should == 'name'
16
- end
17
-
18
- it 'should be the string if :from is a string' do
19
- @desc = OxMlk::Description.new(:name, :from => 'String')
20
- @desc.xpath.should == 'String'
21
- end
22
-
23
- it 'should be @+accessor if :from is :attr' do
24
- @desc = OxMlk::Description.new(:name, :from => :attr)
25
- @desc.xpath.should == '@name'
26
- end
27
-
28
- it 'should be . if :from is :content' do
29
- @desc = OxMlk::Description.new(:name, :from => :content)
30
- @desc.xpath.should == '.'
31
- end
32
-
33
- it 'should be singular if plural name and is a collection' do
34
- @desc = OxMlk::Description.new(:numbers, :as => [])
35
- @desc.xpath.should == 'number'
36
- end
37
-
38
- it 'should be ox_tag if :as is a ox_object' do
39
- @desc = OxMlk::Description.new(:digits, :as => Number)
40
- @desc.xpath.should == 'number'
41
- end
42
-
43
- it 'should be list of ox_tag if :as is an array of ox_objects' do
44
- @desc = OxMlk::Description.new(:digits, :as => [Number,Person])
45
- @desc.xpath.should == 'number|person'
46
- end
47
-
48
- it 'should add :in + / to xpath if :in is passed' do
49
- @desc = OxMlk::Description.new(:person, :in => :friends)
50
- @desc.xpath.should == 'friends/person'
51
- end
52
-
53
- it 'should add :in + / to all items in array of ox_objetcs' do
54
- @desc = OxMlk::Description.new(:digits, :as => [Number,Person], :in => :friends)
55
- @desc.xpath.should == 'friends/number|friends/person'
56
- end
57
- end
58
-
59
- describe '#accessor' do
60
- it 'should be attr name as Symbol' do
61
- @desc = OxMlk::Description.new(:name)
62
- @desc.accessor.should == :name
63
- end
64
- end
65
-
66
- describe '#setter' do
67
- it 'should be accessor with = on the end' do
68
- @desc = OxMlk::Description.new(:name)
69
- @desc.setter.should == :'name='
70
- end
71
- end
72
-
73
- describe '#instance_variable' do
74
- it 'should be accessor with @ on the front' do
75
- @desc = OxMlk::Description.new(:name)
76
- @desc.instance_variable.should == :'@name'
77
- end
78
- end
79
-
80
- describe '#writable?' do
81
- it 'should be true by default' do
82
- @desc = OxMlk::Description.new(:name)
83
- @desc.writable?.should be_true
84
- end
85
-
86
- it 'should be true if :freeze is false' do
87
- @desc = OxMlk::Description.new(:name, :freeze => false)
88
- @desc.writable?.should be_true
89
- end
90
-
91
- it 'should be false if :freeze is true' do
92
- @desc = OxMlk::Description.new(:name, :freeze => true)
93
- @desc.writable?.should be_false
94
- end
95
- end
96
-
97
- describe '#attribute?' do
98
- it 'should be true if :from starts with @' do
99
- @desc = OxMlk::Description.new(:name, :from => '@name')
100
- @desc.attribute?.should be_true
101
- end
102
-
103
- it 'should be true if :from is :attribute' do
104
- @desc = OxMlk::Description.new(:name, :from => :attr)
105
- @desc.attribute?.should be_true
106
- end
107
- end
108
-
109
- describe '#elem?' do
110
- it 'should be true if attribute? is false' do
111
- @desc = OxMlk::Description.new(:name)
112
- @desc.elem?.should be_true
113
- end
114
-
115
- it 'should be false if attribute? is true' do
116
- @desc = OxMlk::Description.new(:name, :from => :attr)
117
- @desc.elem?.should be_false
118
- end
119
- end
120
-
121
- describe '#ox_type' do
122
- it 'should be :elem if elem? is true' do
123
- @desc = OxMlk::Description.new(:name)
124
- @desc.ox_type.should == :elem
125
- end
126
-
127
- it 'should be :attribute if attribute? is true' do
128
- @desc = OxMlk::Description.new(:name, :from => :attr)
129
- @desc.ox_type.should == :attribute
130
- end
131
- end
132
-
133
- describe '#collection?' do
134
- it 'should be true if :as is an Array' do
135
- @desc = OxMlk::Description.new(:name, :as => [])
136
- @desc.collection?.should be_true
137
- end
138
-
139
- it 'should be false if :as is not Array' do
140
- @desc = OxMlk::Description.new(:name)
141
- @desc.collection?.should be_false
142
- end
143
- end
144
-
145
- describe '#ox_object?' do
146
- it 'should be true if :as responds to from_xml' do
147
- @desc = OxMlk::Description.new(:number, :as => Person)
148
- @desc.ox_object?.should be_true
149
- end
150
-
151
- it 'should be true if :as is an array of objects that respond to from_xml' do
152
- @desc = OxMlk::Description.new(:number, :as => [Person,Number])
153
- @desc.ox_object?.should be_true
154
- end
155
-
156
- it 'should be false if :as does not responds to from_xml' do
157
- @desc = OxMlk::Description.new(:number, :as => 1)
158
- @desc.ox_object?.should be_false
159
- end
160
-
161
- it 'should be false if any of the items in :as array do not respond to from_xml' do
162
- @desc = OxMlk::Description.new(:number, :as => [Person,Number,1])
163
- @desc.ox_object?.should be_false
164
- end
165
- end
166
-
167
- describe '#content?' do
168
- it 'should return true if :from is :content' do
169
- @desc = OxMlk::Description.new(:number, :from => :content)
170
- @desc.content?.should be_true
171
- end
172
-
173
- it 'should return true if :from is "."' do
174
- @desc = OxMlk::Description.new(:number, :from => '.')
175
- @desc.content?.should be_true
176
- end
177
-
178
- it 'should return false if :from is nil' do
179
- @desc = OxMlk::Description.new(:number)
180
- @desc.content?.should be_false
181
- end
182
-
183
- it 'should return false if :from is string other than "."' do
184
- @desc = OxMlk::Description.new(:number, :from => 'hi')
185
- @desc.content?.should be_false
186
- end
187
- end
188
-
189
- describe '#from_xml' do
190
-
191
- it 'should accept xml argument' do
192
- @desc = OxMlk::Description.new(:name)
193
- @desc.from_xml(@xml, @klass.new).should be_a(String)
194
- end
195
-
196
- it 'should return an array if :as is an array' do
197
- @desc = OxMlk::Description.new(:name, :as => [])
198
- @desc.from_xml(@xml, @klass.new).should be_an(Array)
199
- end
200
-
201
- it 'should return a String if :as is :value' do
202
- @desc = OxMlk::Description.new(:name, :as => :value)
203
- @desc.from_xml(@xml, @klass.new).should be_an(String)
204
- end
205
-
206
- it 'should return a String if :as is nil' do
207
- @desc = OxMlk::Description.new(:name)
208
- @desc.from_xml(@xml, @klass.new).should be_an(String)
209
- end
210
-
211
- it 'should return an Integer if :as is Integer' do
212
- @desc = OxMlk::Description.new(:name, :as => Integer)
213
- @desc.from_xml(@xml, @klass.new).should be_an(Integer)
214
- end
215
-
216
- it 'should return an Float if :as is Float' do
217
- @desc = OxMlk::Description.new(:name, :as => Float)
218
- @desc.from_xml(@xml, @klass.new).should be_an(Float)
219
- end
220
-
221
- it 'should return an Array of Integers if :as is [Integer]' do
222
- @desc = OxMlk::Description.new(:name, :as => [Integer])
223
- @desc.from_xml(@xml, @klass.new).each do |x|
224
- x.should be_an(Integer)
225
- end
226
- end
227
-
228
- it 'should run procs passed to :as' do
229
- @desc = OxMlk::Description.new(:name, :as => proc {|x| 'hi'})
230
- @desc.from_xml(@xml, @klass.new).should == 'hi'
231
- end
232
-
233
- it 'should run method when symbol is passed to :as' do
234
- @desc = OxMlk::Description.new(:name, :as => :say_hello)
235
- @desc.from_xml(@xml, @klass.new).should == 'hello'
236
- end
237
-
238
- it 'should return an OxMlk object if one is passed to :as' do
239
- @desc = OxMlk::Description.new(:number, :as => Number)
240
- @desc.from_xml(@xml, @klass.new).should be_a(Number)
241
- end
242
-
243
- it 'should match class to ox_tag if array of ox_objects is passed to :as' do
244
- @desc = OxMlk::Description.new(:contact, :as => [Number,Email])
245
- @desc.from_xml(@xml, @klass.new).first.should be_a(Number)
246
- end
247
- end
248
-
249
- describe '#to_xml' do
250
- before(:all) do
251
- @ox = Person.from_xml(@xml)
252
- @attr = Person.ox_attributes.first
253
- @elem = Person.ox_elems.first
254
- end
255
-
256
- it 'should return an Array of Strings if it is an attribute' do
257
- @attr.to_xml(@ox).should be_a(Array)
258
- @attr.to_xml(@ox).first.should be_a(String)
259
- end
260
-
261
- it 'should return an Array of nodes if it is an elem' do
262
- @elem.to_xml(@ox).should be_a(Array)
263
- @elem.to_xml(@ox).first.should be_a(OxMlk::XML::Node)
264
- end
265
- end
266
- end