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.
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