versionomy 0.4.1 → 0.4.2

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.
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # Versionomy schema wrapper class
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2008-2009 Daniel Azuma
7
- #
7
+ #
8
8
  # All rights reserved.
9
- #
9
+ #
10
10
  # Redistribution and use in source and binary forms, with or without
11
11
  # modification, are permitted provided that the following conditions are met:
12
- #
12
+ #
13
13
  # * Redistributions of source code must retain the above copyright notice,
14
14
  # this list of conditions and the following disclaimer.
15
15
  # * Redistributions in binary form must reproduce the above copyright notice,
@@ -18,7 +18,7 @@
18
18
  # * Neither the name of the copyright holder, nor the names of any other
19
19
  # contributors to this software, may be used to endorse or promote products
20
20
  # derived from this software without specific prior written permission.
21
- #
21
+ #
22
22
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
23
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
24
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -35,17 +35,17 @@
35
35
 
36
36
 
37
37
  module Versionomy
38
-
38
+
39
39
  module Schema
40
-
41
-
40
+
41
+
42
42
  # Creates a schema.
43
43
  # Returns an object of type Versionomy::Schema::Wrapper.
44
- #
44
+ #
45
45
  # You may either pass a root field, or provide a block to use to build
46
46
  # fields. If you provide a block, you must use the methods in
47
47
  # Versionomy::Schema::Builder in the block to create the root field.
48
-
48
+
49
49
  def self.create(field_=nil, opts_={}, &block_)
50
50
  if field_ && block_
51
51
  raise ::ArgumentError, 'You may provide either a root field or block but not both'
@@ -61,17 +61,17 @@ module Versionomy
61
61
  end
62
62
  Schema::Wrapper.new(field_, modules_, aliases_)
63
63
  end
64
-
65
-
64
+
65
+
66
66
  # Schemas are generally referenced through an object of this class.
67
-
67
+
68
68
  class Wrapper
69
-
70
-
69
+
70
+
71
71
  # Create a new schema wrapper object given a root field.
72
72
  # This is a low-level method. Usually you should call
73
73
  # Versionomy::Schema#create instead.
74
-
74
+
75
75
  def initialize(field_, modules_=[], aliases_={})
76
76
  @root_field = field_
77
77
  @names = @root_field._descendants_by_name
@@ -85,43 +85,43 @@ module Versionomy
85
85
  end
86
86
  end
87
87
  end
88
-
89
-
88
+
89
+
90
90
  def inspect # :nodoc:
91
91
  "#<#{self.class}:0x#{object_id.to_s(16)} root=#{@root_field.inspect}>"
92
92
  end
93
-
93
+
94
94
  def to_s # :nodoc:
95
95
  inspect
96
96
  end
97
-
98
-
97
+
98
+
99
99
  # Returns true if this schema is equivalent to the other schema.
100
100
  # Two schemas are equivalent if their root fields are the same--
101
101
  # which means that the entire field tree is the same-- and they
102
102
  # include the same value modules.
103
103
  # Note that this is different from the definition of <tt>==</tt>.
104
-
104
+
105
105
  def eql?(obj_)
106
106
  return false unless obj_.kind_of?(Schema::Wrapper)
107
107
  return @root_field == obj_.root_field && @modules == obj_.modules && @aliases == obj_.aliases
108
108
  end
109
-
110
-
109
+
110
+
111
111
  # Returns true if this schema is compatible with the other schema.
112
112
  # Two schemas are compatible if their root fields are the same--
113
113
  # which means that the entire field tree is the same. They may,
114
114
  # however, include different value modules.
115
115
  # Note that this is different from the definition of <tt>eql?</tt>.
116
-
116
+
117
117
  def ==(obj_)
118
118
  eql?(obj_)
119
119
  end
120
-
121
-
120
+
121
+
122
122
  # If the RHS is a schema, returns true if the schemas are equivalent.
123
123
  # If the RHS is a value, returns true if the value uses this schema.
124
-
124
+
125
125
  def ===(obj_)
