versionomy 0.1.3 → 0.2.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.
@@ -0,0 +1,382 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Versionomy standard format implementation
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2008-2009 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ module Versionomy
38
+
39
+ module Format
40
+
41
+
42
+ # Get the standard format.
43
+ # This is identical to calling <tt>get('standard')</tt>.
44
+ #
45
+ # The standard format is designed to handle most commonly-used version
46
+ # number forms, and allow parsing and comparison between them.
47
+ #
48
+ # The standard schema is the heart of this format, providing a
49
+ # common structure for most version numbers.
50
+ #
51
+ # It begins with four numeric fields:
52
+ # "<tt>major.minor.tiny.tiny2</tt>".
53
+ #
54
+ # The next field, <tt>:release_type</tt>, defines the remaining
55
+ # structure. The release type can be one of these symbolic values:
56
+ # <tt>:development</tt>, <tt>:alpha</tt>, <tt>:beta</tt>,
57
+ # <tt>:preview</tt>, <tt>:release_candidate</tt>, <tt>:release</tt>.
58
+ #
59
+ # Depending on that value, additional fields become available. For
60
+ # example, the <tt>:alpha</tt> value enables the fields
61
+ # <tt>:alpha_version</tt> and <tt>:alpha_minor</tt>, which represent
62
+ # version number fields after the "a" alpha specifier. i.e. "2.1a30"
63
+ # has an alpha_version of 30. "2.1a30.2" also has an alpha_minor of 2.
64
+ # Similarly, the <tt>:beta</tt> release_type value enables the fields
65
+ # <tt>:beta_version</tt> and <tt>:beta_minor</tt>. A release_type
66
+ # of <tt>:release</tt> enables <tt>:patchlevel</tt> and
67
+ # <tt>:patchlevel_minor</tt>, to support versions like "1.8.7p72".
68
+ #
69
+ # The format itself is a delimiter-based format that understands a
70
+ # wide variety of string representations of this version schema.
71
+ # Examples of supported syntax include:
72
+ #
73
+ # 2.0
74
+ # 2.0.42.10
75
+ # 2.0b2
76
+ # 2.0rc15
77
+ # 2.0-5
78
+ # 2.0p5
79
+ # 2.0 Alpha 1
80
+ # 2.0a5.3
81
+ # 2.1.42.10-4.3
82
+ #
83
+ # Because the standard format is based on Versionomy::Format::Delimiter,
84
+ # a number of parameters are available for parsing and unparsing. See
85
+ # the documentation for the delimiter class for more information.
86
+ #
87
+ # Two of the fields have styles that can be set when unparsing.
88
+ # The <tt>:release_type</tt> field can be unparsed as either
89
+ # <tt>:long</tt> style (e.g. "1.0alpha2") or <tt>:short</tt> style
90
+ # (e.g. "1.0a2"). The patchlevel field can be unparsed as either
91
+ # <tt>:number</tt> style (e.g. "2.1-1") or <tt>:letter</tt> style
92
+ # (e.g. "2.1a"). Most fields can have their delimiter specified during
93
+ # unparsing as well.
94
+ #
95
+ # For the exact annotated definition of the standard schema and format,
96
+ # see the source code for Versionomy::Format::Standard#create.
97
+
98
+ def self.standard
99
+ get('standard')
100
+ end
101
+
102
+
103
+ # This is a namespace for the implementation of the Standard schema
104
+ # and format.
105
+
106
+ module Standard
107
+
108
+
109
+ # Extra methods added to version values that use the standard schema.
110
+
111
+ module ExtraMethods
112
+
113
+
114
+ # Returns true if the version is a prerelease version
115
+
116
+ def prerelease?
117
+ self.release_type != :final
118
+ end
119
+
120
+
121
+ # Returns the release for this version.
122
+ # For example, converts "1.2.0a1" to "1.2.0".
123
+ # Non-prerelease versions return themselves.
124
+
125
+ def release
126
+ self.change(:release_type => :final)
127
+ end
128
+
129
+
130
+ end
131
+
132
+
133
+ # Create the standard format.
134
+ # This method is called internally when Versionomy initializes itself,
135
+ # and you should not need to call it again. It is documented, however,
136
+ # so that you can inspect its source code from RDoc, since the source
137
+ # contains useful examples of how to use the schema and format
138
+ # definition DSLs.
139
+
140
+ def self.create
141
+
142
+ # The following is the definition of the standard schema
143
+ schema_ = Schema.create do
144
+
145
+ # The major field has the default value of 1. Most other fields
146
+ # have a default value of 0. Thus, the default version number
147
+ # overall is "1.0".
148
+ # We first create the core version fields "major.minor.tiny.tiny2".
149
+ field(:major, :default_value => 1) do
150
+ field(:minor) do
151
+ field(:tiny) do
152
+ field(:tiny2) do
153
+
154
+ # The next field is a symbolic field that specifies the
155
+ # release type: e.g. beta, release candidate, release, etc.
156
+ field(:release_type, :type => :symbol) do
157
+
158
+ # Development releases are typically expressed like
159
+ # "1.0d3" and are intended for unstable development
160
+ # progress. Bumping the release type will change it to
161
+ # alpha.
162
+ symbol(:development, :bump => :alpha)
163
+
164
+ # Alpha releases are typically expressed like "1.0a2" and
165
+ # are intended for internal testing.
166
+ # Bumping the release type advances to beta.
167
+ symbol(:alpha, :bump => :beta)
168
+
169
+ # Beta releases are typically expressed like "1.0b2" and
170
+ # are intended for external or public testing.
171
+ # Bumping the release type advances to release candidate.
172
+ symbol(:beta, :bump => :release_candidate)
173
+
174
+ # Release candidate releases are typically expressed like
175
+ # "1.0rc2" and are intended for final public testing
176
+ # prior to release.
177
+ # Bumping the release type advances to final release.
178
+ symbol(:release_candidate, :bump => :final)
179
+
180
+ # Preview releases represent an alternative release type
181
+ # progression, and are typically used for public testing
182
+ # similar to beta or release candidate.
183
+ # Bumping the release type advances to final release.
184
+ symbol(:preview, :bump => :final)
185
+
186
+ # This type represents a final release. This is the
187
+ # default value for the release_type field if no value is
188
+ # explicitly provided.
189
+ # Bumping the release type has no effect.
190
+ symbol(:final, :bump => :final)
191
+ default_value(:final)
192
+
193
+ # If the release type is development, these fields are
194
+ # made available to indicate which development release
195
+ # is being represented.
196
+ field(:development_version, :only => :development,
197
+ :default_value => 1) do
198
+ field(:development_minor)
199
+ end
200
+
201
+ # If the release type is alpha, these fields are made
202
+ # available to indicate which alpha release is being
203
+ # represented.
204
+ field(:alpha_version, :only => :alpha, :default_value => 1) do
205
+ field(:alpha_minor)
206
+ end
207
+
208
+ # If the release type is beta, these fields are made
209
+ # available to indicate which beta release is being
210
+ # represented.
211
+ field(:beta_version, :only => :beta, :default_value => 1) do
212
+ field(:beta_minor)
213
+ end
214
+
215
+ # If the release type is release candidate, these fields
216
+ # are made available to indicate which release candidate
217
+ # is being represented.
218
+ field(:release_candidate_version, :only => :release_candidate,
219
+ :default_value => 1) do
220
+ field(:release_candidate_minor)
221
+ end
222
+
223
+ # If the release type is preview, these fields are made
224
+ # available to indicate which preview release is being
225
+ # represented.
226
+ field(:preview_version, :only => :preview, :default_value => 1) do
227
+ field(:preview_minor)
228
+ end
229
+
230
+ # If the release type is final, these fields are made
231
+ # available to indicate an optional patchlevel.
232
+ field(:patchlevel, :only => :final) do
233
+ field(:patchlevel_minor)
234
+ end
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
240
+
241
+ # Add the methods in this module to each value
242
+ add_module(Format::Standard::ExtraMethods)
243
+ end
244
+
245
+ # The following is the definition of the standard format. It
246
+ # understands the standard schema defined above.
247
+ format_ = Format::Delimiter.new(schema_) do
248
+
249
+ # All version number strings must start with the major version.
250
+ # Unlike other fields, it is not preceded by any delimiter.
251
+ field(:major) do
252
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
253
+ end
254
+
255
+ # The remainder of the core version number are represented as
256
+ # integers delimited by periods by default. Each is also dependent
257
+ # on the presence of the previous field, so :requires_previous_field
258
+ # retains its default value of true. Finally, they can be optional
259
+ # in an unparsed string if they are set to the default value of 0.
260
+ field(:minor) do
261
+ recognize_number(:default_value_optional => true)
262
+ end
263
+ field(:tiny) do
264
+ recognize_number(:default_value_optional => true)
265
+ end
266
+ field(:tiny2) do
267
+ recognize_number(:default_value_optional => true)
268
+ end
269
+
270
+ # The release type field is the most complex field because of the
271
+ # variety of syntaxes we support. The basic strategy is to map
272
+ # a few specific sets of characters as signaling particular release
273
+ # types. For example, the "a" in "1.0a5" signals an alpha release.
274
+ # If no such release type marker is found, it defaults to the final
275
+ # release type.
276
+ # We set up two styles, a short style and a long style. Short style
277
+ # syntax looks like "1.0a5". Long syntax looks more like
278
+ # "1.0 Alpha 5". The parsed value retains knowledge of which style
279
+ # it came from so it can be reconstructed when the value is unparsed.
280
+ # Finally, we turn requires_previous_field off because the release
281
+ # type syntax markers don't require any particular set of the core
282
+ # version number fields to be present. "1.0a5" and "1.0.0.0a5" are
283
+ # both valid version numbers.
284
+ field(:release_type, :requires_previous_field => false,
285
+ :default_style => :short) do
286
+ # First check for "short form" syntax. Not that we support post-
287
+ # delimiters; that is, we recognize "1.0 pre-2" where the hyphen
288
+ # is a post-delimiter. Also notice that we expect prerelease types
289
+ # to be followed by a numeric prerelease version number.
290
+ recognize_regexp_map(:style => :short, :default_delimiter => '',
291
+ :delimiter_regexp => '-|\.|\s?',
292
+ :post_delimiter_regexp => '-|\.|\s?',
293
+ :expected_follower_regexp => '\d') do
294
+ map(:development, 'd')
295
+ map(:alpha, 'a')
296
+ map(:beta, 'b')
297
+ map(:release_candidate, 'rc')
298
+ map(:preview, 'pre')
299
+ # Note that we omit the value <tt>:final</tt>. This is because
300
+ # that value is signaled by the absence of any syntax in the
301
+ # version string, including the absence of any delimiters. So we
302
+ # just allow it to fall through to the default.
303
+ end
304
+ # Check for "long form" syntax. Note again that we omit :final.
305
+ recognize_regexp_map(:style => :long, :default_delimiter => '',
306
+ :delimiter_regexp => '-|\.|\s?',
307
+ :post_delimiter_regexp => '-|\.|\s?',
308
+ :expected_follower_regexp => '\d') do
309
+ map(:development, 'dev')
310
+ map(:alpha, 'alpha')
311
+ map(:beta, 'beta')
312
+ map(:release_candidate, 'rc')
313
+ map(:preview, 'preview')
314
+ end
315
+ end
316
+
317
+ # The development version must appear in the string if it is present
318
+ # in the value, even if the value is 0. Similar for all the other
319
+ # prerelease version numbers: alpha, beta, release candidate, and
320
+ # preview. However, the minor fields are optional.
321
+ field(:development_version) do
322
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
323
+ end
324
+ field(:development_minor) do
325
+ recognize_number(:default_value_optional => true)
326
+ end
327
+ field(:alpha_version) do
328
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
329
+ end
330
+ field(:alpha_minor) do
331
+ recognize_number(:default_value_optional => true)
332
+ end
333
+ field(:beta_version) do
334
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
335
+ end
336
+ field(:beta_minor) do
337
+ recognize_number(:default_value_optional => true)
338
+ end
339
+ field(:release_candidate_version) do
340
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
341
+ end
342
+ field(:release_candidate_minor) do
343
+ recognize_number(:default_value_optional => true)
344
+ end
345
+ field(:preview_version) do
346
+ recognize_number(:delimiter_regexp => '', :default_delimiter => '')
347
+ end
348
+ field(:preview_minor) do
349
+ recognize_number(:default_value_optional => true)
350
+ end
351
+
352
+ # The patchlevel field does not require the previous field (which is
353
+ # release_type). Here we also set up two styles: a numeric style and
354
+ # a letter style. So "1.0a" and "1.0-1" are equivalent.
355
+ field(:patchlevel, :requires_previous_field => false,
356
+ :default_value_optional => true, :default_style => :number) do
357
+ recognize_number(:style => :number, :default_delimiter => '-',
358
+ :delimiter_regexp => '(-|\.|\s?)p|-')
359
+ recognize_letter(:style => :letter, :default_delimiter => '',
360
+ :delimiter_regexp => '-|\.|\s?',
361
+ :expected_follower_regexp => '\z')
362
+ end
363
+ field(:patchlevel_minor) do
364
+ recognize_number(:default_value_optional => true)
365
+ end
366
+
367
+ # By default, we require that at least the major and minor fields
368
+ # appear in an unparsed version string.
369
+ default_unparse_params(:required_fields => [:minor])
370
+ end
371
+ end
372
+
373
+
374
+ end
375
+
376
+
377
+ register('standard', Format::Standard.create) unless get('standard')
378
+
379
+
380
+ end
381
+
382
+ end
@@ -48,21 +48,90 @@ module Versionomy
48
48
  # only that schema's version numbers.
