gorillib 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/gorillib.gemspec +32 -5
- data/lib/gorillib/array/hashify.rb +11 -0
- data/lib/gorillib/base.rb +1 -0
- data/lib/gorillib/data_munging.rb +8 -1
- data/lib/gorillib/exception/raisers.rb +6 -1
- data/lib/gorillib/factories.rb +26 -13
- data/lib/gorillib/model/base.rb +6 -1
- data/lib/gorillib/model/schema_magic.rb +1 -0
- data/lib/gorillib/model/serialization/csv.rb +2 -0
- data/lib/gorillib/model/serialization/json.rb +44 -0
- data/lib/gorillib/model/serialization/lines.rb +30 -0
- data/lib/gorillib/model/serialization/tsv.rb +55 -0
- data/lib/gorillib/pathname/utils.rb +34 -0
- data/lib/gorillib/type/extended.rb +1 -0
- data/lib/gorillib/type/ip_address.rb +153 -0
- data/notes/HOWTO.md +22 -0
- data/notes/bucket.md +155 -0
- data/notes/builder.md +170 -0
- data/notes/collection.md +81 -0
- data/notes/factories.md +86 -0
- data/notes/model-overlay.md +209 -0
- data/notes/model.md +135 -0
- data/notes/structured-data-classes.md +127 -0
- data/spec/gorillib/array/hashify_spec.rb +20 -0
- data/spec/gorillib/builder_spec.rb +2 -2
- data/spec/gorillib/{model/factories_spec.rb → factories_spec.rb} +3 -5
- data/spec/gorillib/model/serialization/tsv_spec.rb +17 -0
- data/spec/gorillib/type/ip_address_spec.rb +143 -0
- metadata +35 -5
data/Rakefile
CHANGED
@@ -42,6 +42,7 @@ Jeweler::Tasks.new do |gem|
|
|
42
42
|
reject{|f| File.directory?(f) }.
|
43
43
|
reject{|f| ignores.any?{|i| File.fnmatch(i, f) || File.fnmatch(i+'/**/*', f) || File.fnmatch(i+'/*', f) } }
|
44
44
|
gem.test_files = gem.files.grep(/^spec\//)
|
45
|
+
gem.extra_rdoc_files = [gem.files.grep(/^notes\//), gem.files.grep(/\.md$/)].flatten.uniq
|
45
46
|
gem.require_paths = ['lib']
|
46
47
|
end
|
47
48
|
Jeweler::RubygemsDotOrgTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/gorillib.gemspec
CHANGED
@@ -5,16 +5,26 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "gorillib"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
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-10-22"
|
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 = [
|
16
|
+
"CHANGELOG.md",
|
16
17
|
"LICENSE.md",
|
17
|
-
"README.md"
|
18
|
+
"README.md",
|
19
|
+
"TODO.md",
|
20
|
+
"notes/HOWTO.md",
|
21
|
+
"notes/bucket.md",
|
22
|
+
"notes/builder.md",
|
23
|
+
"notes/collection.md",
|
24
|
+
"notes/factories.md",
|
25
|
+
"notes/model-overlay.md",
|
26
|
+
"notes/model.md",
|
27
|
+
"notes/structured-data-classes.md"
|
18
28
|
]
|
19
29
|
s.files = [
|
20
30
|
".gitignore",
|
@@ -37,6 +47,7 @@ Gem::Specification.new do |s|
|
|
37
47
|
"lib/gorillib/array/compact_blank.rb",
|
38
48
|
"lib/gorillib/array/deep_compact.rb",
|
39
49
|
"lib/gorillib/array/extract_options.rb",
|
50
|
+
"lib/gorillib/array/hashify.rb",
|
40
51
|
"lib/gorillib/array/simple_statistics.rb",
|
41
52
|
"lib/gorillib/array/wrap.rb",
|
42
53
|
"lib/gorillib/base.rb",
|
@@ -99,12 +110,16 @@ Gem::Specification.new do |s|
|
|
99
110
|
"lib/gorillib/model/schema_magic.rb",
|
100
111
|
"lib/gorillib/model/serialization.rb",
|
101
112
|
"lib/gorillib/model/serialization/csv.rb",
|
113
|
+
"lib/gorillib/model/serialization/json.rb",
|
114
|
+
"lib/gorillib/model/serialization/lines.rb",
|
115
|
+
"lib/gorillib/model/serialization/tsv.rb",
|
102
116
|
"lib/gorillib/model/validate.rb",
|
103
117
|
"lib/gorillib/numeric/clamp.rb",
|
104
118
|
"lib/gorillib/object/blank.rb",
|
105
119
|
"lib/gorillib/object/try.rb",
|
106
120
|
"lib/gorillib/object/try_dup.rb",
|
107
121
|
"lib/gorillib/pathname.rb",
|
122
|
+
"lib/gorillib/pathname/utils.rb",
|
108
123
|
"lib/gorillib/serialization/to_wire.rb",
|
109
124
|
"lib/gorillib/some.rb",
|
110
125
|
"lib/gorillib/string/constantize.rb",
|
@@ -115,16 +130,26 @@ Gem::Specification.new do |s|
|
|
115
130
|
"lib/gorillib/string/truncate.rb",
|
116
131
|
"lib/gorillib/type/boolean.rb",
|
117
132
|
"lib/gorillib/type/extended.rb",
|
133
|
+
"lib/gorillib/type/ip_address.rb",
|
118
134
|
"lib/gorillib/type/url.rb",
|
119
135
|
"lib/gorillib/utils/capture_output.rb",
|
120
136
|
"lib/gorillib/utils/console.rb",
|
121
137
|
"lib/gorillib/utils/edge_cases.rb",
|
122
138
|
"lib/gorillib/utils/nuke_constants.rb",
|
139
|
+
"notes/HOWTO.md",
|
140
|
+
"notes/bucket.md",
|
141
|
+
"notes/builder.md",
|
142
|
+
"notes/collection.md",
|
143
|
+
"notes/factories.md",
|
144
|
+
"notes/model-overlay.md",
|
145
|
+
"notes/model.md",
|
146
|
+
"notes/structured-data-classes.md",
|
123
147
|
"spec/examples/builder/ironfan_spec.rb",
|
124
148
|
"spec/extlib/hash_spec.rb",
|
125
149
|
"spec/extlib/mash_spec.rb",
|
126
150
|
"spec/gorillib/array/compact_blank_spec.rb",
|
127
151
|
"spec/gorillib/array/extract_options_spec.rb",
|
152
|
+
"spec/gorillib/array/hashify_spec.rb",
|
128
153
|
"spec/gorillib/array/simple_statistics_spec.rb",
|
129
154
|
"spec/gorillib/builder_spec.rb",
|
130
155
|
"spec/gorillib/collection_spec.rb",
|
@@ -133,6 +158,7 @@ Gem::Specification.new do |s|
|
|
133
158
|
"spec/gorillib/datetime/to_flat_spec.rb",
|
134
159
|
"spec/gorillib/enumerable/sum_spec.rb",
|
135
160
|
"spec/gorillib/exception/raisers_spec.rb",
|
161
|
+
"spec/gorillib/factories_spec.rb",
|
136
162
|
"spec/gorillib/hash/compact_spec.rb",
|
137
163
|
"spec/gorillib/hash/deep_compact_spec.rb",
|
138
164
|
"spec/gorillib/hash/deep_merge_spec.rb",
|
@@ -150,9 +176,9 @@ Gem::Specification.new do |s|
|
|
150
176
|
"spec/gorillib/metaprogramming/delegation_spec.rb",
|
151
177
|
"spec/gorillib/metaprogramming/singleton_class_spec.rb",
|
152
178
|
"spec/gorillib/model/defaults_spec.rb",
|
153
|
-
"spec/gorillib/model/factories_spec.rb",
|
154
179
|
"spec/gorillib/model/lint_spec.rb",
|
155
180
|
"spec/gorillib/model/overlay_spec.rb",
|
181
|
+
"spec/gorillib/model/serialization/tsv_spec.rb",
|
156
182
|
"spec/gorillib/model/serialization_spec.rb",
|
157
183
|
"spec/gorillib/model_spec.rb",
|
158
184
|
"spec/gorillib/numeric/clamp_spec.rb",
|
@@ -166,6 +192,7 @@ Gem::Specification.new do |s|
|
|
166
192
|
"spec/gorillib/string/inflector_test_cases.rb",
|
167
193
|
"spec/gorillib/string/truncate_spec.rb",
|
168
194
|
"spec/gorillib/type/extended_spec.rb",
|
195
|
+
"spec/gorillib/type/ip_address_spec.rb",
|
169
196
|
"spec/gorillib/utils/capture_output_spec.rb",
|
170
197
|
"spec/spec_helper.rb",
|
171
198
|
"spec/support/factory_test_helpers.rb",
|
@@ -186,7 +213,7 @@ Gem::Specification.new do |s|
|
|
186
213
|
s.require_paths = ["lib"]
|
187
214
|
s.rubygems_version = "1.8.24"
|
188
215
|
s.summary = "include only what you need. No dependencies, no creep"
|
189
|
-
s.test_files = ["spec/extlib/mash_spec.rb", "spec/extlib/hash_spec.rb", "spec/support/gorillib_test_helpers.rb", "spec/support/hashlike_helper.rb", "spec/support/shared_examples/included_module.rb", "spec/support/hashlike_fuzzing_helper.rb", "spec/support/matchers/be_hash_eql.rb", "spec/support/matchers/be_array_eql.rb", "spec/support/matchers/enumerate_method.rb", "spec/support/matchers/evaluate_to_true.rb", "spec/support/model_test_helpers.rb", "spec/support/factory_test_helpers.rb", "spec/support/hashlike_via_delegation.rb", "spec/support/hashlike_struct_helper.rb", "spec/gorillib/model_spec.rb", "spec/gorillib/builder_spec.rb", "spec/gorillib/numeric/clamp_spec.rb", "spec/gorillib/string/human_spec.rb", "spec/gorillib/string/inflections_spec.rb", "spec/gorillib/string/inflector_test_cases.rb", "spec/gorillib/string/constantize_spec.rb", "spec/gorillib/string/truncate_spec.rb", "spec/gorillib/metaprogramming/class_attribute_spec.rb", "spec/gorillib/metaprogramming/singleton_class_spec.rb", "spec/gorillib/metaprogramming/delegation_spec.rb", "spec/gorillib/hashlike_spec.rb", "spec/gorillib/exception/raisers_spec.rb", "spec/gorillib/utils/capture_output_spec.rb", "spec/gorillib/collection_spec.rb", "spec/gorillib/type/extended_spec.rb", "spec/gorillib/hash/zip_spec.rb", "spec/gorillib/hash/reverse_merge_spec.rb", "spec/gorillib/hash/slice_spec.rb", "spec/gorillib/hash/keys_spec.rb", "spec/gorillib/hash/compact_spec.rb", "spec/gorillib/hash/deep_compact_spec.rb", "spec/gorillib/hash/deep_merge_spec.rb", "spec/gorillib/datetime/parse_spec.rb", "spec/gorillib/datetime/to_flat_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/behave_same_as_hash_spec.rb", "spec/gorillib/configurable_spec.rb", "spec/gorillib/model/
|
216
|
+
s.test_files = ["spec/extlib/mash_spec.rb", "spec/extlib/hash_spec.rb", "spec/support/gorillib_test_helpers.rb", "spec/support/hashlike_helper.rb", "spec/support/shared_examples/included_module.rb", "spec/support/hashlike_fuzzing_helper.rb", "spec/support/matchers/be_hash_eql.rb", "spec/support/matchers/be_array_eql.rb", "spec/support/matchers/enumerate_method.rb", "spec/support/matchers/evaluate_to_true.rb", "spec/support/model_test_helpers.rb", "spec/support/factory_test_helpers.rb", "spec/support/hashlike_via_delegation.rb", "spec/support/hashlike_struct_helper.rb", "spec/gorillib/model_spec.rb", "spec/gorillib/builder_spec.rb", "spec/gorillib/numeric/clamp_spec.rb", "spec/gorillib/string/human_spec.rb", "spec/gorillib/string/inflections_spec.rb", "spec/gorillib/string/inflector_test_cases.rb", "spec/gorillib/string/constantize_spec.rb", "spec/gorillib/string/truncate_spec.rb", "spec/gorillib/metaprogramming/class_attribute_spec.rb", "spec/gorillib/metaprogramming/singleton_class_spec.rb", "spec/gorillib/metaprogramming/delegation_spec.rb", "spec/gorillib/hashlike_spec.rb", "spec/gorillib/exception/raisers_spec.rb", "spec/gorillib/utils/capture_output_spec.rb", "spec/gorillib/collection_spec.rb", "spec/gorillib/type/extended_spec.rb", "spec/gorillib/type/ip_address_spec.rb", "spec/gorillib/hash/zip_spec.rb", "spec/gorillib/hash/reverse_merge_spec.rb", "spec/gorillib/hash/slice_spec.rb", "spec/gorillib/hash/keys_spec.rb", "spec/gorillib/hash/compact_spec.rb", "spec/gorillib/hash/deep_compact_spec.rb", "spec/gorillib/hash/deep_merge_spec.rb", "spec/gorillib/datetime/parse_spec.rb", "spec/gorillib/datetime/to_flat_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/behave_same_as_hash_spec.rb", "spec/gorillib/configurable_spec.rb", "spec/gorillib/factories_spec.rb", "spec/gorillib/model/serialization/tsv_spec.rb", "spec/gorillib/model/lint_spec.rb", "spec/gorillib/model/defaults_spec.rb", "spec/gorillib/model/serialization_spec.rb", "spec/gorillib/model/overlay_spec.rb", "spec/gorillib/pathname_spec.rb", "spec/gorillib/enumerable/sum_spec.rb", "spec/gorillib/object/try_spec.rb", "spec/gorillib/object/blank_spec.rb", "spec/gorillib/object/try_dup_spec.rb", "spec/gorillib/array/compact_blank_spec.rb", "spec/gorillib/array/simple_statistics_spec.rb", "spec/gorillib/array/extract_options_spec.rb", "spec/gorillib/array/hashify_spec.rb", "spec/gorillib/logger/log_spec.rb", "spec/spec_helper.rb", "spec/examples/builder/ironfan_spec.rb"]
|
190
217
|
|
191
218
|
if s.respond_to? :specification_version then
|
192
219
|
s.specification_version = 3
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Array
|
2
|
+
#
|
3
|
+
# Gets value of block on each element;
|
4
|
+
# constructs a hash of element-value pairs
|
5
|
+
#
|
6
|
+
# @return [Hash] hash of key-value pairs
|
7
|
+
def hashify
|
8
|
+
raise ArgumentError, 'hashify requires a block' unless block_given?
|
9
|
+
Hash[ self.map{|el| [el, yield(el)] } ]
|
10
|
+
end
|
11
|
+
end
|
data/lib/gorillib/base.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
require 'gorillib/base'
|
2
4
|
require 'gorillib/array/wrap'
|
3
5
|
require 'gorillib/type/extended'
|
4
6
|
require 'gorillib/hash/slice'
|
@@ -6,3 +8,8 @@ require 'gorillib/pathname'
|
|
6
8
|
require 'gorillib/logger/log'
|
7
9
|
require 'gorillib/model'
|
8
10
|
require 'gorillib/factories'
|
11
|
+
require 'gorillib/model/serialization'
|
12
|
+
require 'gorillib/model/serialization/csv'
|
13
|
+
require 'gorillib/model/serialization/tsv'
|
14
|
+
require 'gorillib/model/serialization/json'
|
15
|
+
require 'gorillib/model/indexable'
|
@@ -25,7 +25,7 @@ Exception.class_eval do
|
|
25
25
|
# end
|
26
26
|
#
|
27
27
|
def polish(extra_info)
|
28
|
-
filename, _, method_name = self.class.caller_parts
|
28
|
+
filename, _, method_name = self.class.caller_parts(2)
|
29
29
|
method_name.gsub!(/rescue in /, '')
|
30
30
|
most_recent_line = backtrace.detect{|line|
|
31
31
|
line.include?(filename) && line.include?(method_name) && line.end_with?("'") }
|
@@ -102,6 +102,11 @@ class ArgumentError
|
|
102
102
|
raise self, message, *args
|
103
103
|
end
|
104
104
|
|
105
|
+
|
106
|
+
def self.block_required!(block)
|
107
|
+
raise self.new("Block is required") unless block
|
108
|
+
end
|
109
|
+
|
105
110
|
#
|
106
111
|
# @param obj [Object] Object to check
|
107
112
|
# @param types [Array[Symbol,Class,Module]] Types or methods to compare
|
data/lib/gorillib/factories.rb
CHANGED
@@ -32,19 +32,6 @@ module Gorillib
|
|
32
32
|
klass.new(options)
|
33
33
|
end
|
34
34
|
|
35
|
-
# Manufactures objects from their raw attributes hash
|
36
|
-
#
|
37
|
-
# A hash with a value for `:_type` is dispatched to the corresponding factory
|
38
|
-
# Everything else is returned directly
|
39
|
-
def self.make(obj)
|
40
|
-
if obj.respond_to?(:has_key?) && (obj.has_key?(:_type) || obj.has_key?('_type'))
|
41
|
-
factory = Gorillib::Factory(attrs[:_type])
|
42
|
-
factory.receive(obj)
|
43
|
-
else
|
44
|
-
obj
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
35
|
def self.register_factory(factory, typenames)
|
49
36
|
typenames.each{|typename| factories[typename] = factory }
|
50
37
|
end
|
@@ -185,6 +172,14 @@ module Gorillib
|
|
185
172
|
end
|
186
173
|
end
|
187
174
|
|
175
|
+
# __________________________________________________________________________
|
176
|
+
#
|
177
|
+
# Generic Factories
|
178
|
+
# __________________________________________________________________________
|
179
|
+
|
180
|
+
#
|
181
|
+
# Factory that accepts whatever given and uses it directly -- no nothin'
|
182
|
+
#
|
188
183
|
class ::Whatever < BaseFactory
|
189
184
|
def initialize(options={})
|
190
185
|
options.slice!(:convert, :blankish)
|
@@ -200,6 +195,24 @@ module Gorillib
|
|
200
195
|
end
|
201
196
|
IdenticalFactory = ::Whatever unless defined?(IdenticalFactory)
|
202
197
|
|
198
|
+
|
199
|
+
# Manufactures objects from their raw attributes hash
|
200
|
+
#
|
201
|
+
# The hash must have a value for `:_type`, used to retrieve the actual factory
|
202
|
+
#
|
203
|
+
class ::GenericModel < BaseFactory
|
204
|
+
def blankish?(obj) obj.nil? ; end
|
205
|
+
def native?(obj) false ; end
|
206
|
+
def receive(attrs, &block)
|
207
|
+
Gorillib::Model::Validate.hashlike!(attrs){ "attributes for typed object" }
|
208
|
+
klass = Gorillib::Factory(attrs.fetch(:_type){ attrs.fetch("_type") })
|
209
|
+
#
|
210
|
+
klass.new(attrs, &block)
|
211
|
+
end
|
212
|
+
def self.receive(obj) allocate.receive(obj) end
|
213
|
+
register_factory!(GenericModel, :generic)
|
214
|
+
end
|
215
|
+
|
203
216
|
# __________________________________________________________________________
|
204
217
|
#
|
205
218
|
# Concrete Factories
|
data/lib/gorillib/model/base.rb
CHANGED
@@ -31,6 +31,7 @@ module Gorillib
|
|
31
31
|
# @return [{Symbol => Object}] The Hash of all attributes
|
32
32
|
def attributes
|
33
33
|
self.class.field_names.inject(Hash.new) do |hsh, fn|
|
34
|
+
# hsh[fn] = attribute_set?(fn) ? read_attribute(fn) : nil
|
34
35
|
hsh[fn] = read_attribute(fn)
|
35
36
|
hsh
|
36
37
|
end
|
@@ -199,6 +200,10 @@ module Gorillib
|
|
199
200
|
str << '>'
|
200
201
|
end
|
201
202
|
|
203
|
+
def to_s
|
204
|
+
inspect
|
205
|
+
end
|
206
|
+
|
202
207
|
def inspect_compact
|
203
208
|
str = "#<#{self.class.name.to_s}>"
|
204
209
|
end
|
@@ -208,7 +213,6 @@ module Gorillib
|
|
208
213
|
def to_inspectable
|
209
214
|
compact_attributes
|
210
215
|
end
|
211
|
-
private :to_inspectable
|
212
216
|
|
213
217
|
protected
|
214
218
|
|
@@ -260,6 +264,7 @@ module Gorillib
|
|
260
264
|
base.instance_eval do
|
261
265
|
extend Gorillib::Model::NamedSchema
|
262
266
|
extend Gorillib::Model::ClassMethods
|
267
|
+
self.meta_module
|
263
268
|
@_own_fields ||= {}
|
264
269
|
end
|
265
270
|
end
|
@@ -21,9 +21,11 @@ module Gorillib
|
|
21
21
|
def each_in_csv(filename, options={})
|
22
22
|
filename = Pathname.path_to(filename)
|
23
23
|
options = csv_options.merge(options)
|
24
|
+
#
|
24
25
|
pop_headers = options.delete(:pop_headers)
|
25
26
|
num_fields = options.delete(:num_fields){ (fields.length .. fields.length) }
|
26
27
|
raise ArgumentError, "The :headers option to CSV changes its internal behavior; use 'pop_headers: true' to ignore the first line" if options[:headers]
|
28
|
+
#
|
27
29
|
CSV.open(filename, options) do |csv_file|
|
28
30
|
csv_file.shift if pop_headers
|
29
31
|
csv_file.each do |tuple|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative './lines'
|
2
|
+
|
3
|
+
module Gorillib
|
4
|
+
module Model
|
5
|
+
|
6
|
+
module LoadFromJson
|
7
|
+
extend Gorillib::Concern
|
8
|
+
include LoadLines
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
# Iterate a block over each line of a file having JSON records, one per
|
13
|
+
# line, in a big stack
|
14
|
+
#
|
15
|
+
# @yield an object instantiated from each line in the file.
|
16
|
+
def _each_from_json(filename, options={})
|
17
|
+
_each_raw_line(filename, options) do |line|
|
18
|
+
hsh = MultiJson.load(line)
|
19
|
+
yield receive(hsh)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# With a block, calls block on each object in turn (and returns nil)
|
24
|
+
#
|
25
|
+
# With no block, accumulates all the instances into the array it
|
26
|
+
# returns. As opposed to the with-a-block case, the memory footprint of
|
27
|
+
# this increases as the filesize does, so use caution with large files.
|
28
|
+
#
|
29
|
+
# @return with a block, returns nil; with no block, an array of this class' instances
|
30
|
+
def load_json(*args)
|
31
|
+
if block_given?
|
32
|
+
_each_from_json(*args, &Proc.new)
|
33
|
+
else
|
34
|
+
objs = []
|
35
|
+
_each_from_json(*args){|obj| objs << obj }
|
36
|
+
objs
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Gorillib
|
2
|
+
module Model
|
3
|
+
|
4
|
+
module LoadLines
|
5
|
+
extend Gorillib::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
# Iterate a block over each line of a file
|
10
|
+
# @yield each line in the file.
|
11
|
+
def _each_raw_line(filename, options={})
|
12
|
+
filename = Pathname.path_to(filename)
|
13
|
+
#
|
14
|
+
pop_headers = options.delete(:pop_headers)
|
15
|
+
#
|
16
|
+
File.open(filename) do |file|
|
17
|
+
file.readline if pop_headers
|
18
|
+
file.each do |line|
|
19
|
+
line.chomp! ; next if line.empty?
|
20
|
+
yield line
|
21
|
+
end
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative './lines'
|
2
|
+
|
3
|
+
module Gorillib
|
4
|
+
module Model
|
5
|
+
|
6
|
+
module LoadFromTsv
|
7
|
+
extend Gorillib::Concern
|
8
|
+
include LoadLines
|
9
|
+
|
10
|
+
included do |base|
|
11
|
+
# Options that will be passed to CSV. Be careful to modify with assignment (`+=`) and not in-place (`<<`)
|
12
|
+
base.class_attribute :tsv_options
|
13
|
+
base.tsv_options = Hash.new
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
# Iterate a block over each line of a TSV file
|
19
|
+
#
|
20
|
+
# @raise [Gorillib::Model::RawDataMismatchError] if a line has too many or too few fields
|
21
|
+
# @yield an object instantiated from each line in the file.
|
22
|
+
def _each_from_tsv(filename, options={})
|
23
|
+
options = tsv_options.merge(options)
|
24
|
+
num_fields = options.delete(:num_fields){ (fields.length .. fields.length) }
|
25
|
+
max_fields = num_fields.max # need to make sure "1\t2\t\t\t" becomes ["1","2","","",""]
|
26
|
+
#
|
27
|
+
_each_raw_line(filename, options) do |line|
|
28
|
+
tuple = line.split("\t", max_fields)
|
29
|
+
unless num_fields.include?(tuple.length) then raise Gorillib::Model::RawDataMismatchError, "yark, spurious fields: #{tuple.inspect}" ; end
|
30
|
+
yield from_tuple(*tuple)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# With a block, calls block on each object in turn (and returns nil)
|
35
|
+
#
|
36
|
+
# With no block, accumulates all the instances into the array it
|
37
|
+
# returns. As opposed to the with-a-block case, the memory footprint of
|
38
|
+
# this increases as the filesize does, so use caution with large files.
|
39
|
+
#
|
40
|
+
# @return with a block, returns nil; with no block, an array of this class' instances
|
41
|
+
def load_tsv(*args)
|
42
|
+
if block_given?
|
43
|
+
_each_from_tsv(*args, &Proc.new)
|
44
|
+
else
|
45
|
+
objs = []
|
46
|
+
_each_from_tsv(*args){|obj| objs << obj }
|
47
|
+
objs
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Pathname
|
2
|
+
# same as `#exist?`
|
3
|
+
def exists?(*args) exist?(*args) ; end
|
4
|
+
|
5
|
+
# @example It chains nicely:
|
6
|
+
# # put each file in eg. dest/f/foo.json
|
7
|
+
# Pathname.of(:dest, slug[0..0], "#{slug}.json").mkparent.open('w') do |file|
|
8
|
+
# # ...
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# @returns the path itself (not its parent)
|
12
|
+
def mkparent
|
13
|
+
dirname.mkpath
|
14
|
+
return self
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Executes the block (passing the opened file) if the file does not
|
19
|
+
# exist. Ignores the block otherwise. The block is required.
|
20
|
+
#
|
21
|
+
# @param options
|
22
|
+
# @option options[:force] Force creation of the file
|
23
|
+
#
|
24
|
+
# @returns the path itself (not the file)
|
25
|
+
def if_missing(options={}, &block)
|
26
|
+
ArgumentError.block_required!(block)
|
27
|
+
return self if exist? && (not options[:force])
|
28
|
+
#
|
29
|
+
mkparent
|
30
|
+
open((options[:mode] || 'w'), &block)
|
31
|
+
return self
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|