126
126
  if obj_.kind_of?(Value)
127
127
  obj_.schema == self
@@ -129,86 +129,86 @@ module Versionomy
129
129
  obj_ == self
130
130
  end
131
131
  end
132
-
133
-
132
+
133
+
134
134
  def hash # :nodoc:
135
135
  @hash ||= @root_field.hash ^ @modules.hash
136
136
  end
137
-
138
-
137
+
138
+
139
139
  # Returns the root (most significant) field in this schema.
140
-
140
+
141
141
  def root_field
142
142
  @root_field
143
143
  end
144
-
145
-
144
+
145
+
146
146
  # Return the canonical field name given a name, or nil if the name
147
147
  # is not recognized.
148
-
148
+
149
149
  def canonical_name(name_)
150
150
  name_ = name_.to_sym
151
151
  name_ = @aliases[name_] || name_
152
152
  @names.include?(name_) ? name_ : nil
153
153
  end
154
-
155
-
154
+
155
+
156
156
  # Return the field with the given name, or nil if the given name
157
157
  # is not found in this schema. If include_aliases_ is set to true,
158
158
  # this also supports lookup by alias.
159
-
159
+
160
160
  def field_named(name_, include_aliases_=false)
161
161
  name_ = name_.to_sym
162
162
  name_ = @aliases[name_] || name_ if include_aliases_
163
163
  field_ = @names[name_]
164
164
  end
165
-
166
-
165
+
166
+
167
167
  # Returns an array of names present in this schema, in no particular
168
168
  # order. Does not include aliases.
169
-
169
+
170
170
  def names
171
171
  @names.keys
172
172
  end
173
-
174
-
173
+
174
+
175
175
  # Returns an array of modules that should be included in values that
176
176
  # use this schema.
177
-
177
+
178
178
  def modules
179
179
  @modules.dup
180
180
  end
181
-
182
-
181
+
182
+
183
183
  # Returns a hash of field name aliases.
184
-
184
+
185
185
  def aliases
186
186
  @aliases.dup
187
187
  end
188
-
189
-
188
+
189
+
190
190
  end
191
-
192
-
191
+
192
+
193
193
  # These methods are available in a schema definition block given to
194
194
  # Versionomy::Schema#create.
195
-
195
+
196
196
  class Builder
197
-
197
+
198
198
  include ::Blockenspiel::DSL
199
-
199
+
200
200
  def initialize() # :nodoc:
201
201
  @field = nil
202
202
  @modules = []
203
203
  @aliases = {}
204
204
  @defaults = { :integer => {}, :string => {}, :symbol => {} }
205
205
  end
206
-
207
-
206
+
207
+
208
208
  # Create the root field.
209
- #
209
+ #
210
210
  # Recognized options include:
211
- #
211
+ #
212
212
  # <tt>:type</tt>::
213
213
  # Type of field. This should be <tt>:integer</tt>, <tt>:string</tt>,
214
214
  # or <tt>:symbol</tt>. Default is <tt>:integer</tt>.
@@ -216,51 +216,51 @@ module Versionomy
216
216
  # Default value for the field if no value is explicitly set. Default
217
217
  # is 0 for an integer field, the empty string for a string field, or
218
218
  # the first symbol added for a symbol field.
219
- #
219
+ #
220
220
  # You may provide an optional block. Within the block, you may call
221
221
  # methods of Versionomy::Schema::FieldBuilder to customize this field.
222
- #
222
+ #
223
223
  # Raises Versionomy::Errors::IllegalValueError if the given default
224
224
  # value is not legal.
225
- #
225
+ #
226
226
  # Raises Versionomy::Errors::RangeOverlapError if a root field has
227
227
  # already been created.
228
-
228
+
229
229
  def field(name_, opts_={}, &block_)
230
230
  if @field
231
231
  raise Errors::RangeOverlapError, "Root field already defined"
232
232
  end
233
233
  @field = Schema::Field.new(name_, opts_.merge(:master_builder => self), &block_)