49
49
  #
50
50
  # Under many circumstances, you should use the standard format, which
51
- # can be retrieved by calling Versionomy::Formats#standard. This format
51
+ # can be retrieved by calling Versionomy::Format#standard. This format
52
52
  # understands most common version numbers, including prerelease
53
53
  # (e.g. alpha, beta, release candidate, etc.) forms and patchlevels.
54
54
  #
55
55
  # You may also create your own formats, either by implementing the
56
- # format contract (see Versionomy::Format::Base) or by using the
56
+ # format contract (see Versionomy::Format::Base), or by using the
57
57
  # Versionomy::Format::Delimiter tool, which can be used to construct
58
58
  # parsers for many version number formats.
59
59
  #
60
60
  # Formats may be registered with Versionomy and given a name using the
61
- # methods of this Versionomy::Formats. This allows version numbers to be
62
- # serialized with their format.
61
+ # methods of this module. This allows version numbers to be serialized
62
+ # with their format.
63
+ #
64
+ # Finally, this module serves as a namespace for format implementations.
63
65
 
64
66
  module Format
67
+
68
+ @names_to_formats = ::Hash.new
69
+ @formats_to_names = ::Hash.new
70
+
71
+ class << self
72
+
73
+
74
+ # Get the format with the given name.
75
+ #
76
+ # If the given name has not been defined, and strict is set to true,
77
+ # raises Versionomy::Errors::UnknownFormatError. If strict is set to
78
+ # false, returns nil if the given name has not been defined.
79
+
80
+ def get(name_, strict_=false)
81
+ format_ = @names_to_formats[name_.to_s]
82
+ if format_.nil? && strict_
83
+ raise Errors::UnknownFormatError, name_
84
+ end
85
+ format_
86
+ end
87
+
88
+
89
+ # Register the given format under the given name.
90
+ #
91
+ # Valid names may contain only letters, digits, underscores, dashes,
92
+ # and periods.
93
+ #
94
+ # Raises Versionomy::Errors::FormatRedefinedError if the name has
95
+ # already been defined.
96
+
97
+ def register(name_, format_)
98
+ name_ = name_.to_s
99
+ unless name_ =~ /\A[\w.-]+\z/
100
+ raise ::ArgumentError, "Illegal name: #{name_.inspect}"
101
+ end
102
+ if @names_to_formats.include?(name_)
103
+ raise Errors::FormatRedefinedError, name_
104
+ end
105
+ @names_to_formats[name_] = format_
106
+ @formats_to_names[format_.object_id] = name_
107
+ end
108
+
109
+
110
+ # Get the canonical name for the given format, as a string.
111
+ # This is the first name the format was registered under.
112
+ #
113
+ # If the given format was never registered, and strict is set to true,
114
+ # raises Versionomy::Errors::UnknownFormatError. If strict is set to
115
+ # false, returns nil if the given format was never registered.
116
+
117
+ def canonical_name_for(format_, strict_=false)
118
+ name_ = @formats_to_names[format_.object_id]
119
+ if name_.nil? && strict_
120
+ raise Errors::UnknownFormatError
121
+ end
122
+ name_
123
+ end
124
+
125
+
126
+ end
127
+
65
128
  end
