oxmlk 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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