234
234
  end
235
-
236
-
235
+
236
+
237
237
  # Create a field alias.
238
-
238
+
239
239
  def alias_field(alias_name_, field_name_)
240
240
  @aliases[alias_name_.to_sym] = field_name_.to_sym
241
241
  end
242
-
243
-
242
+
243
+
244
244
  # Add a module to the schema. All values that use this schema will
245
245
  # include this module. This provides a way to add schema-specific
246
246
  # capabilities to version numbers.
247
-
247
+
248
248
  def add_module(mod_)
249
249
  @modules << mod_
250
250
  end
251
-
252
-
251
+
252
+
253
253
  # Provide a default bump procedure for the given type.
254
254
  # The type should be <tt>:integer</tt>, <tt>:string</tt>, or
255
255
  # <tt>:symbol</tt>. You must provide a block that takes a field value
256
256
  # and returns the "bumped" value. This procedure will be used for
257
257
  # all fields of this type, unless explicitly overridden by the field.
258
-
258
+
259
259
  def to_bump_type(type_, &block_)
260
260
  @defaults[type_][:bump] = block_
261
261
  end
262
-
263
-
262
+
263
+
264
264
  # Provide a default compare procedure for the given type.
265
265
  # The type should be <tt>:integer</tt>, <tt>:string</tt>, or
266
266
  # <tt>:symbol</tt>. You must provide a block that takes two values
@@ -269,53 +269,53 @@ module Versionomy
269
269
  # positive integer if the first value is greater. This procedure will
270
270
  # be used for all fields of this type, unless explicitly overridden
271
271
  # by the field.
272
-
272
+
273
273
  def to_compare_type(type_, &block_)
274
274
  @defaults[type_][:compare] = block_
275
275
  end
276
-
277
-
276
+
277
+
278
278
  # Provide a default canonicalization procedure for the given type.
279
279
  # The type should be <tt>:integer</tt>, <tt>:string</tt>, or
280
280
  # <tt>:symbol</tt>. You must provide a block that takes a field value
281
281
  # and returns the canonical value. This procedure will be used for
282
282
  # all fields of this type, unless explicitly overridden by the field.
283
-
283
+
284
284
  def to_canonicalize_type(type_, &block_)
285
285
  @defaults[type_][:canonicalize] = block_
286
286
  end
287
-
288
-
287
+
288
+
289
289
  # Provide a default value for the given type.
290
290
  # The type should be <tt>:integer</tt>, <tt>:string</tt>, or
291
291
  # <tt>:symbol</tt>. You must provide a default value that will be
292
292
  # used for all fields of this type, unless explicitly overridden by
293
293
  # the field.
294
-
294
+
295
295
  def default_value_for_type(type_, value_)
296
296
  @defaults[type_][:value] = value_
297
297
  end
298
-
299
-
298
+
299
+
300
300
  def _get_field # :nodoc:
301
301
  @field
302
302
  end
303
-
303
+
304
304
  def _get_modules # :nodoc:
305
305
  @modules
306
306
  end
307
-
307
+
308
308
  def _get_aliases # :nodoc:
309
309
  @aliases
310
310
  end
311
-
311
+
312
312
  def _get_default_setting(type_, setting_) # :nodoc:
313
313
  @defaults[type_][setting_]
314
314
  end
315
-
315
+
316
316
  end
317
-
318
-
317
+
318
+
319
319
  end
320
-
320
+
321
321
  end
@@ -1,15 +1,15 @@
1
1
  # -----------------------------------------------------------------------------
2
- #
2
+ #
3
3
  # Versionomy value
4
- #
4
+ #
5
5
  # -----------------------------------------------------------------------------
6
6
  # Copyright 2008-2009 Daniel Azuma
7
- #
7
+ #
8
8
  # All rights reserved.
9
- #
9
+ #
10
10
  # Redistribution and use in source and binary forms, with or without
11
11
  # modification, are permitted provided that the following conditions are met:
12
- #
12
+ #
13
13
  # * Redistributions of source code must retain the above copyright notice,