66
129
 
67
130
 
131
+ # Versionomy::Formats is an alias for Versionomy::Format, for backward
132
+ # compatibility with version 0.1.0 code. It is deprecated; use
133
+ # Versionomy::Format instead.
134
+ Formats = Format
135
+
136
+
68
137
  end
@@ -48,27 +48,27 @@ module Versionomy
48
48
 
49
49
 
50
50
  # Gets the current default format. Usually this is the "standard"
51
- # format returned by Versionomy::Formats.standard.
51
+ # format returned by Versionomy::Format.standard.
52
52
 
53
53
  def default_format
54
- @default_format ||= Formats.standard
54
+ @default_format ||= Format.standard
55
55
  end
56
56
 
57
57
 
58
58
  # Sets the default format used by other methods of this convenience
59
59
  # interface. Usually, this is set to the "standard" format returned by
60
- # Versionomy::Formats.standard and should not be changed.
60
+ # Versionomy::Format.standard and should not be changed.
61
61
  #
62
62
  # The format can be specified as a format object or the name of a format
63
- # registered with Versionomy::Formats. If the format is set to nil, the
63
+ # registered with Versionomy::Format. If the format is set to nil, the
64
64
  # default_format will be reset to the "standard" format.
65
65
  #
66
66
  # Raises Versionomy::Errors::UnknownFormatError if a name is given that
