gorillib 0.4.1pre → 0.4.2pre
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.
- 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
@@ -0,0 +1,101 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'formatador'
|
4
|
+
require 'active_support/core_ext/hash/slice.rb'
|
5
|
+
load File.expand_path('../../lib/gorillib/hashlike/slice.rb', File.dirname(__FILE__))
|
6
|
+
load File.expand_path('../../lib/gorillib/hash/mash.rb', File.dirname(__FILE__))
|
7
|
+
|
8
|
+
# +-----------+-------+---------+-------------+---------------------------+--------------------+
|
9
|
+
# | method | kind | altered | returns | result | receiver |
|
10
|
+
# +-----------+-------+---------+-------------+---------------------------+--------------------+
|
11
|
+
# | select | block | - | copy | {:a=>"A", :c=>"A"} | (unchanged) |
|
12
|
+
# | only | list | - | copy | {:a=>"A", :c=>"A"} | (unchanged) |
|
13
|
+
# | slice | list | - | copy | {:a=>"A", :c=>"A"} | (unchanged) |
|
14
|
+
# | reject | block | - | copy | {:b=>"not A"} | (unchanged) |
|
15
|
+
# | except | list | - | copy | {:b=>"not A"} | (unchanged) |
|
16
|
+
# | select! | block | yes | self or nil | {:a=>"A", :c=>"A"} or nil | {:a=>"A", :c=>"A"} |
|
17
|
+
# | keep_if | block | yes | self | {:a=>"A", :c=>"A"} | {:a=>"A", :c=>"A"} |
|
18
|
+
# | only! | list | yes | self | {:a=>"A", :c=>"A"} | {:a=>"A", :c=>"A"} |
|
19
|
+
# | slice! | list | yes | copy | {:b=>"not A"} | {:a=>"A", :c=>"A"} |
|
20
|
+
# | reject! | block | yes | self or nil | {:b=>"not A"} or nil | {:b=>"not A"} |
|
21
|
+
# | delete_if | block | yes | self | {:b=>"not A"} | {:b=>"not A"} |
|
22
|
+
# | except! | list | yes | self | {:b=>"not A"} | {:b=>"not A"} |
|
23
|
+
# | extract! | list | yes | copy | {:a=>"A", :c=>"A"} | {:b=>"not A"} |
|
24
|
+
# +-----------+-------+---------+-------------+---------------------------+--------------------+
|
25
|
+
|
26
|
+
SLICING_METHODS = [
|
27
|
+
:select, :only, :slice,
|
28
|
+
:reject, :except,
|
29
|
+
:select!, :keep_if, :only!, :slice!,
|
30
|
+
:reject!, :delete_if, :except!, :extract!, ]
|
31
|
+
|
32
|
+
|
33
|
+
class Hashish < Hash
|
34
|
+
include Gorillib::Hashlike::Slice
|
35
|
+
include Gorillib::Hashlike::ExceptOnly
|
36
|
+
end
|
37
|
+
class Mashish < Mash
|
38
|
+
include Gorillib::Hashlike::ExceptOnly
|
39
|
+
end
|
40
|
+
|
41
|
+
EXAMPLE_HASH = { a: 'A', b: 'not A', c: 'A' }.freeze
|
42
|
+
EXAMPLE_MASH = Mash .new.merge!(EXAMPLE_HASH).freeze
|
43
|
+
EXAMPLE_HASHISH = Hashish.new.merge!(EXAMPLE_HASH).freeze
|
44
|
+
EXAMPLE_MASHISH = Mashish.new.merge!(EXAMPLE_HASH).freeze
|
45
|
+
|
46
|
+
# The given set of keys, 'A' -- either as list or block
|
47
|
+
GIVEN_KEYS = [:c, :a]
|
48
|
+
GIVEN_BLK = ->(key,val){ val == 'A' }
|
49
|
+
|
50
|
+
KLASS_COLORS = {Hashish => 'green', Mash => 'blue', Hash => 'red'}
|
51
|
+
|
52
|
+
def colorize(item, choices)
|
53
|
+
color = choices[item] or return item
|
54
|
+
"[#{color}]#{item}[/]"
|
55
|
+
end
|
56
|
+
|
57
|
+
def slicing_method_report(obj, meth)
|
58
|
+
return :split if meth == :split
|
59
|
+
return({ method: meth, result: '(unimplemented)' }) unless obj.respond_to?(meth)
|
60
|
+
hsh = obj.dup
|
61
|
+
kind = (hsh.method(meth).arity == 0) ? :block : :list
|
62
|
+
result = (kind == :block) ? hsh.send(meth, &GIVEN_BLK) : hsh.send(meth, *GIVEN_KEYS)
|
63
|
+
#
|
64
|
+
altered = (hsh == obj)
|
65
|
+
result_str = result.to_s
|
66
|
+
returns = result.equal?(hsh) ? 'self' : 'copy'
|
67
|
+
if [:select!, :reject!].include?(meth)
|
68
|
+
result_str << " or nil"; returns << " or nil"
|
69
|
+
end
|
70
|
+
ret_class = colorize(result.class, KLASS_COLORS)
|
71
|
+
obj_class = colorize(obj.class, KLASS_COLORS)
|
72
|
+
src_loc, _ = hsh.method(meth).source_location
|
73
|
+
provider = case src_loc when /gorillib\/hashlike\/slice/ then 'gorillib' when /activesupp/ then 'activesupp' when nil then 'internal' else 'other' ; end
|
74
|
+
|
75
|
+
{ method: meth, kind: kind, altered: (altered ? '-' : 'yes'),
|
76
|
+
returns: returns, result: result_str, receiver: (altered ? '(unchanged)' : hsh),
|
77
|
+
provider: provider, obj_class: obj_class, ret_class: ret_class }
|
78
|
+
end
|
79
|
+
|
80
|
+
def display_results_table
|
81
|
+
info = SLICING_METHODS.flat_map do |meth|
|
82
|
+
[EXAMPLE_HASH, EXAMPLE_MASH, EXAMPLE_HASHISH, EXAMPLE_MASHISH].flat_map do |obj|
|
83
|
+
slicing_method_report(obj, meth)
|
84
|
+
end + [:split]
|
85
|
+
end
|
86
|
+
Formatador.display_compact_table(info,
|
87
|
+
[:method, :kind, :altered, :returns, :result, :receiver, :provider, :obj_class, :ret_class] )
|
88
|
+
end
|
89
|
+
|
90
|
+
puts
|
91
|
+
puts "Results for hash #{EXAMPLE_HASH.inspect}, of hash.meth(:a, :c) or"
|
92
|
+
puts " hash.meth{|key, val| val == 'A'} as appropriate."
|
93
|
+
puts " Note: select! and reject! act resp. like keep_if and delete_if"
|
94
|
+
puts " but return nil if the contents are unchanged."
|
95
|
+
puts
|
96
|
+
|
97
|
+
display_results_table
|
98
|
+
|
99
|
+
# display_results_table(EXAMPLE_HASHISH)
|
100
|
+
#
|
101
|
+
# display_results_table(EXAMPLE_MASH)
|
data/gorillib.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "gorillib"
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.2pre"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Infochimps"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-08-18"
|
13
13
|
s.description = "Gorillib: infochimps lightweight subset of ruby convenience methods"
|
14
14
|
s.email = "coders@infochimps.org"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -28,32 +28,32 @@ Gem::Specification.new do |s|
|
|
28
28
|
"Rakefile",
|
29
29
|
"TODO.md",
|
30
30
|
"VERSION",
|
31
|
+
"examples/benchmark/factories_benchmark.rb",
|
31
32
|
"examples/builder/ironfan.rb",
|
33
|
+
"examples/hash/slicing_methods.rb",
|
32
34
|
"examples/model/simple.rb",
|
33
35
|
"gorillib.gemspec",
|
34
|
-
"lib/alt/kernel/call_stack.rb",
|
35
36
|
"lib/gorillib.rb",
|
36
|
-
"lib/gorillib/array/average.rb",
|
37
37
|
"lib/gorillib/array/compact_blank.rb",
|
38
38
|
"lib/gorillib/array/deep_compact.rb",
|
39
39
|
"lib/gorillib/array/extract_options.rb",
|
40
|
-
"lib/gorillib/array/
|
41
|
-
"lib/gorillib/array/sorted_median.rb",
|
42
|
-
"lib/gorillib/array/sorted_percentile.rb",
|
43
|
-
"lib/gorillib/array/sorted_sample.rb",
|
40
|
+
"lib/gorillib/array/simple_statistics.rb",
|
44
41
|
"lib/gorillib/array/wrap.rb",
|
45
42
|
"lib/gorillib/base.rb",
|
46
43
|
"lib/gorillib/builder.rb",
|
47
|
-
"lib/gorillib/builder/field.rb",
|
48
44
|
"lib/gorillib/collection.rb",
|
49
|
-
"lib/gorillib/collection/has_collection.rb",
|
50
|
-
"lib/gorillib/collection/list_collection.rb",
|
51
45
|
"lib/gorillib/collection/model_collection.rb",
|
52
46
|
"lib/gorillib/datetime/parse.rb",
|
53
47
|
"lib/gorillib/datetime/to_flat.rb",
|
48
|
+
"lib/gorillib/deprecated/array/average.rb",
|
49
|
+
"lib/gorillib/deprecated/array/random.rb",
|
50
|
+
"lib/gorillib/deprecated/array/sorted_median.rb",
|
51
|
+
"lib/gorillib/deprecated/array/sorted_percentile.rb",
|
52
|
+
"lib/gorillib/deprecated/array/sorted_sample.rb",
|
53
|
+
"lib/gorillib/deprecated/metaprogramming/aliasing.rb",
|
54
54
|
"lib/gorillib/enumerable/sum.rb",
|
55
|
-
"lib/gorillib/exception/confidence.rb",
|
56
55
|
"lib/gorillib/exception/raisers.rb",
|
56
|
+
"lib/gorillib/factories.rb",
|
57
57
|
"lib/gorillib/hash/compact.rb",
|
58
58
|
"lib/gorillib/hash/deep_compact.rb",
|
59
59
|
"lib/gorillib/hash/deep_dup.rb",
|
@@ -73,9 +73,7 @@ Gem::Specification.new do |s|
|
|
73
73
|
"lib/gorillib/hashlike/keys.rb",
|
74
74
|
"lib/gorillib/hashlike/reverse_merge.rb",
|
75
75
|
"lib/gorillib/hashlike/slice.rb",
|
76
|
-
"lib/gorillib/io/system_helpers.rb",
|
77
76
|
"lib/gorillib/logger/log.rb",
|
78
|
-
"lib/gorillib/metaprogramming/aliasing.rb",
|
79
77
|
"lib/gorillib/metaprogramming/class_attribute.rb",
|
80
78
|
"lib/gorillib/metaprogramming/concern.rb",
|
81
79
|
"lib/gorillib/metaprogramming/delegation.rb",
|
@@ -91,11 +89,14 @@ Gem::Specification.new do |s|
|
|
91
89
|
"lib/gorillib/model/errors.rb",
|
92
90
|
"lib/gorillib/model/factories.rb",
|
93
91
|
"lib/gorillib/model/field.rb",
|
92
|
+
"lib/gorillib/model/fixup.rb",
|
94
93
|
"lib/gorillib/model/lint.rb",
|
95
94
|
"lib/gorillib/model/named_schema.rb",
|
96
95
|
"lib/gorillib/model/overlay.rb",
|
97
|
-
"lib/gorillib/model/
|
96
|
+
"lib/gorillib/model/positional_fields.rb",
|
97
|
+
"lib/gorillib/model/schema_magic.rb",
|
98
98
|
"lib/gorillib/model/serialization.rb",
|
99
|
+
"lib/gorillib/model/serialization/csv.rb",
|
99
100
|
"lib/gorillib/model/validate.rb",
|
100
101
|
"lib/gorillib/numeric/clamp.rb",
|
101
102
|
"lib/gorillib/object/blank.rb",
|
@@ -110,12 +111,13 @@ Gem::Specification.new do |s|
|
|
110
111
|
"lib/gorillib/string/inflector.rb",
|
111
112
|
"lib/gorillib/string/simple_inflector.rb",
|
112
113
|
"lib/gorillib/string/truncate.rb",
|
114
|
+
"lib/gorillib/type/boolean.rb",
|
113
115
|
"lib/gorillib/type/extended.rb",
|
114
116
|
"lib/gorillib/type/url.rb",
|
115
117
|
"lib/gorillib/utils/capture_output.rb",
|
116
118
|
"lib/gorillib/utils/console.rb",
|
119
|
+
"lib/gorillib/utils/edge_cases.rb",
|
117
120
|
"lib/gorillib/utils/nuke_constants.rb",
|
118
|
-
"lib/gorillib/utils/stub_module.rb",
|
119
121
|
"notes/HOWTO.md",
|
120
122
|
"notes/bucket.md",
|
121
123
|
"notes/builder.md",
|
@@ -124,15 +126,12 @@ Gem::Specification.new do |s|
|
|
124
126
|
"notes/model-overlay.md",
|
125
127
|
"notes/model.md",
|
126
128
|
"notes/structured-data-classes.md",
|
127
|
-
"spec/array/average_spec.rb",
|
128
|
-
"spec/array/sorted_median_spec.rb",
|
129
|
-
"spec/array/sorted_percentile_spec.rb",
|
130
|
-
"spec/array/sorted_sample_spec.rb",
|
131
129
|
"spec/examples/builder/ironfan_spec.rb",
|
132
130
|
"spec/extlib/hash_spec.rb",
|
133
131
|
"spec/extlib/mash_spec.rb",
|
134
132
|
"spec/gorillib/array/compact_blank_spec.rb",
|
135
133
|
"spec/gorillib/array/extract_options_spec.rb",
|
134
|
+
"spec/gorillib/array/simple_statistics_spec.rb",
|
136
135
|
"spec/gorillib/builder_spec.rb",
|
137
136
|
"spec/gorillib/collection_spec.rb",
|
138
137
|
"spec/gorillib/datetime/parse_spec.rb",
|
@@ -152,14 +151,13 @@ Gem::Specification.new do |s|
|
|
152
151
|
"spec/gorillib/hashlike/hashlike_via_accessors_spec.rb",
|
153
152
|
"spec/gorillib/hashlike_spec.rb",
|
154
153
|
"spec/gorillib/logger/log_spec.rb",
|
155
|
-
"spec/gorillib/metaprogramming/aliasing_spec.rb",
|
156
154
|
"spec/gorillib/metaprogramming/class_attribute_spec.rb",
|
157
155
|
"spec/gorillib/metaprogramming/delegation_spec.rb",
|
158
156
|
"spec/gorillib/metaprogramming/singleton_class_spec.rb",
|
157
|
+
"spec/gorillib/model/defaults_spec.rb",
|
158
|
+
"spec/gorillib/model/factories_spec.rb",
|
159
159
|
"spec/gorillib/model/lint_spec.rb",
|
160
|
-
"spec/gorillib/model/
|
161
|
-
"spec/gorillib/model/record/factories_spec.rb",
|
162
|
-
"spec/gorillib/model/record/overlay_spec.rb",
|
160
|
+
"spec/gorillib/model/overlay_spec.rb",
|
163
161
|
"spec/gorillib/model/serialization_spec.rb",
|
164
162
|
"spec/gorillib/model_spec.rb",
|
165
163
|
"spec/gorillib/numeric/clamp_spec.rb",
|
@@ -175,24 +173,24 @@ Gem::Specification.new do |s|
|
|
175
173
|
"spec/gorillib/type/extended_spec.rb",
|
176
174
|
"spec/gorillib/utils/capture_output_spec.rb",
|
177
175
|
"spec/spec_helper.rb",
|
176
|
+
"spec/support/factory_test_helpers.rb",
|
178
177
|
"spec/support/gorillib_test_helpers.rb",
|
179
178
|
"spec/support/hashlike_fuzzing_helper.rb",
|
180
179
|
"spec/support/hashlike_helper.rb",
|
181
180
|
"spec/support/hashlike_struct_helper.rb",
|
182
181
|
"spec/support/hashlike_via_delegation.rb",
|
183
|
-
"spec/support/kcode_test_helper.rb",
|
184
182
|
"spec/support/matchers/be_array_eql.rb",
|
185
183
|
"spec/support/matchers/be_hash_eql.rb",
|
186
184
|
"spec/support/matchers/enumerate_method.rb",
|
187
185
|
"spec/support/matchers/evaluate_to_true.rb",
|
188
186
|
"spec/support/model_test_helpers.rb"
|
189
187
|
]
|
190
|
-
s.homepage = "
|
191
|
-
s.licenses = ["
|
188
|
+
s.homepage = "https://github.com/infochimps-labs/gorillib"
|
189
|
+
s.licenses = ["Apache 2.0"]
|
192
190
|
s.require_paths = ["lib"]
|
193
|
-
s.rubygems_version = "1.8.
|
191
|
+
s.rubygems_version = "1.8.24"
|
194
192
|
s.summary = "include only what you need. No dependencies, no creep"
|
195
|
-
s.test_files = ["spec/
|
193
|
+
s.test_files = ["spec/examples/builder/ironfan_spec.rb", "spec/extlib/hash_spec.rb", "spec/extlib/mash_spec.rb", "spec/gorillib/array/compact_blank_spec.rb", "spec/gorillib/array/extract_options_spec.rb", "spec/gorillib/array/simple_statistics_spec.rb", "spec/gorillib/builder_spec.rb", "spec/gorillib/collection_spec.rb", "spec/gorillib/datetime/parse_spec.rb", "spec/gorillib/datetime/to_flat_spec.rb", "spec/gorillib/enumerable/sum_spec.rb", "spec/gorillib/exception/raisers_spec.rb", "spec/gorillib/hash/compact_spec.rb", "spec/gorillib/hash/deep_compact_spec.rb", "spec/gorillib/hash/deep_merge_spec.rb", "spec/gorillib/hash/keys_spec.rb", "spec/gorillib/hash/reverse_merge_spec.rb", "spec/gorillib/hash/slice_spec.rb", "spec/gorillib/hash/zip_spec.rb", "spec/gorillib/hashlike/behave_same_as_hash_spec.rb", "spec/gorillib/hashlike/deep_hash_spec.rb", "spec/gorillib/hashlike/hashlike_behavior_spec.rb", "spec/gorillib/hashlike/hashlike_via_accessors_spec.rb", "spec/gorillib/hashlike_spec.rb", "spec/gorillib/logger/log_spec.rb", "spec/gorillib/metaprogramming/class_attribute_spec.rb", "spec/gorillib/metaprogramming/delegation_spec.rb", "spec/gorillib/metaprogramming/singleton_class_spec.rb", "spec/gorillib/model/defaults_spec.rb", "spec/gorillib/model/factories_spec.rb", "spec/gorillib/model/lint_spec.rb", "spec/gorillib/model/overlay_spec.rb", "spec/gorillib/model/serialization_spec.rb", "spec/gorillib/model_spec.rb", "spec/gorillib/numeric/clamp_spec.rb", "spec/gorillib/object/blank_spec.rb", "spec/gorillib/object/try_dup_spec.rb", "spec/gorillib/object/try_spec.rb", "spec/gorillib/pathname_spec.rb", "spec/gorillib/string/constantize_spec.rb", "spec/gorillib/string/human_spec.rb", "spec/gorillib/string/inflections_spec.rb", "spec/gorillib/string/inflector_test_cases.rb", "spec/gorillib/string/truncate_spec.rb", "spec/gorillib/type/extended_spec.rb", "spec/gorillib/utils/capture_output_spec.rb", "spec/spec_helper.rb", "spec/support/factory_test_helpers.rb", "spec/support/gorillib_test_helpers.rb", "spec/support/hashlike_fuzzing_helper.rb", "spec/support/hashlike_helper.rb", "spec/support/hashlike_struct_helper.rb", "spec/support/hashlike_via_delegation.rb", "spec/support/matchers/be_array_eql.rb", "spec/support/matchers/be_hash_eql.rb", "spec/support/matchers/enumerate_method.rb", "spec/support/matchers/evaluate_to_true.rb", "spec/support/model_test_helpers.rb"]
|
196
194
|
|
197
195
|
if s.respond_to? :specification_version then
|
198
196
|
s.specification_version = 3
|
@@ -201,20 +199,23 @@ Gem::Specification.new do |s|
|
|
201
199
|
s.add_runtime_dependency(%q<multi_json>, [">= 1.1"])
|
202
200
|
s.add_development_dependency(%q<bundler>, ["~> 1.1"])
|
203
201
|
s.add_development_dependency(%q<rake>, [">= 0"])
|
204
|
-
s.add_development_dependency(%q<
|
205
|
-
s.add_development_dependency(%q<
|
202
|
+
s.add_development_dependency(%q<yard>, [">= 0.7"])
|
203
|
+
s.add_development_dependency(%q<rspec>, [">= 2.8"])
|
204
|
+
s.add_development_dependency(%q<jeweler>, [">= 1.6"])
|
206
205
|
else
|
207
206
|
s.add_dependency(%q<multi_json>, [">= 1.1"])
|
208
207
|
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
209
208
|
s.add_dependency(%q<rake>, [">= 0"])
|
210
|
-
s.add_dependency(%q<
|
211
|
-
s.add_dependency(%q<
|
209
|
+
s.add_dependency(%q<yard>, [">= 0.7"])
|
210
|
+
s.add_dependency(%q<rspec>, [">= 2.8"])
|
211
|
+
s.add_dependency(%q<jeweler>, [">= 1.6"])
|
212
212
|
end
|
213
213
|
else
|
214
214
|
s.add_dependency(%q<multi_json>, [">= 1.1"])
|
215
215
|
s.add_dependency(%q<bundler>, ["~> 1.1"])
|
216
216
|
s.add_dependency(%q<rake>, [">= 0"])
|
217
|
-
s.add_dependency(%q<
|
218
|
-
s.add_dependency(%q<
|
217
|
+
s.add_dependency(%q<yard>, [">= 0.7"])
|
218
|
+
s.add_dependency(%q<rspec>, [">= 2.8"])
|
219
|
+
s.add_dependency(%q<jeweler>, [">= 1.6"])
|
219
220
|
end
|
220
221
|
end
|
@@ -1,9 +1,10 @@
|
|
1
|
+
require 'set'
|
1
2
|
require 'gorillib/object/blank'
|
2
3
|
|
3
|
-
#
|
4
|
-
# deep_compact! removes all 'blank?' elements in the array in place, recursively
|
5
|
-
#
|
6
4
|
class Array
|
5
|
+
#
|
6
|
+
# deep_compact! removes all 'blank?' elements in the array in place, recursively
|
7
|
+
#
|
7
8
|
def deep_compact!
|
8
9
|
self.map! do |val|
|
9
10
|
val.deep_compact! if val.respond_to?(:deep_compact!)
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class Array
|
2
|
+
|
3
|
+
#
|
4
|
+
# The average of my elements.
|
5
|
+
# precondition: Each element must be convertible to a float.
|
6
|
+
#
|
7
|
+
# @return [Float] average of all elements
|
8
|
+
def average
|
9
|
+
return nil if empty?
|
10
|
+
inject(:+) / size.to_f
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# @return the element that fraction of the way along the indexes
|
15
|
+
#
|
16
|
+
# @example halfway point:
|
17
|
+
# [1,4,9,16,25].at_fraction(0.5) # 9
|
18
|
+
#
|
19
|
+
# @example note that indexes are rounded down:
|
20
|
+
# [1,4,9,16,25].at_fraction(0.74999) # 9
|
21
|
+
# [1,4,9,16,25].at_fraction(0.75) # 16
|
22
|
+
#
|
23
|
+
# @example blank array:
|
24
|
+
# [].at_fraction(0.1) # nil
|
25
|
+
#
|
26
|
+
def at_fraction(fraction)
|
27
|
+
raise ArgumentError, "fraction should be between 0.0 and 1.0: got #{fraction.inspect}" unless (0.0 .. 1.0).include?(fraction)
|
28
|
+
return nil if empty?
|
29
|
+
self[ ((size - 1) * Float(fraction)).round ]
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# @return the 1/nth, 2/nth, ... n/nth (last) elements in the array.
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# [1,4,9,16,25,36,49].take_nths(3) # [4, 16, 36]
|
37
|
+
# [ 4,9, 16, 36,49].take_nths(3) # [4, 16, 36]
|
38
|
+
# [1,4,9,16,25,36,49].take_nths(5) # [1, 4, 16, 25, 36]
|
39
|
+
#
|
40
|
+
# @example edge cases
|
41
|
+
# [1,4,9,16,25,36,49].take_nths(99) # [1,4,9,16,25,36,49]
|
42
|
+
# [1,4,9,16,25,36,49].take_nths(1) # [16]
|
43
|
+
# [1,4,9,16,25,36,49].take_nths(0) # []
|
44
|
+
# [].take_nths(3) # []
|
45
|
+
#
|
46
|
+
# The array must be sorted for this to be useful.
|
47
|
+
#
|
48
|
+
def take_nths(num)
|
49
|
+
return [] if empty?
|
50
|
+
(0 .. num-1).map{|step| at_fraction( (step + 0.5)/(num)) }.uniq
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Returns the middle element of odd-sized arrays. For even arrays,
|
55
|
+
# it will return one of the two middle elements. Precisely which is
|
56
|
+
# undefined, except that it will consistently return one or the
|
57
|
+
# other.
|
58
|
+
#
|
59
|
+
# The array must be sorted for this to be useful.
|
60
|
+
#
|
61
|
+
def sorted_median
|
62
|
+
at_fraction(0.5)
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Returns the element at the position closest to the given
|
67
|
+
# percentile. For example, sorted_percentile 0.0 will return the
|
68
|
+
# first element and sorted_percentile 100.0 will return the last
|
69
|
+
# element.
|
70
|
+
#
|
71
|
+
# The array must be sorted for this to be useful.
|
72
|
+
#
|
73
|
+
def sorted_percentile(percentile)
|
74
|
+
at_fraction(percentile / 100.0)
|
75
|
+
end
|
76
|
+
end
|
data/lib/gorillib/base.rb
CHANGED
data/lib/gorillib/builder.rb
CHANGED
@@ -7,12 +7,12 @@ module Gorillib
|
|
7
7
|
extend Gorillib::Concern
|
8
8
|
include Gorillib::Model
|
9
9
|
|
10
|
+
# @return [Object, nil] the return value of the block, or nil if no block given
|
10
11
|
def receive!(*args, &block)
|
11
12
|
super(*args)
|
12
13
|
if block_given?
|
13
14
|
(block.arity == 1) ? block.call(self) : self.instance_eval(&block)
|
14
15
|
end
|
15
|
-
self
|
16
16
|
end
|
17
17
|
|
18
18
|
def getset(field, *args, &block)
|
@@ -35,8 +35,8 @@ module Gorillib
|
|
35
35
|
val = read_attribute(field.name)
|
36
36
|
if val.present?
|
37
37
|
# existing item: update it with args and block
|
38
|
-
val.receive!(*args, &block) if args.present?
|
39
|
-
elsif attrs.blank?
|
38
|
+
val.receive!(*args, &block) if args.present? or block_given?
|
39
|
+
elsif attrs.blank? and not block_given?
|
40
40
|
# missing item (read): return nil
|
41
41
|
return nil
|
42
42
|
else
|
@@ -72,7 +72,9 @@ module Gorillib
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def set_collection_item(plural_name, item_key, item)
|
75
|
-
collection_of(plural_name)
|
75
|
+
collection = collection_of(plural_name)
|
76
|
+
collection[item_key] = item
|
77
|
+
collection[item_key]
|
76
78
|
end
|
77
79
|
|
78
80
|
def has_collection_item?(plural_name, item_key)
|
@@ -84,13 +86,11 @@ module Gorillib
|
|
84
86
|
end
|
85
87
|
|
86
88
|
def to_key
|
87
|
-
self.
|
89
|
+
self.send(key_method)
|
88
90
|
end
|
89
91
|
|
90
|
-
def
|
91
|
-
attrs.delete(:owner)
|
92
|
-
# detailed ? str : ([str[0..-2], " #{to_key}>"].join)
|
93
|
-
str = super(detailed, attrs)
|
92
|
+
def to_inspectable
|
93
|
+
super.tap{|attrs| attrs.delete(:owner) }
|
94
94
|
end
|
95
95
|
|
96
96
|
def collection_of(plural_name)
|
@@ -106,10 +106,11 @@ module Gorillib
|
|
106
106
|
def member(field_name, type, options={})
|
107
107
|
field(field_name, type, {:field_type => ::Gorillib::Builder::MemberField}.merge(options))
|
108
108
|
end
|
109
|
+
|
110
|
+
# FIXME: this interface is borked -- it should not take the item_type in the second slot.
|
109
111
|
def collection(field_name, item_type, options={})
|
110
|
-
|
111
|
-
:item_type => item_type,
|
112
|
-
:field_type => ::Gorillib::Builder::CollectionField}.merge(options))
|
112
|
+
super(field_name, Gorillib::ModelCollection, {
|
113
|
+
:item_type => item_type, :field_type => ::Gorillib::Builder::GetsetCollectionField }.merge(options))
|
113
114
|
end
|
114
115
|
|
115
116
|
protected
|
@@ -141,20 +142,6 @@ module Gorillib
|
|
141
142
|
end
|
142
143
|
end
|
143
144
|
|
144
|
-
def define_collection_receiver(field)
|
145
|
-
plural_name = field.name; item_type = field.item_type; field_type = field.type
|
146
|
-
define_meta_module_method("receive_#{plural_name}", true) do |coll, &block|
|
147
|
-
begin
|
148
|
-
if coll.is_a?(field_type)
|
149
|
-
write_attribute(plural_name, coll)
|
150
|
-
else
|
151
|
-
read_attribute(plural_name).receive!(coll, &block)
|
152
|
-
end
|
153
|
-
self
|
154
|
-
rescue StandardError => err ; err.polish("#{self.class} #{plural_name} c[#{item_type}] on #{args}'") rescue nil ; raise ; end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
145
|
def define_collection_tester(field)
|
159
146
|
plural_name = field.plural_name
|
160
147
|
define_meta_module_method("has_#{field.singular_name}?", field.visibility(:collection_tester)) do |item_key|
|
@@ -223,9 +210,8 @@ module Gorillib
|
|
223
210
|
end
|
224
211
|
end
|
225
212
|
|
226
|
-
class
|
213
|
+
class GetsetCollectionField < ::Gorillib::Model::SimpleCollectionField
|
227
214
|
field :singular_name, Symbol, :default => ->{ Gorillib::Inflector.singularize(name.to_s).to_sym }
|
228
|
-
field :item_type, Class, :default => Whatever
|
229
215
|
|
230
216
|
self.visibilities = visibilities.merge(:writer => false, :tester => false,
|
231
217
|
:collection_getset => :public, :collection_tester => true)
|
@@ -236,8 +222,6 @@ module Gorillib
|
|
236
222
|
end
|
237
223
|
|
238
224
|
def inscribe_methods(model)
|
239
|
-
item_type = self.item_type
|
240
|
-
self.default = ->{ Gorillib::ModelCollection.new(nil, item_type) }
|
241
225
|
raise "Plural and singular names must differ: #{self.plural_name}" if (singular_name == plural_name)
|
242
226
|
#
|
243
227
|
@visibilities[:writer] = false
|
@@ -249,6 +233,7 @@ module Gorillib
|
|
249
233
|
model.__send__(:define_collection_tester, self)
|
250
234
|
end
|
251
235
|
end
|
236
|
+
CollectionField = GetsetCollectionField
|
252
237
|
|
253
238
|
end
|
254
239
|
end
|