14
14
  # this list of conditions and the following disclaimer.
15
15
  # * Redistributions in binary form must reproduce the above copyright notice,
@@ -18,7 +18,7 @@
18
18
  # * Neither the name of the copyright holder, nor the names of any other
19
19
  # contributors to this software, may be used to endorse or promote products
20
20
  # derived from this software without specific prior written permission.
21
- #
21
+ #
22
22
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
23
  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
24
  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -34,35 +34,39 @@
34
34
  ;
35
35
 
36
36
 
37
- require 'yaml'
37
+ begin
38
+ require 'psych'
39
+ rescue ::LoadError
40
+ require 'yaml'
41
+ end
38
42
 
39
43
 
40
44
  module Versionomy
41
-
42
-
45
+
46
+
43
47
  # === Version number value
44
- #
48
+ #
45
49
  # A version number value is an ordered list of values, corresponding to an
46
50
  # ordered list of fields defined by a schema. For example, if the schema
47
51
  # is a simple one of the form "major.minor.tiny", then the the version
48
52
  # number "1.4.2" would have the values <tt>[1, 4, 2]</tt> in that order,
49
53
  # corresponding to the fields <tt>[:major, :minor, :tiny]</tt>.
50
- #
54
+ #
51
55
  # Version number values are comparable with other values that have an
52
56
  # equivalent schema.
53
-
57
+
54
58
  class Value
55
-
56
-
59
+
60
+
57
61
  # Create a value, given a hash or array of values, and a format. Both
58
62
  # these parameters are required.
59
- #
63
+ #
60
64
  # The values should either be a hash of field names and values, or an
61
65
  # array of values that will be interpreted in field order.
62
- #
66
+ #
63
67
  # You can also optionally provide default unparsing parameters for the
64
68
  # value.
65
-
69
+
66
70
  def initialize(values_, format_, unparse_params_=nil)
67
71
  unless values_.kind_of?(::Hash) || values_.kind_of?(::Array)
68
72
  raise ::ArgumentError, "Expected hash or array but got #{values_.class}"
@@ -83,8 +87,8 @@ module Versionomy
83
87
  modules_ = @_format.schema.modules
84
88
  extend(*modules_) if modules_.size > 0
85
89
  end
86
-
87
-
90
+
91
+
88
92
  def inspect # :nodoc:
89
93
  begin
90
94
  str_ = unparse
@@ -93,17 +97,17 @@ module Versionomy
93
97
  _inspect
94
98
  end
95
99
  end
96
-
100
+
97
101
  def _inspect # :nodoc:
98
102
  "#<#{self.class}:0x#{object_id.to_s(16)} " +
99
103
  @_field_path.map{ |field_| "#{field_.name}=#{@_values[field_.name].inspect}" }.join(' ')
100
104
  end
101
-
102
-
105
+
106
+
103
107
  # Returns a string representation generated by unparsing.
104
108
  # If unparsing fails, does not raise Versionomy::Errors::UnparseError,
105
109
  # but instead returns the string generated by +inspect+.
106
-
110
+
107
111
  def to_s
108
112
  begin
109
113
  unparse
@@ -111,149 +115,72 @@ module Versionomy
111
115
  _inspect
112
116
  end
113
117
  end