67
67
  # is not registered.
68
68
 
69
69
  def default_format=(format_)
70
- if format_.kind_of?(String) || format_.kind_of?(Symbol)
71
- format_ = Formats.get(format_, true)
70
+ if format_.kind_of?(::String) || format_.kind_of?(::Symbol)
71
+ format_ = Format.get(format_, true)
72
72
  end
73
73
  @default_format = format_
74
74
  end
@@ -81,7 +81,7 @@ module Versionomy
81
81
  # array of values that will be interpreted in field order.
82
82
  #
83
83
  # The format can be specified as a format object or the name of a format
84
- # registered with Versionomy::Formats. If the format is omitted or set
84
+ # registered with Versionomy::Format. If the format is omitted or set
85
85
  # to nil, the default_format will be used.
86
86
  #
87
87
  # You can also optionally provide default parameters to be used when
@@ -90,12 +90,16 @@ module Versionomy
90
90
  # Raises Versionomy::Errors::UnknownFormatError if a name is given that
91
91
  # is not registered.
92
92
 
93
- def create(values_=[], format_=nil, unparse_params_=nil)
94
- if format_.kind_of?(String) || format_.kind_of?(Symbol)
95
- format_ = Formats.get(format_, true)
93
+ def create(values_=nil, format_=nil, unparse_params_=nil)
94
+ if format_.kind_of?(::Hash) && unparse_params_.nil?
95
+ unparse_params_ = format_
96
+ format_ = nil
97
+ end
98
+ if format_.kind_of?(::String) || format_.kind_of?(::Symbol)
99
+ format_ = Format.get(format_, true)
96
100
  end
