gorillib 0.4.1pre → 0.4.2pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/.gitignore +13 -10
  2. data/.rspec +1 -1
  3. data/.yardopts +1 -0
  4. data/CHANGELOG.md +47 -0
  5. data/Gemfile +22 -19
  6. data/Guardfile +23 -9
  7. data/README.md +12 -12
  8. data/Rakefile +29 -40
  9. data/VERSION +1 -1
  10. data/examples/benchmark/factories_benchmark.rb +87 -0
  11. data/examples/builder/ironfan.rb +1 -19
  12. data/examples/hash/slicing_methods.rb +101 -0
  13. data/gorillib.gemspec +36 -35
  14. data/lib/gorillib/array/deep_compact.rb +4 -3
  15. data/lib/gorillib/array/simple_statistics.rb +76 -0
  16. data/lib/gorillib/base.rb +0 -1
  17. data/lib/gorillib/builder.rb +15 -30
  18. data/lib/gorillib/collection.rb +159 -57
  19. data/lib/gorillib/collection/model_collection.rb +136 -43
  20. data/lib/gorillib/datetime/parse.rb +4 -2
  21. data/lib/gorillib/{array → deprecated/array}/average.rb +0 -0
  22. data/lib/gorillib/{array → deprecated/array}/random.rb +2 -1
  23. data/lib/gorillib/{array → deprecated/array}/sorted_median.rb +0 -0
  24. data/lib/gorillib/{array → deprecated/array}/sorted_percentile.rb +0 -0
  25. data/lib/gorillib/deprecated/array/sorted_sample.rb +13 -0
  26. data/lib/gorillib/{metaprogramming → deprecated/metaprogramming}/aliasing.rb +0 -0
  27. data/lib/gorillib/enumerable/sum.rb +3 -3
  28. data/lib/gorillib/exception/raisers.rb +92 -22
  29. data/lib/gorillib/factories.rb +550 -0
  30. data/lib/gorillib/hash/mash.rb +15 -58
  31. data/lib/gorillib/hashlike/deep_compact.rb +2 -2
  32. data/lib/gorillib/hashlike/slice.rb +55 -40
  33. data/lib/gorillib/model.rb +5 -3
  34. data/lib/gorillib/model/base.rb +33 -119
  35. data/lib/gorillib/model/defaults.rb +58 -14
  36. data/lib/gorillib/model/errors.rb +10 -0
  37. data/lib/gorillib/model/factories.rb +1 -367
  38. data/lib/gorillib/model/field.rb +40 -18
  39. data/lib/gorillib/model/fixup.rb +16 -0
  40. data/lib/gorillib/model/positional_fields.rb +35 -0
  41. data/lib/gorillib/model/schema_magic.rb +162 -0
  42. data/lib/gorillib/model/serialization.rb +1 -2
  43. data/lib/gorillib/model/serialization/csv.rb +59 -0
  44. data/lib/gorillib/pathname.rb +19 -8
  45. data/lib/gorillib/some.rb +2 -0
  46. data/lib/gorillib/string/constantize.rb +17 -10
  47. data/lib/gorillib/string/inflector.rb +11 -7
  48. data/lib/gorillib/type/boolean.rb +40 -0
  49. data/lib/gorillib/type/extended.rb +76 -40
  50. data/lib/gorillib/type/url.rb +6 -4
  51. data/lib/gorillib/utils/console.rb +1 -18
  52. data/lib/gorillib/utils/edge_cases.rb +18 -0
  53. data/spec/examples/builder/ironfan_spec.rb +5 -10
  54. data/spec/gorillib/array/compact_blank_spec.rb +36 -21
  55. data/spec/gorillib/array/simple_statistics_spec.rb +143 -0
  56. data/spec/gorillib/builder_spec.rb +16 -20
  57. data/spec/gorillib/collection_spec.rb +131 -35
  58. data/spec/gorillib/exception/raisers_spec.rb +39 -0
  59. data/spec/gorillib/hash/deep_compact_spec.rb +3 -3
  60. data/spec/gorillib/model/{record/defaults_spec.rb → defaults_spec.rb} +5 -1
  61. data/spec/gorillib/model/factories_spec.rb +335 -0
  62. data/spec/gorillib/model/{record/overlay_spec.rb → overlay_spec.rb} +0 -0
  63. data/spec/gorillib/model/serialization_spec.rb +2 -2
  64. data/spec/gorillib/model_spec.rb +19 -18
  65. data/spec/gorillib/pathname_spec.rb +7 -7
  66. data/spec/gorillib/string/truncate_spec.rb +3 -13
  67. data/spec/gorillib/type/extended_spec.rb +50 -2
  68. data/spec/gorillib/utils/capture_output_spec.rb +1 -1
  69. data/spec/spec_helper.rb +10 -7
  70. data/spec/support/factory_test_helpers.rb +76 -0
  71. data/spec/support/gorillib_test_helpers.rb +36 -24
  72. data/spec/support/model_test_helpers.rb +39 -2
  73. metadata +86 -51
  74. data/lib/alt/kernel/call_stack.rb +0 -56
  75. data/lib/gorillib/array/sorted_sample.rb +0 -12
  76. data/lib/gorillib/builder/field.rb +0 -5
  77. data/lib/gorillib/collection/has_collection.rb +0 -31
  78. data/lib/gorillib/collection/list_collection.rb +0 -58
  79. data/lib/gorillib/exception/confidence.rb +0 -17
  80. data/lib/gorillib/io/system_helpers.rb +0 -30
  81. data/lib/gorillib/model/record_schema.rb +0 -9
  82. data/lib/gorillib/utils/stub_module.rb +0 -33
  83. data/spec/array/average_spec.rb +0 -24
  84. data/spec/array/sorted_median_spec.rb +0 -18
  85. data/spec/array/sorted_percentile_spec.rb +0 -24
  86. data/spec/array/sorted_sample_spec.rb +0 -28
  87. data/spec/gorillib/metaprogramming/aliasing_spec.rb +0 -180
  88. data/spec/gorillib/model/record/factories_spec.rb +0 -335
  89. 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)
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "gorillib"
8
- s.version = "0.4.1pre"
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-06-27"
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/random.rb",
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/record_schema.rb",
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/record/defaults_spec.rb",
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 = "http://infochimps.com/labs"
191
- s.licenses = ["MIT"]
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.11"
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/array/average_spec.rb", "spec/array/sorted_median_spec.rb", "spec/array/sorted_percentile_spec.rb", "spec/array/sorted_sample_spec.rb", "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/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/aliasing_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/lint_spec.rb", "spec/gorillib/model/record/defaults_spec.rb", "spec/gorillib/model/record/factories_spec.rb", "spec/gorillib/model/record/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/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/kcode_test_helper.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"]
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<oj>, [">= 1.2"])
205
- s.add_development_dependency(%q<json>, [">= 0"])
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<oj>, [">= 1.2"])
211
- s.add_dependency(%q<json>, [">= 0"])
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<oj>, [">= 1.2"])
218
- s.add_dependency(%q<json>, [">= 0"])
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
@@ -1,5 +1,4 @@
1
1
  require 'gorillib/object/blank'
2
- require 'gorillib/object/try'
3
2
  require 'gorillib/array/extract_options'
4
3
  require 'gorillib/array/compact_blank'
5
4
  require 'gorillib/hash/reverse_merge'
@@ -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)[item_key] = item
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.read_attribute(key_method)
89
+ self.send(key_method)
88
90
  end
89
91
 
90
- def inspect_helper(detailed, attrs)
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
- field(field_name, Gorillib::ModelCollection, {
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 CollectionField < Gorillib::Model::Field
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