114
-
115
-
116
- # Marshal this version number.
117
-
118
- def marshal_dump # :nodoc:
119
- format_name_ = Format.canonical_name_for(@_format, true)
120
- unparsed_data_ = nil
121
- if @_format.respond_to?(:unparse_for_serialization)
122
- unparsed_data_ = @_format.unparse_for_serialization(self) rescue nil
123
- end
124
- unparsed_data_ ||= @_format.unparse(self) rescue nil
125
- data_ = [format_name_]
126
- case unparsed_data_
127
- when ::Array
128
- data_ << unparsed_data_[0]
129
- data_ << unparsed_data_[1] if unparsed_data_[1]
130
- when ::String
131
- data_ << unparsed_data_
132
- else
133
- data_ << values_array
134
- data_ << @_unparse_params if @_unparse_params
135
- end
136
- data_
137
- end
138
-
139
-
140
- # Unmarshal this version number.
141
-
142
- def marshal_load(data_) # :nodoc:
143
- format_ = Format.get(data_[0], true)
144
- if data_[1].kind_of?(::String)
145
- val_ = format_.parse(data_[1], data_[2])
146
- initialize(val_.values_array, format_, val_.unparse_params)
147
- else
148
- initialize(data_[1], format_, data_[2])
149
- end
150
- end
151
-
152
-
153
- # YAML tags. The last one is the canonical one.
154
- yaml_as "tag:danielazuma.com,2009:version"
155
- yaml_as "tag:verse15.com,2009:version"
156
-
157
-
158
- # Deserialize a version number from YAML
159
-
160
- def self.yaml_new(klass_, tag_, data_) # :nodoc:
161
- unless data_.kind_of?(::Hash)
162
- raise ::YAML::TypeError, "Invalid version format: #{val_.inspect}"
163
- end
164
- format_ = Format.get(data_['format'], true)
165
- value_ = data_['value']
166
- if value_
167
- format_.parse(value_, data_['parse_params'])
168
- else
169
- Value.new(format_, data_['fields'], data_['unparse_params'])
170
- end
171
- end
172
-
173
-
174
- # Serialize this version number to YAML format.
175
-
176
- def to_yaml(opts_={})
177
- data_ = marshal_dump
178
- ::YAML::quick_emit(nil, opts_) do |out_|
179
- out_.map(taguri, to_yaml_style) do |map_|
180
- map_.add('format', data_[0])
181
- if data_[1].kind_of?(::String)
182
- map_.add('value', data_[1])
183
- map_.add('parse_params', data_[2]) if data_[2]
184
- else
185
- map_.add('fields', data_[1])
186
- map_.add('unparse_params', data_[2]) if data_[2]
187
- end
188
- end
189
- end
190
- end
191
-
192
-
118
+
119
+
193
120
  # Unparse this version number and return a string.
194
- #
121
+ #
195
122
  # Raises Versionomy::Errors::UnparseError if unparsing failed.
196
-
123
+
197
124
  def unparse(params_=nil)
198
125
  @_format.unparse(self, params_)
199
126
  end
200
-
201
-
127
+
128
+
202
129
  # Return the schema defining the structure and semantics of this
203
130
  # version number.
204
-
131
+
205
132
  def schema
206
133
  @_format.schema
207
134
  end
208
-
209
-
135
+
136
+
210
137
  # Return the format defining the schema and formatting/parsing of
211
138
  # this version number.
212
-
139
+
213
140
  def format
214
141
  @_format
215
142
  end
216
-
217
-
143
+
144
+
218
145
  # Return the unparsing parameters for this value.
219
146
  # Returns nil if this value was not created using a parser.
220
-
147
+
221
148
  def unparse_params
222
149
  @_unparse_params ? @_unparse_params.dup : nil
223
150
  end
224
-
225
-
151
+
152
+
226
153
  # Iterates over each field, in field order, yielding the field name and value.
227
-
154
+
228
155
  def each_field
229
156
  @_field_path.each do |field_|
230
157
  yield(field_, @_values[field_.name])
231
158
  end
232
159
  end
233
-
234
-
160
+
161
+
235
162
  # Iterates over each field, in field order, yielding the
236
163
  # Versionomy::Schema::Field object and value.
237
-
164
+
238
165
  def each_field_object # :nodoc:
239
166
  @_field_path.each do |field_|
240
167
  yield(field_, @_values[field_.name])
241
168
  end
242
169
  end
243
-
244
-
170
+
171
+
245
172
  # Returns an array of recognized field names for this value, in field order.
246
173
  # This is the order of the fields actually present in this value, in
247
174
  # order from most to least significant.
248
-
175
+
249
176
  def field_names
250
177
  @_field_path.map{ |field_| field_.name }