97
101
  format_ ||= default_format
98
- Value.new(values_, format_, unparse_params_)
102
+ Value.new(values_ || [], format_, unparse_params_)
99
103
  end
100
104
 
101
105
 
@@ -103,7 +107,7 @@ module Versionomy
103
107
  # format.
104
108
  #
105
109
  # The format can be specified as a format object or the name of a format
106
- # registered with Versionomy::Formats. If the format is omitted or set
110
+ # registered with Versionomy::Format. If the format is omitted or set
107
111
  # to nil, the default_format will be used.
108
112
  #
109
113
  # The parameter hash, if present, will be passed as parsing parameters
@@ -115,8 +119,12 @@ module Versionomy
115
119
  # May raise Versionomy::Errors::ParseError if parsing failed.
116
120
 
117
121
  def parse(str_, format_=nil, parse_params_=nil)
118
- if format_.kind_of?(String) || format_.kind_of?(Symbol)
119
- format_ = Formats.get(format_, true)
122
+ if format_.kind_of?(::Hash) && parse_params_.nil?
123
+ parse_params_ = format_
124
+ format_ = nil
125
+ end
126
+ if format_.kind_of?(::String) || format_.kind_of?(::Symbol)
127
+ format_ = Format.get(format_, true)
120
128
  end
121
129
  format_ ||= default_format
