representable 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ h2. 0.9.3
2
+
3
+ * Removed the @:as => [..]@ syntax in favor of @:array => true@.
4
+
1
5
  h2. 0.9.2
2
6
 
3
7
  * Arguments and block now successfully forwarded in @#from_*@.
@@ -51,172 +51,28 @@ private
51
51
  representable_attrs.map {|attr| binding_for_definition(attr) }
52
52
  end
53
53
 
54
- # Declares a reference to a certain xml element, whether an attribute, a node,
55
- # or a typed collection of nodes. This method does not add a corresponding accessor
56
- # to the object. For that behavior see the similar methods: .xml_reader and .xml_accessor.
54
+ # Declares a represented document node, which is usually a XML tag or a JSON key.
57
55
  #
58
- # == Sym Option
59
- # [sym] Symbol representing the name of the accessor.
56
+ # Examples:
60
57
  #
61
- # === Default naming
62
- # This name will be the default node or attribute name searched for,
63
- # if no other is declared. For example,
64
- #
65
- # xml_reader :bob
66
- # xml_accessor :pony, :from => :attr
67
- #
68
- # are equivalent to:
69
- #
70
- # xml_reader :bob, :from => 'bob'
71
- # xml_accessor :pony, :from => '@pony'
72
- #
73
- # == Options
74
- # === :as
75
- # ==== Basic Types
76
- # Allows you to specify one of several basic types to return the value as. For example
77
- #
78
- # xml_reader :count, :as => Integer
79
- #
80
- # is equivalent to:
81
- #
82
- # xml_reader(:count) {|val| Integer(val) unless val.empty? }
83
- #
84
- # Such block shorthands for Integer, Float, Fixnum, BigDecimal, Date, Time, and DateTime
85
- # are currently available, but only for non-Hash declarations.
86
- #
87
- # To reference many elements, put the desired type in a literal array. e.g.:
88
- #
89
- # xml_reader :counts, :as => [Integer]
90
- #
91
- # Even an array of text nodes can be specified with :as => []
92
- #
93
- # xml_reader :quotes, :as => []
94
- #
95
- # === Other ROXML Class
96
- # Declares an accessor that represents another ROXML class as child XML element
97
- # (one-to-one or composition) or array of child elements (one-to-many or
98
- # aggregation) of this type. Default is one-to-one. For one-to-many, simply pass the class
99
- # as the only element in an array.
100
- #
101
- # Composition example:
102
- # <book>
103
- # <publisher>
104
- # <name>Pragmatic Bookshelf</name>
105
- # </publisher>
106
- # </book>
107
- #
108
- # Can be mapped using the following code:
109
- # class Book
110
- # xml_reader :publisher, :as => Publisher
111
- # end
112
- #
113
- # Aggregation example:
114
- # <library>
115
- # <books>
116
- # <book/>
117
- # <book/>
118
- # </books>
119
- # </library>
120
- #
121
- # Can be mapped using the following code:
122
- # class Library
123
- # xml_reader :books, :as => [Book], :in => "books"
124
- # end
125
- #
126
- # If you don't have the <books> tag to wrap around the list of <book> tags:
127
- # <library>
128
- # <name>Ruby books</name>
129
- # <book/>
130
- # <book/>
131
- # </library>
132
- #
133
- # You can skip the wrapper argument:
134
- # xml_reader :books, :as => [Book]
135
- #
136
- # === :from
137
- # The name by which the xml value will be found, either an attribute or tag name in XML.
138
- # Default is sym, or the singular form of sym, in the case of arrays and hashes.
139
- #
140
- # This value may also include XPath notation.
141
- #
142
- # ==== :from => :content
143
- # When :from is set to :content, this refers to the content of the current node,
144
- # rather than a sub-node. It is equivalent to :from => '.'
145
- #
146
- # Example:
147
- # class Contributor
148
- # xml_reader :name, :from => :content
149
- # xml_reader :role, :from => :attr
150
- # end
151
- #
152
- # To map:
153
- # <contributor role="editor">James Wick</contributor>
154
- #
155
- # ==== :from => :attr
156
- # When :from is set to :attr, this refers to the content of an attribute,
157
- # rather than a sub-node. It is equivalent to :from => '@attribute_name'
158
- #
159
- # Example:
160
- # class Book
161
- # xml_reader :isbn, :from => "@ISBN"
162
- # xml_accessor :title, :from => :attr # :from defaults to '@title'
163
- # end
164
- #
165
- # To map:
166
- # <book ISBN="0974514055" title="Programming Ruby: the pragmatic programmers' guide" />
167
- #
168
- # ==== :from => :text
169
- # The default source, if none is specified, this means the accessor
170
- # represents a text node from XML. This is documented for completeness
171
- # only. You should just leave this option off when you want the default behavior,
172
- # as in the examples below.
173
- #
174
- # :text is equivalent to :from => accessor_name, and you should specify the
175
- # actual node name (and, optionally, a namespace) if it differs, as in the case of :author below.
176
- #
177
- # Example:
178
- # class Book
179
- # xml_reader :author, :from => 'Author'
180
- # xml_accessor :description, :cdata => true
181
- # xml_reader :title
182
- # end
183
- #
184
- # To map:
185
- # <book>
186
- # <title>Programming Ruby: the pragmatic programmers' guide</title>
187
- # <description><![CDATA[Probably the best Ruby book out there]]></description>
188
- # <Author>David Thomas</Author>
189
- # </book>
190
- #
191
- # Likewise, a number of :text node values can be collected in an array like so:
192
- #
193
- # Example:
194
- # class Library
195
- # xml_reader :books, :as => []
196
- # end
197
- #
198
- # To map:
199
- # <library>
200
- # <book>To kill a mockingbird</book>
201
- # <book>House of Leaves</book>
202
- # <book>Gödel, Escher, Bach</book>
203
- # </library>
204
- #
205
- # === Other Options
206
- # [:in] An optional name of a wrapping tag for this XML accessor.
207
- # This can include other xpath values, which will be joined with :from with a '/'
208
- # [:required] If true, throws RequiredElementMissing when the element isn't present
209
- # [:cdata] true for values which should be input from or output as cdata elements
210
- # [:to_xml] this proc is applied to the attributes value outputting the instance via #to_xml
211
- #
212
- def representable_property(*args) # TODO: make it accept 1-n props.
58
+ # representable_property :name
59
+ # representable_property :name, :from => :title
60
+ # representable_property :name, :as => Name
61
+ def representable_property(*args)
213
62
  attr = add_representable_property(*args)