251
178
  end
252
-
253
-
179
+
180
+
254
181
  # Returns true if this value contains the given field, which may be specified
255
182
  # as a field object, name, or index.
256
-
183
+
257
184
  def has_field?(field_)
258
185
  case field_
259
186
  when Schema::Field
@@ -266,38 +193,38 @@ module Versionomy
266
193
  raise ::ArgumentError
267
194
  end
268
195
  end
269
-
270
-
196
+
197
+
271
198
  # Returns the value of the given field, or nil if the field is not
272
199
  # recognized. The field may be specified as a field object, field name,
273
200
  # or field index.
274
-
201
+
275
202
  def [](field_)
276
203
  @_values[_interpret_field(field_)]
277
204
  end
278
-
279
-
205
+
206
+
280
207
  # Returns the value as an array of field values, in field order.
281
208
  # This is the order of the fields actually present in this value, in
282
209
  # order from most to least significant.
283
-
210
+
284
211
  def values_array
285
212
  @_field_path.map{ |field_| @_values[field_.name] }
286
213
  end
287
-
288
-
214
+
215
+
289
216
  # Returns the value as a hash of values keyed by field name.
290
-
217
+
291
218
  def values_hash
292
219
  @_values.dup
293
220
  end
294
-
295
-
221
+
222
+
296
223
  # Returns a new version number created by bumping the given field. The
297
224
  # field may be specified as a field object, field name, or field index.
298
225
  # Returns self unchanged if the field was not recognized or could not
299
226
  # be modified.
300
-
227
+
301
228
  def bump(field_)
302
229
  name_ = _interpret_field(field_)
303
230
  return self unless name_ && @_values.include?(name_)
@@ -315,13 +242,13 @@ module Versionomy
315
242
  end
316
243
  self
317
244
  end
318
-
319
-
245
+
246
+
320
247
  # Returns a new version number created by resetting the given field. The
321
248
  # field may be specified as a field object, field name, or field index.
322
249
  # Returns self unchanged if the field was not recognized or could not
323
250
  # be modified.
324
-
251
+
325
252
  def reset(field_)
326
253
  name_ = _interpret_field(field_)
327
254
  return self unless name_ && @_values.include?(name_)
@@ -337,33 +264,33 @@ module Versionomy
337
264
  end
338
265
  self
339
266
  end
340
-
341
-
267
+
268
+
342
269
  # Returns a new version number created by cloning this version number
343
270
  # and changing the given field values.
344
- #
271
+ #
345
272
  # You should pass in a hash of field names to values. These are the
346
273
  # fields to modify; any other fields will be left alone, unless they
347
274
  # are implicitly changed by the modifications you are making.
348
275
  # For example, changing the :release_type on a value using the standard
349
276
  # format, may change which fields are present in the resulting value.
350
- #
277
+ #
351
278
  # You may also pass a delta hash to modify the unparse params stored in
352
279
  # the value.
353
-
280
+
354
281
  def change(values_={}, unparse_params_={})
355
282
  unparse_params_ = @_unparse_params.merge(unparse_params_) if @_unparse_params
356
283
  values_ = _canonicalize_values_hash(values_)
357
284
  Value.new(@_values.merge(values_), @_format, unparse_params_)
358
285
  end
359
-
360
-
286
+
287
+
361
288
  # Attempts to convert this value to the given format, and returns the
362
289
  # resulting value.
363
- #
290
+ #
364
291
  # Raises Versionomy::Errors::ConversionError if the value could not
365
292
  # be converted.
366
-
293
+
367
294
  def convert(format_, convert_params_=nil)
368
295
  if format_.kind_of?(::String) || format_.kind_of?(::Symbol)
369
296
  format_ = Format.get(format_)
@@ -389,18 +316,18 @@ module Versionomy
389
316
  end
390
317
  end
391
318
  end
392
-
393
-
319
+
320
+
394
321
  def hash # :nodoc:
395
322
  @_hash ||= @_values.hash
