gorillib 0.4.1pre → 0.4.2pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +13 -10
- data/.rspec +1 -1
- data/.yardopts +1 -0
- data/CHANGELOG.md +47 -0
- data/Gemfile +22 -19
- data/Guardfile +23 -9
- data/README.md +12 -12
- data/Rakefile +29 -40
- data/VERSION +1 -1
- data/examples/benchmark/factories_benchmark.rb +87 -0
- data/examples/builder/ironfan.rb +1 -19
- data/examples/hash/slicing_methods.rb +101 -0
- data/gorillib.gemspec +36 -35
- data/lib/gorillib/array/deep_compact.rb +4 -3
- data/lib/gorillib/array/simple_statistics.rb +76 -0
- data/lib/gorillib/base.rb +0 -1
- data/lib/gorillib/builder.rb +15 -30
- data/lib/gorillib/collection.rb +159 -57
- data/lib/gorillib/collection/model_collection.rb +136 -43
- data/lib/gorillib/datetime/parse.rb +4 -2
- data/lib/gorillib/{array → deprecated/array}/average.rb +0 -0
- data/lib/gorillib/{array → deprecated/array}/random.rb +2 -1
- data/lib/gorillib/{array → deprecated/array}/sorted_median.rb +0 -0
- data/lib/gorillib/{array → deprecated/array}/sorted_percentile.rb +0 -0
- data/lib/gorillib/deprecated/array/sorted_sample.rb +13 -0
- data/lib/gorillib/{metaprogramming → deprecated/metaprogramming}/aliasing.rb +0 -0
- data/lib/gorillib/enumerable/sum.rb +3 -3
- data/lib/gorillib/exception/raisers.rb +92 -22
- data/lib/gorillib/factories.rb +550 -0
- data/lib/gorillib/hash/mash.rb +15 -58
- data/lib/gorillib/hashlike/deep_compact.rb +2 -2
- data/lib/gorillib/hashlike/slice.rb +55 -40
- data/lib/gorillib/model.rb +5 -3
- data/lib/gorillib/model/base.rb +33 -119
- data/lib/gorillib/model/defaults.rb +58 -14
- data/lib/gorillib/model/errors.rb +10 -0
- data/lib/gorillib/model/factories.rb +1 -367
- data/lib/gorillib/model/field.rb +40 -18
- data/lib/gorillib/model/fixup.rb +16 -0
- data/lib/gorillib/model/positional_fields.rb +35 -0
- data/lib/gorillib/model/schema_magic.rb +162 -0
- data/lib/gorillib/model/serialization.rb +1 -2
- data/lib/gorillib/model/serialization/csv.rb +59 -0
- data/lib/gorillib/pathname.rb +19 -8
- data/lib/gorillib/some.rb +2 -0
- data/lib/gorillib/string/constantize.rb +17 -10
- data/lib/gorillib/string/inflector.rb +11 -7
- data/lib/gorillib/type/boolean.rb +40 -0
- data/lib/gorillib/type/extended.rb +76 -40
- data/lib/gorillib/type/url.rb +6 -4
- data/lib/gorillib/utils/console.rb +1 -18
- data/lib/gorillib/utils/edge_cases.rb +18 -0
- data/spec/examples/builder/ironfan_spec.rb +5 -10
- data/spec/gorillib/array/compact_blank_spec.rb +36 -21
- data/spec/gorillib/array/simple_statistics_spec.rb +143 -0
- data/spec/gorillib/builder_spec.rb +16 -20
- data/spec/gorillib/collection_spec.rb +131 -35
- data/spec/gorillib/exception/raisers_spec.rb +39 -0
- data/spec/gorillib/hash/deep_compact_spec.rb +3 -3
- data/spec/gorillib/model/{record/defaults_spec.rb → defaults_spec.rb} +5 -1
- data/spec/gorillib/model/factories_spec.rb +335 -0
- data/spec/gorillib/model/{record/overlay_spec.rb → overlay_spec.rb} +0 -0
- data/spec/gorillib/model/serialization_spec.rb +2 -2
- data/spec/gorillib/model_spec.rb +19 -18
- data/spec/gorillib/pathname_spec.rb +7 -7
- data/spec/gorillib/string/truncate_spec.rb +3 -13
- data/spec/gorillib/type/extended_spec.rb +50 -2
- data/spec/gorillib/utils/capture_output_spec.rb +1 -1
- data/spec/spec_helper.rb +10 -7
- data/spec/support/factory_test_helpers.rb +76 -0
- data/spec/support/gorillib_test_helpers.rb +36 -24
- data/spec/support/model_test_helpers.rb +39 -2
- metadata +86 -51
- data/lib/alt/kernel/call_stack.rb +0 -56
- data/lib/gorillib/array/sorted_sample.rb +0 -12
- data/lib/gorillib/builder/field.rb +0 -5
- data/lib/gorillib/collection/has_collection.rb +0 -31
- data/lib/gorillib/collection/list_collection.rb +0 -58
- data/lib/gorillib/exception/confidence.rb +0 -17
- data/lib/gorillib/io/system_helpers.rb +0 -30
- data/lib/gorillib/model/record_schema.rb +0 -9
- data/lib/gorillib/utils/stub_module.rb +0 -33
- data/spec/array/average_spec.rb +0 -24
- data/spec/array/sorted_median_spec.rb +0 -18
- data/spec/array/sorted_percentile_spec.rb +0 -24
- data/spec/array/sorted_sample_spec.rb +0 -28
- data/spec/gorillib/metaprogramming/aliasing_spec.rb +0 -180
- data/spec/gorillib/model/record/factories_spec.rb +0 -335
- data/spec/support/kcode_test_helper.rb +0 -16
@@ -9,19 +9,7 @@ module Gorillib
|
|
9
9
|
attribute_set?(:default)
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
13
|
-
# This is called by `read_attribute` if an attribute is unset; you should
|
14
|
-
# not call this directly. You might use this to provide defaults, or lazy
|
15
|
-
# access, or layered resolution.
|
16
|
-
#
|
17
|
-
# @param [String, Symbol, #to_s] field_name Name of the attribute to unset.
|
18
|
-
# @return [nil] Ze goggles! Zey do nussing!
|
19
|
-
def read_unset_attribute(field_name)
|
20
|
-
field = self.class.fields[field_name]
|
21
|
-
return unless field.has_default?
|
22
|
-
write_attribute(field.name, attribute_default(field))
|
23
|
-
end
|
24
|
-
|
12
|
+
|
25
13
|
# FieldDefaults allows defaults to be declared for your fields
|
26
14
|
#
|
27
15
|
# Defaults are declared by passing the :default option to the field
|
@@ -50,6 +38,60 @@ module Gorillib
|
|
50
38
|
# event.end_date.to_s #=> "2012-01-01"
|
51
39
|
#
|
52
40
|
|
41
|
+
# This is called by `read_attribute` if an attribute is unset; you should
|
42
|
+
# not call this directly. You might use this to provide defaults, or lazy
|
43
|
+
# access, or layered resolution.
|
44
|
+
#
|
45
|
+
# Once a non-nil default value has been read, it is **fixed on the field**; this method
|
46
|
+
# will not be called again, and `attribute_set?(...)` will return `true`.
|
47
|
+
#
|
48
|
+
# @example values are fixed on read
|
49
|
+
# class Defaultable
|
50
|
+
# include Gorillib::Model
|
51
|
+
# field :timestamp, Integer, default: ->{ Time.now }
|
52
|
+
# end
|
53
|
+
# dd = Defaultable.new
|
54
|
+
# dd.attribute_set?(:timestamp) # => false
|
55
|
+
# dd.timestamp # => '2012-01-02 12:34:56 CST'
|
56
|
+
# dd.attribute_set?(:timestamp) # => true
|
57
|
+
# # The block is *not* re-run -- the time is the same
|
58
|
+
# dd.timestamp # => '2012-01-02 12:34:56 CST'
|
59
|
+
#
|
60
|
+
# @example If the default is a literal nil it is set as normal:
|
61
|
+
#
|
62
|
+
# Defaultable.field :might_be_nil, String, default: nil
|
63
|
+
# dd.attribute_set?(:might_be_nil) # => false
|
64
|
+
# dd.might_be_nil # => nil
|
65
|
+
# dd.attribute_set?(:might_be_nil) # => true
|
66
|
+
#
|
67
|
+
# If the default is generated from a block (or anything but a literal nil), no default is set:
|
68
|
+
#
|
69
|
+
# Defaultable.field :might_be_nil, String, default: ->{ puts 'ran!'; some_other_value ? some_other_value.reverse : nil }
|
70
|
+
# Defaultable.field :some_other_value, String
|
71
|
+
# dd = Defaultable.new
|
72
|
+
# dd.attribute_set?(:might_be_nil) # => false
|
73
|
+
# dd.might_be_nil # => nil
|
74
|
+
# 'ran!' # block was run
|
75
|
+
# dd.might_be_nil # => nil
|
76
|
+
# 'ran!' # block was run again
|
77
|
+
# dd.some_other_val = 'hello'
|
78
|
+
# dd.might_be_nil # => 'olleh'
|
79
|
+
# 'ran!' # block was run again, and set a value this time
|
80
|
+
# dd.some_other_val = 'goodbye'
|
81
|
+
# dd.might_be_nil # => 'olleh'
|
82
|
+
# # block was not run again
|
83
|
+
#
|
84
|
+
# @param [String, Symbol, #to_s] field_name Name of the attribute to unset.
|
85
|
+
# @return [Object] The new value
|
86
|
+
def read_unset_attribute(field_name)
|
87
|
+
field = self.class.fields[field_name] or return nil
|
88
|
+
return unless field.has_default?
|
89
|
+
val = attribute_default(field)
|
90
|
+
return nil if val.nil? && (not field.default.nil?) # don't write nil unless intent is clearly to have default nil
|
91
|
+
write_attribute(field.name, val)
|
92
|
+
end
|
93
|
+
|
94
|
+
|
53
95
|
protected
|
54
96
|
|
55
97
|
# the actual default value to assign to the attribute
|
@@ -57,8 +99,10 @@ module Gorillib
|
|
57
99
|
return unless field.has_default?
|
58
100
|
val = field.default
|
59
101
|
case
|
60
|
-
when
|
102
|
+
when val.is_a?(Proc) && (val.arity == 0)
|
61
103
|
self.instance_exec(&val)
|
104
|
+
when val.is_a?(UnboundMethod) && (val.arity == 0)
|
105
|
+
val.bind(self).call
|
62
106
|
when val.respond_to?(:call)
|
63
107
|
val.call(self, field.name)
|
64
108
|
else
|
@@ -10,5 +10,15 @@ module Gorillib
|
|
10
10
|
include Gorillib::Model::Error
|
11
11
|
end
|
12
12
|
|
13
|
+
class ConflictingPositionError < ::ArgumentError
|
14
|
+
include Gorillib::Model::Error
|
15
|
+
end
|
16
|
+
|
17
|
+
# Exception raised if deserialized attributes don't have the right shape:
|
18
|
+
# for example, a CSV line with too many/too few fields
|
19
|
+
class RawDataMismatchError < ::StandardError
|
20
|
+
include Gorillib::Model::Error
|
21
|
+
end
|
22
|
+
|
13
23
|
end
|
14
24
|
end
|
@@ -1,367 +1 @@
|
|
1
|
-
|
2
|
-
require 'gorillib/type/extended'
|
3
|
-
|
4
|
-
def Gorillib::Factory(*args)
|
5
|
-
::Gorillib::Factory.receive(*args)
|
6
|
-
end
|
7
|
-
|
8
|
-
module Gorillib
|
9
|
-
|
10
|
-
module Factory
|
11
|
-
class FactoryMismatchError < ArgumentError ; end
|
12
|
-
|
13
|
-
def self.receive(type)
|
14
|
-
case
|
15
|
-
when factories.include?(type) then return factories[type]
|
16
|
-
when type.respond_to?(:receive) then return type
|
17
|
-
when type.is_a?(Proc) || type.is_a?(Method) then return Gorillib::Factory::ApplyProcFactory.new(type)
|
18
|
-
when type.is_a?(String) then
|
19
|
-
return( factories[type] = Gorillib::Inflector.constantize(Gorillib::Inflector.camelize(type.gsub(/\./, '/'))) )
|
20
|
-
else raise ArgumentError, "Don't know which factory makes a #{type}"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Manufactures objects from their raw attributes hash
|
25
|
-
#
|
26
|
-
# A hash with a value for `:_type` is dispatched to the corresponding factory
|
27
|
-
# Everything else is returned directly
|
28
|
-
def self.make(obj)
|
29
|
-
if obj.respond_to?(:has_key?) && (obj.has_key?(:_type) || obj.has_key?('_type'))
|
30
|
-
factory = Gorillib::Factory(attrs[:_type])
|
31
|
-
factory.receive(obj)
|
32
|
-
else
|
33
|
-
obj
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
def self.factories
|
39
|
-
@factories ||= Hash.new
|
40
|
-
end
|
41
|
-
public
|
42
|
-
|
43
|
-
def self.register_factory(factory, typenames)
|
44
|
-
typenames.each{|typename| factories[typename] = factory }
|
45
|
-
end
|
46
|
-
|
47
|
-
class BaseFactory
|
48
|
-
# [Class] The type of objects produced by this factory
|
49
|
-
class_attribute :product
|
50
|
-
|
51
|
-
def initialize(options={})
|
52
|
-
@product = options.delete(:product){ self.class.product }
|
53
|
-
if options[:blankish]
|
54
|
-
define_singleton_method(:blankish, options.delete(:blankish))
|
55
|
-
end
|
56
|
-
redefine(:convert, options.delete(:convert)) if options.has_key?(:convert)
|
57
|
-
warn "Unknown options #{options.keys}" unless options.empty?
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.typename
|
61
|
-
@typename ||= Gorillib::Inflector.underscore(product.name).to_sym
|
62
|
-
end
|
63
|
-
def typename ; self.class.typename ; end
|
64
|
-
|
65
|
-
# A `native` object does not need any transformation; it is accepted directly.
|
66
|
-
# By default, an object is native if it `is_a?(product)`
|
67
|
-
#
|
68
|
-
# @param [Object] obj the object to convert and receive
|
69
|
-
# @return [true, false] true if the item does not need conversion
|
70
|
-
def native?(obj)
|
71
|
-
obj.is_a?(@product)
|
72
|
-
end
|
73
|
-
def self.native?(obj) self.new.native?(obj) ; end
|
74
|
-
|
75
|
-
# A `blankish` object should be converted to `nil`, not a value
|
76
|
-
#
|
77
|
-
# @param [Object] obj the object to convert and receive
|
78
|
-
# @return [true, false] true if the item is equivalent to a nil value
|
79
|
-
def blankish?(obj)
|
80
|
-
obj.nil? || (obj == "")
|
81
|
-
end
|
82
|
-
def self.blankish?(obj)
|
83
|
-
obj.nil? || (obj == "")
|
84
|
-
end
|
85
|
-
|
86
|
-
protected
|
87
|
-
|
88
|
-
def redefine(meth, *args, &block)
|
89
|
-
if args.present?
|
90
|
-
val = args.first
|
91
|
-
case
|
92
|
-
when block_given? then raise ArgumentError, "Pass a block or a value, not both"
|
93
|
-
when val.is_a?(Proc) || val.is_a?(Method) then block = val
|
94
|
-
else block = ->(*){ val.try_dup }
|
95
|
-
end
|
96
|
-
end
|
97
|
-
define_singleton_method(meth, &block)
|
98
|
-
self
|
99
|
-
end
|
100
|
-
|
101
|
-
# Raises a FactoryMismatchError.
|
102
|
-
def mismatched!(obj, message=nil, *args)
|
103
|
-
message ||= "item cannot be converted to #{product}"
|
104
|
-
message << (" got #{obj.inspect}" rescue ' (and is uninspectable)')
|
105
|
-
raise FactoryMismatchError, message, *args
|
106
|
-
end
|
107
|
-
|
108
|
-
def self.register_factory!(*typenames)
|
109
|
-
typenames = [typename, product] if typenames.empty?
|
110
|
-
Gorillib::Factory.register_factory(self.new, typenames)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
class ConvertingFactory < BaseFactory
|
115
|
-
def receive(obj)
|
116
|
-
return nil if blankish?(obj)
|
117
|
-
return obj if native?(obj)
|
118
|
-
convert(obj)
|
119
|
-
rescue NoMethodError, TypeError, RangeError => err
|
120
|
-
mismatched!(obj, err.message, err.backtrace)
|
121
|
-
end
|
122
|
-
protected
|
123
|
-
# Convert a receivable object to the factory's product type. This method
|
124
|
-
# should convert an object to `native?` form or die trying; any
|
125
|
-
# polymorphism (such as converting an empty string to nil) happens in
|
126
|
-
# other methods called by `receive`.
|
127
|
-
#
|
128
|
-
# @param [Object] obj the object to convert.
|
129
|
-
def convert(obj)
|
130
|
-
obj.dup
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
#
|
135
|
-
# A NonConvertingFactory accepts objects that are *already* native, and
|
136
|
-
# throws a mismatch error for anything else.
|
137
|
-
#
|
138
|
-
# @example
|
139
|
-
# ff = Gorillib::Factory::NonConvertingFactory.new(:product => String, :blankish => ->(obj){ obj.nil? })
|
140
|
-
# ff.receive(nil) #=> nil
|
141
|
-
# ff.receive("bob") #=> "bob"
|
142
|
-
# ff.receive(:bob) #=> Gorillib::Factory::FactoryMismatchError: must be an instance of String, got 3
|
143
|
-
#
|
144
|
-
class NonConvertingFactory < BaseFactory
|
145
|
-
def blankish?(obj) obj.nil? ; end
|
146
|
-
def receive(obj)
|
147
|
-
return nil if blankish?(obj)
|
148
|
-
return obj if native?(obj)
|
149
|
-
mismatched!(obj, "must be an instance of #{product},")
|
150
|
-
rescue NoMethodError => err
|
151
|
-
mismatched!(obj, err.message, err.backtrace)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
class ::Whatever < BaseFactory
|
156
|
-
def initialize(options={})
|
157
|
-
options.slice!(:convert, :blankish)
|
158
|
-
super(options)
|
159
|
-
end
|
160
|
-
def native?(obj) true ; end
|
161
|
-
def blankish?(obj) false ; end
|
162
|
-
def receive(obj) obj ; end
|
163
|
-
def self.receive(obj)
|
164
|
-
obj
|
165
|
-
end
|
166
|
-
Gorillib::Factory.register_factory(self, [self, :identical, :whatever])
|
167
|
-
end
|
168
|
-
IdenticalFactory = ::Whatever unless defined?(IdenticalFactory)
|
169
|
-
|
170
|
-
# __________________________________________________________________________
|
171
|
-
#
|
172
|
-
# Concrete Factories
|
173
|
-
# __________________________________________________________________________
|
174
|
-
|
175
|
-
class StringFactory < ConvertingFactory
|
176
|
-
self.product = String
|
177
|
-
def blankish?(obj) obj.nil? ; end
|
178
|
-
def native?(obj) obj.respond_to?(:to_str) end
|
179
|
-
def convert(obj) obj.to_s end
|
180
|
-
register_factory!
|
181
|
-
end
|
182
|
-
|
183
|
-
class GuidFactory < StringFactory ; self.product = ::Guid ; register_factory! ; end
|
184
|
-
class HostnameFactory < StringFactory ; self.product = ::Hostname ; register_factory! ; end
|
185
|
-
class IpAddressFactory < StringFactory ; self.product = ::IpAddress ; register_factory! ; end
|
186
|
-
|
187
|
-
class BinaryFactory < StringFactory
|
188
|
-
def convert(obj)
|
189
|
-
super.force_encoding("BINARY")
|
190
|
-
end
|
191
|
-
register_factory!(:binary)
|
192
|
-
end
|
193
|
-
|
194
|
-
class PathnameFactory < ConvertingFactory
|
195
|
-
self.product = ::Pathname
|
196
|
-
def convert(obj) Pathname.new(obj) end
|
197
|
-
register_factory!
|
198
|
-
end
|
199
|
-
|
200
|
-
class SymbolFactory < ConvertingFactory
|
201
|
-
self.product = Symbol
|
202
|
-
def convert(obj) obj.to_sym end
|
203
|
-
register_factory!
|
204
|
-
end
|
205
|
-
|
206
|
-
class RegexpFactory < ConvertingFactory
|
207
|
-
self.product = Regexp
|
208
|
-
def convert(obj) Regexp.new(obj) end
|
209
|
-
register_factory!
|
210
|
-
end
|
211
|
-
|
212
|
-
class IntegerFactory < ConvertingFactory
|
213
|
-
self.product = Integer
|
214
|
-
def convert(obj) obj.to_i end
|
215
|
-
register_factory!(:int, :integer, Integer)
|
216
|
-
end
|
217
|
-
class BignumFactory < IntegerFactory
|
218
|
-
self.product = Bignum
|
219
|
-
register_factory!
|
220
|
-
end
|
221
|
-
class FloatFactory < ConvertingFactory
|
222
|
-
self.product = Float
|
223
|
-
def convert(obj) obj.to_f end
|
224
|
-
register_factory!
|
225
|
-
end
|
226
|
-
class ComplexFactory < ConvertingFactory
|
227
|
-
self.product = Complex
|
228
|
-
def convert(obj) obj.to_c end
|
229
|
-
register_factory!
|
230
|
-
end
|
231
|
-
class RationalFactory < ConvertingFactory
|
232
|
-
self.product = Rational
|
233
|
-
def convert(obj) obj.to_r end
|
234
|
-
register_factory!
|
235
|
-
end
|
236
|
-
|
237
|
-
class TimeFactory < ConvertingFactory
|
238
|
-
self.product = Time
|
239
|
-
def convert(obj)
|
240
|
-
case obj
|
241
|
-
when String
|
242
|
-
Time.parse(obj).utc
|
243
|
-
when Numeric
|
244
|
-
Time.at(obj).utc
|
245
|
-
end
|
246
|
-
rescue ArgumentError => err
|
247
|
-
warn "Cannot parse time #{obj}: #{err}"
|
248
|
-
return nil
|
249
|
-
end
|
250
|
-
register_factory!
|
251
|
-
end
|
252
|
-
|
253
|
-
# __________________________________________________________________________
|
254
|
-
|
255
|
-
class ClassFactory < NonConvertingFactory ; self.product = Class ; register_factory! ; end
|
256
|
-
class ModuleFactory < NonConvertingFactory ; self.product = Module ; register_factory! ; end
|
257
|
-
class TrueFactory < NonConvertingFactory ; self.product = TrueClass ; register_factory!(:true, TrueClass) ; end
|
258
|
-
class FalseFactory < NonConvertingFactory ; self.product = FalseClass ; register_factory!(:false, FalseClass) ; end
|
259
|
-
|
260
|
-
class ExceptionFactory < NonConvertingFactory ; self.product = Exception ; register_factory!(:exception, Exception) ; end
|
261
|
-
|
262
|
-
class NilFactory < NonConvertingFactory
|
263
|
-
self.product = NilClass
|
264
|
-
def blankish?(obj) false ; end
|
265
|
-
register_factory!(:nil, NilClass)
|
266
|
-
end
|
267
|
-
|
268
|
-
class BooleanFactory < ConvertingFactory
|
269
|
-
self.product = [TrueClass, FalseClass]
|
270
|
-
def blankish?(obj) obj.nil? ; end
|
271
|
-
def native?(obj) obj.equal?(true) || obj.equal?(false) ; end
|
272
|
-
def convert(obj) (obj.to_s == "false") ? false : true ; end
|
273
|
-
register_factory!(:boolean)
|
274
|
-
def self.typename() :boolean ; end
|
275
|
-
end
|
276
|
-
|
277
|
-
#
|
278
|
-
#
|
279
|
-
#
|
280
|
-
|
281
|
-
class EnumerableFactory < ConvertingFactory
|
282
|
-
# [#receive] factory for converting items
|
283
|
-
attr_reader :items_factory
|
284
|
-
|
285
|
-
def initialize(options={})
|
286
|
-
@items_factory = Gorillib::Factory.receive( options.delete(:items){ Gorillib::Factory(:identical) } )
|
287
|
-
redefine(:empty_product, options.delete(:empty_product)) if options.has_key?(:empty_product)
|
288
|
-
super(options)
|
289
|
-
end
|
290
|
-
|
291
|
-
def blankish?(obj) obj.nil? ; end
|
292
|
-
def native?(obj) false ; end
|
293
|
-
|
294
|
-
def empty_product
|
295
|
-
@product.new
|
296
|
-
end
|
297
|
-
|
298
|
-
def convert(obj)
|
299
|
-
clxn = empty_product
|
300
|
-
obj.each do |val|
|
301
|
-
clxn << items_factory.receive(val)
|
302
|
-
end
|
303
|
-
clxn
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
class ArrayFactory < EnumerableFactory
|
308
|
-
self.product = Array
|
309
|
-
register_factory!
|
310
|
-
end
|
311
|
-
|
312
|
-
class SetFactory < EnumerableFactory
|
313
|
-
self.product = Set
|
314
|
-
register_factory!
|
315
|
-
end
|
316
|
-
|
317
|
-
class HashFactory < EnumerableFactory
|
318
|
-
# [#receive] factory for converting keys
|
319
|
-
attr_reader :keys_factory
|
320
|
-
self.product = Hash
|
321
|
-
|
322
|
-
def initialize(options={})
|
323
|
-
@keys_factory = Gorillib::Factory( options.delete(:keys){ Gorillib::Factory(:identical) } )
|
324
|
-
super(options)
|
325
|
-
end
|
326
|
-
|
327
|
-
def convert(obj)
|
328
|
-
hsh = empty_product
|
329
|
-
obj.each_pair do |key, val|
|
330
|
-
hsh[keys_factory.receive(key)] = items_factory.receive(val)
|
331
|
-
end
|
332
|
-
hsh
|
333
|
-
end
|
334
|
-
register_factory!
|
335
|
-
end
|
336
|
-
|
337
|
-
class RangeFactory < NonConvertingFactory
|
338
|
-
self.product = Range
|
339
|
-
def blankish?(obj) obj.nil? || obj == [] ; end
|
340
|
-
register_factory!
|
341
|
-
end
|
342
|
-
|
343
|
-
# __________________________________________________________________________
|
344
|
-
|
345
|
-
class ApplyProcFactory < ConvertingFactory
|
346
|
-
attr_reader :callable
|
347
|
-
|
348
|
-
def initialize(callable=nil, options={}, &block)
|
349
|
-
if block_given?
|
350
|
-
raise ArgumentError, "Pass a block or a value, not both" unless callable.nil?
|
351
|
-
callable = block
|
352
|
-
end
|
353
|
-
@callable = callable
|
354
|
-
super(options)
|
355
|
-
end
|
356
|
-
def blankish?(obj) obj.nil? ; end
|
357
|
-
def native?(val) false ; end
|
358
|
-
def convert(obj)
|
359
|
-
callable.call(obj)
|
360
|
-
end
|
361
|
-
register_factory!(:proc)
|
362
|
-
end
|
363
|
-
|
364
|
-
|
365
|
-
end
|
366
|
-
|
367
|
-
end
|
1
|
+
require_relative '../factories'
|