214
63
  attr_reader(attr.getter)
215
64
  attr_writer(attr.getter)
216
65
  end
217
66
 
67
+ # Declares a represented document node collection.
68
+ #
69
+ # Examples:
70
+ #
71
+ # representable_collection :products
72
+ # representable_collection :products, :from => :item
73
+ # representable_collection :products, :as => Product
218
74
  def representable_collection(name, options={})
219
- options[:as] = [options[:as]].compact
75
+ options[:collection] = true
220
76
  representable_property(name, options)
221
77
  end
222
78
 
@@ -44,7 +44,7 @@ module Representable
44
44
  class ObjectBinding < Binding
45
45
  def write(hash, value)
46
46
  if definition.array?
47
- hash.merge! ({definition.from => value.collect {|v| v.to_hash(:wrap => false)}}) # hier name=> wech.
47
+ hash.merge!({definition.from => value.collect {|v| v.to_hash(:wrap => false)}})
48
48
  else
49
49
  hash.merge! value.to_hash
50
50
  end
@@ -3,24 +3,16 @@ module Representable
3
3
  attr_reader :name, :sought_type, :wrapper, :from
4
4
  alias_method :getter, :name
5
5
 
6
- def initialize(sym, opts={})
7
- @name = sym.to_s
8
-
9
- @array = true if opts[:as].is_a?(Array) # DISCUSS: move to ArrayDefinition.
10
- @from = (opts[:from] || name).to_s
11
- @sought_type = extract_type(opts[:as])
6
+ def initialize(sym, options={})
7
+ @name = sym.to_s
8
+ @array = options[:collection]
9
+ @from = (options[:from] || name).to_s
10
+ @sought_type = options[:as] || :text
12
11
 