396
323
  end
397
-
398
-
324
+
325
+
399
326
  # Returns true if this version number is equivalent to the given number.
400
327
  # This type of equality means their schemas are compatible and their
401
328
  # field values are equal.
402
329
  # Note that this is different from the definition of <tt>==</tt>.
403
-
330
+
404
331
  def eql?(obj_)
405
332
  if obj_.kind_of?(::String)
406
333
  obj_ = @_format.parse(obj_) rescue nil
@@ -413,25 +340,25 @@ module Versionomy
413
340
  end
414
341
  true
415
342
  end
416
-
417
-
343
+
344
+
418
345
  # Returns true if this version number is value-equal to the given number.
419
346
  # This type of equality means that they are equivalent, or that it is
420
347
  # possible to convert the RHS to the LHS's format, and that they would
421
348
  # be equivalent after such a conversion has taken place.
422
349
  # Note that this is different from the definition of <tt>eql?</tt>.
423
-
350
+
424
351
  def ==(obj_)
425
352
  (self <=> obj_) == 0
426
353
  end
427
-
428
-
354
+
355
+
429
356
  # Compare this version number with the given version number,
430
357
  # returning 0 if the two are value-equal, a negative number if the RHS
431
358
  # is greater, or a positive number if the LHS is greater.
432
359
  # The comparison may succeed even if the two have different schemas,
433
360
  # if the RHS can be converted to the LHS's format.
434
-
361
+
435
362
  def <=>(obj_)
436
363
  if obj_.kind_of?(::String)
437
364
  obj_ = @_format.parse(obj_)
@@ -450,12 +377,12 @@ module Versionomy
450
377
  end
451
378
  0
452
379
  end
453
-
454
-
380
+
381
+
455
382
  # Compare this version number with the given version number.
456
383
  # The comparison may succeed even if the two have different schemas,
457
384
  # if the RHS can be converted to the LHS's format.
458
-
385
+
459
386
  def <(obj_)
460
387
  val_ = (self <=> obj_)
461
388
  unless val_
@@ -463,12 +390,12 @@ module Versionomy
463
390
  end
464
391
  val_ < 0
465
392
  end
466
-
467
-
393
+
394
+
468
395
  # Compare this version number with the given version number.
469
396
  # The comparison may succeed even if the two have different schemas,
470
397
  # if the RHS can be converted to the LHS's format.
471
-
398
+
472
399
  def >(obj_)
473
400
  val_ = (self <=> obj_)
474
401
  unless val_
@@ -476,20 +403,137 @@ module Versionomy
476
403
  end
477
404
  val_ > 0
478
405
  end
479
-
480
-
406
+
407
+
481
408
  include ::Comparable
482
-
483
-
409
+
410
+
484
411
  # Field values may be retrieved by calling them as methods.
485
-
412
+
486
413
  def method_missing(symbol_)
487
414
  self[symbol_] || super
488
415
  end
489
-
490
-
416
+
417
+
418
+ # :stopdoc:
419
+
420
+
421
+ # Marshal support
422
+
423
+ # Marshal this version number
424
+ def marshal_dump
425
+ format_name_ = Format.canonical_name_for(@_format, true)
426
+ unparsed_data_ = nil
427
+ if @_format.respond_to?(:unparse_for_serialization)
428
+ unparsed_data_ = @_format.unparse_for_serialization(self) rescue nil
429
+ end
430
+ unparsed_data_ ||= @_format.unparse(self) rescue nil
431
+ data_ = [format_name_]
432
+ case unparsed_data_
433
+ when ::Array
434
+ data_ << unparsed_data_[0]
435
+ data_ << unparsed_data_[1] if unparsed_data_[1]
436
+ when ::String
437
+ data_ << unparsed_data_
438
+ else
439
+ data_ << values_array
440
+ data_ << @_unparse_params if @_unparse_params
441
+ end
442
+ data_
443
+ end
444
+
445
+ # Unmarshal this version number.
446
+ def marshal_load(data_)
447
+ format_ = Format.get(data_[0], true)
448
+ if data_[1].kind_of?(::String)
449
+ val_ = format_.parse(data_[1], data_[2])
450
+ initialize(val_.values_array, format_, val_.unparse_params)
451
+ else
452
+ initialize(data_[1], format_, data_[2])
453
+ end
454
+ end
455
+
456
+
457
+ if defined?(::Psych)
458
+
459
+ # YAML support through psych
460
+
461
+ # YAML tags. The last one is the canonical one.
462
+ yaml_tag "tag:danielazuma.com,2009:version"
463
+ yaml_tag "tag:verse15.com,2009:version"
464
+
465
+ # Deserialize a version number from YAML
466
+ def init_with(coder_) # :nodoc:
467
+ format_ = Format.get(coder_['format'], true)
468
+ value_ = coder_['value']
469
+ if value_
470
+ value_ = format_.parse(value_, coder_['parse_params'])
471
+ initialize(value_.values_array, format_, value_.unparse_params)
472
+ else
473
+ initialize(coder_['fields'], format_, coder_['unparse_params'])
474
+ end
475
+ end
476
+
477
+ # Serialize this version number to YAML format.
478
+ def encode_with(coder_) # :nodoc:
479
+ data_ = marshal_dump
480
+ coder_['format'] = data_[0]
481
+ if data_[1].kind_of?(::String)
482
+ coder_['value'] = data_[1]
483
+ coder_['parse_params'] = data_[2] if data_[2]
484
+ else
485
+ coder_['fields'] = data_[1]
486
+ coder_['unparse_params'] = data_[2] if data_[2]
487
+ end
488
+ end
489
+
490
+ else
491
+
492
+ # YAML support through syck
493
+
494
+ # YAML tags. The last one is the canonical one.
495
+ yaml_as "tag:danielazuma.com,2009:version"
496
+ yaml_as "tag:verse15.com,2009:version"
497
+
498
+ # Deserialize a version number from YAML
499
+ def self.yaml_new(klass_, tag_, data_) # :nodoc:
500
+ unless data_.kind_of?(::Hash)
501
+ raise ::YAML::TypeError, "Invalid version format: #{data_.inspect}"
502
+ end
503
+ format_ = Format.get(data_['format'], true)
504
+ value_ = data_['value']
505
+ if value_
506
+ format_.parse(value_, data_['parse_params'])
507
+ else
508
+ Value.new(data_['fields'], format_, data_['unparse_params'])
509
+ end
510
+ end
511
+
512
+ # Serialize this version number to YAML format.
513
+ def to_yaml(opts_={})
514
+ data_ = marshal_dump
515
+ ::YAML.quick_emit(nil, opts_) do |out_|
516
+ out_.map(taguri, to_yaml_style) do |map_|
517
+ map_.add('format', data_[0])
518
+ if data_[1].kind_of?(::String)
519
+ map_.add('value', data_[1])
520
+ map_.add('parse_params', data_[2]) if data_[2]
521
+ else
522
+ map_.add('fields', data_[1])
523
+ map_.add('unparse_params', data_[2]) if data_[2]
524
+ end
525
+ end
526
+ end
527
+ end
528
+
529
+ end
530
+
531
+
532
+ # :startdoc:
533
+
534
+
491
535
  private
492
-
536
+
493
537
  def _interpret_field(field_) # :nodoc:
494
538
  case field_
495
539
  when Schema::Field
@@ -501,8 +545,8 @@ module Versionomy
501
545
  @_format.schema.canonical_name(field_)
502
546
  end
503
547
  end
504
-
505
-
548
+
549
+
506
550
  def _canonicalize_values_hash(values_) # :nodoc:
507
551
  schema_ = @_format.schema
508
552
  new_values_ = {}
@@ -512,9 +556,9 @@ module Versionomy
512
556
  end
513
557
  new_values_
514
558
  end
515
-
516
-
559
+
560
+
517
561
  end
518
-
519
-
562
+
563
+
520
564
  end