122
130
  format_.parse(str_, parse_params_)
@@ -69,7 +69,6 @@ module Versionomy
69
69
  def initialize(name_, opts_={}, &block_)
70
70
  @name = name_.to_sym
71
71
  @type = opts_[:type] || :integer
72
- @default_value = opts_[:default_value]
73
72
  if @type == :symbol
74
73
  @symbol_info = ::Hash.new
75
74
  @symbol_order = ::Array.new
@@ -77,13 +76,21 @@ module Versionomy
77
76
  @symbol_info = nil
78
77
  @symbol_order = nil
79
78
  end
79
+ @default_value = opts_[:default_value]
80
80
  @bump_proc = nil
81
81
  @compare_proc = nil
82
82
  @canonicalize_proc = nil
83
+ master_builder_ = opts_[:master_builder]
84
+ if master_builder_
85
+ @bump_proc = master_builder_._get_default_setting(@type, :bump)
86
+ @compare_proc = master_builder_._get_default_setting(@type, :compare)
87
+ @canonicalize_proc = master_builder_._get_default_setting(@type, :canonicalize)
88
+ @default_value ||= master_builder_._get_default_setting(@type, :value)
89
+ end
83
90
  @ranges = nil
84
91
  @default_child = nil
85
92
  @children = []
86
- ::Blockenspiel.invoke(block_, Schema::FieldBuilder.new(self)) if block_
93
+ ::Blockenspiel.invoke(block_, Schema::FieldBuilder.new(self, master_builder_)) if block_
87
94
  @default_value = canonicalize_value(@default_value)
88
95
  end
89
96
 
@@ -120,11 +127,11 @@ module Versionomy
120
127
 
121
128
 
122
129
  def inspect # :nodoc:
123
- to_s
130
+ "#<#{self.class}:0x#{object_id.to_s(16)} name=#{@name}>"
124
131
  end
125
132
 
126
133
  def to_s # :nodoc:
127
- "#<#{self.class}:0x#{object_id.to_s(16)} name=#{@name}>"
134
+ inspect
128
135
  end
129
136
 
130
137
 
@@ -371,8 +378,9 @@ module Versionomy
371
378
 
372
379
  include ::Blockenspiel::DSL
373
380
 
374
- def initialize(field_) # :nodoc:
381
+ def initialize(field_, master_builder_) # :nodoc:
375
382
  @field = field_
383
+ @master_builder = master_builder_
376
384
  end
377
385
 
378
386
 
@@ -474,6 +482,7 @@ module Versionomy
474
482
 
475
483
  def field(name_, opts_={}, &block_)
476
484
  only_ = opts_.delete(:only)
485
+ opts_.merge!(:master_builder => @master_builder)
477
486
  @field.add_child(Schema::Field.new(name_, opts_, &block_), only_)
478
487
  end
479
488