13
12
  # FIXME: move me to xml.
14
- if opts[:from] == :content
15
- opts[:from] = '.'
16
- elsif opts[:from] == :name
17
- opts[:from] = '*'
18
- elsif opts[:from] == :attr
19
- @sought_type = :attr
20
- opts[:from] = nil
21
- elsif opts[:from].to_s =~ /^@/
13
+ if options[:from].to_s =~ /^@/
22
14
  @sought_type = :attr
23
- opts[:from].sub!('@', '')
15
+ options[:from].sub!('@', '')
24
16
  end
25
17
  end
26
18
 
@@ -67,12 +59,5 @@ module Representable
67
59
 
68
60
  value
69
61
  end
70
-
71
- private
72
- def extract_type(as)
73
- as = as.first if as.is_a?(Array) # TODO: move to ArrayDefinition.
74
-
75
- as || :text
76
- end
77
62
  end
78
63
  end
@@ -2,6 +2,10 @@ require 'json'
2
2
  require 'representable/bindings/json_bindings'
3
3
 
4
4
  module Representable
5
+ # Brings #to_xml, #to_hash, #from_xml and #from_hash to your object.
6
+ #
7
+ # Note: The authorative methods are #to_hash and #from_hash, if you override #to_json instead,
8
+ # things might work as expected.
5
9
  module JSON
6
10
  BINDING_FOR_TYPE = { # TODO: refactor #representable_accessor for better extendability.
7
11
  :text => TextBinding,
@@ -1,3 +1,3 @@
1
1
  module Representable
2
- VERSION = "0.9.2"
2
+ VERSION = "0.9.3"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require 'representable'
2
+ require 'representable/nokogiri_extensions'
2
3
  require 'representable/bindings/xml_bindings'
3
4
 
4
5
  module Representable
@@ -9,7 +9,6 @@ class DefinitionTest < MiniTest::Spec
9
9
  it "responds to #typed?" do
10
10
  assert ! @def.typed?
11
11
  assert Representable::Definition.new(:songs, :as => Hash).typed?
12
- assert Representable::Definition.new(:songs, :as => [Hash]).typed?
13
12
  end
14
13
 
15
14
  it "responds to #getter and returns string" do
@@ -41,19 +40,19 @@ class DefinitionTest < MiniTest::Spec
41
40
  end
42
41
 
43
42
  it "works with collection" do
44
- @d = Representable::Definition.new(:song, :as => [])
43
+ @d = Representable::Definition.new(:song, :collection => true)
45
44
  assert_equal [2,3,4], @d.apply([1,2,3]) { |v| v+1 }
46
45
  end
47
46
 
48
47
  it "skips with collection and nil" do
49
- @d = Representable::Definition.new(:song, :as => [])
48
+ @d = Representable::Definition.new(:song, :collection => true)
50
49
  assert_equal nil, @d.apply(nil) { |v| v+1 }
51
50
  end
52
51
  end
53
52
 
54
- describe ":as => []" do
53
+ describe ":collection => true" do
55
54
  before do
56
- @def = Representable::Definition.new(:songs, :as => [], :tag => :song)
55
+ @def = Representable::Definition.new(:songs, :collection => true, :tag => :song)
57
56
  end
58
57
 
59
58
  it "responds to #array?" do
@@ -64,18 +63,6 @@ class DefinitionTest < MiniTest::Spec
64
63
  assert_equal :text, @def.sought_type
65
64
  end
66
65
  end
67
-
68
-
69
- describe ":as => [Item]" do
70
- before do
71
- @def = Representable::Definition.new(:songs, :as => [Hash])
72
- end
73
-
74
- it "responds to #sought_type" do
75
- assert_equal Hash, @def.sought_type
76
- end
77
- end
78
-
79
66
 
80
67
  describe ":as => Item" do
81
68
  before do
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 2
9
- version: 0.9.2
8
+ - 3
9
+ version: 0.9.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Nick Sutterer
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-11-25 00:00:00 +01:00
17
+ date: 2011-11-27 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency