csv_find 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fad9ba988bfb458d1f4cf9d27d4b3b6ff1fa97ef
4
+ data.tar.gz: e648ecab510c2f0c439ce25d8ba05ab7831b4ec6
5
+ SHA512:
6
+ metadata.gz: ecb6a2486aa3c178e583914a02930d31b5cbd1656791fccaf2aa1536db80620129184320ab26dc979e70f012e1a60060b239e57052cb7b7154da4a7a2424fa8a
7
+ data.tar.gz: 08689bf0756703c741e416f5f5174851959300cd47849b5c1c3ecececbf891b97b5551e159392cc8a9257ef7079cdfa769e4dc2e7c4b6a3735f65d0c4a0e9c26
@@ -0,0 +1,165 @@
1
+ module CsvFind
2
+ require 'csv'
3
+
4
+ VERSION = {
5
+ major: '0',
6
+ minor: '0',
7
+ patch: '1'
8
+ }.values.join('.')
9
+
10
+ def self.included(base)
11
+ base.send :extend, ClassMethods
12
+ base.send :prepend, InstanceMethods
13
+ end
14
+
15
+ module InstanceMethods
16
+ attr_accessor :line_number
17
+
18
+ def initialize(hash = {})
19
+ hash.each { |k,v| send("#{k}=".to_sym, v) }
20
+ end
21
+
22
+ def ==(other_instance)
23
+ instance_variables.map do |instance_variable|
24
+ instance_variable_get(instance_variable) ==
25
+ other_instance.instance_variable_get(instance_variable)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :hash
32
+ end
33
+
34
+ module ClassMethods
35
+ include Enumerable
36
+
37
+ attr_reader :headers, :file, :file_options,
38
+ :first_line, :middle_line, :last_line
39
+
40
+ def csv_file(file_name, options = {})
41
+ @file_options = default_options.merge(options)
42
+ @file = CSV.new(File.open(file_name, 'r'), @file_options)
43
+ @first_line = 2
44
+ @last_line = `wc -l #{file_name}`.split(' ').first.to_i
45
+ @middle_line = (@last_line/2) + 1
46
+ @line_number = nil
47
+ @headers = extract_headers(file_name, file_options)
48
+
49
+ define_accessors
50
+ end
51
+
52
+ def define_accessors
53
+ headers.each do |header|
54
+ send(:attr_accessor, header)
55
+ end
56
+ end
57
+
58
+ def all
59
+ rewind
60
+ file.map { |row| build_instance(row, file.lineno) }
61
+ end
62
+
63
+ def where(key_val_pair)
64
+ search(key_val_pair).map { |row| build_instance(row, row[:line_number]) }
65
+ end
66
+
67
+ def find_by(key_val_pair)
68
+ warn DEPRECATION_MESSAGE
69
+ row = search(key_val_pair).last
70
+ row.nil? ? nil : build_instance(row, row[:line_number])
71
+ end
72
+
73
+ def find_all_by(key_val_pair)
74
+ warn DEPRECATION_MESSAGE
75
+ where(key_val_pair)
76
+ end
77
+
78
+ def find(line_number)
79
+ row = if (first_line..middle_line).include?(line_number)
80
+ front_find(line_number, file.path)
81
+ else
82
+ back_find(line_number, file.path)
83
+ end
84
+
85
+ row.nil? ? row : build_instance(row, line_number)
86
+ end
87
+
88
+ def first
89
+ rewind
90
+ build_instance(file.first, first_line)
91
+ end
92
+
93
+ def last
94
+ command = `head -n 1 #{file.path} && tail -n 1 #{file.path}`
95
+ last_row = CSV.new(command, file_options).first
96
+ build_instance(last_row, last_line)
97
+ end
98
+
99
+ def each
100
+ rewind
101
+ (first_line..last_line).each do |line_number|
102
+ yield find(line_number) if block_given?
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ DEPRECATION_MESSAGE =
109
+ '[DEPRECATION] This method is deprecated and will be removed in v2.' <<
110
+ 'Please user #where.'
111
+
112
+ def default_options
113
+ {
114
+ headers: true,
115
+ header_converters: :symbol,
116
+ return_headers: false
117
+ }
118
+ end
119
+
120
+ def extract_headers(file_name, options)
121
+ csv_file = File.open(file_name,'r')
122
+ CSV.new(csv_file, options).first.headers
123
+ end
124
+
125
+ def build_instance(row, line)
126
+ new_instance = new
127
+ row.each { |key, value| new_instance.send("#{key}=".to_sym, value) }
128
+ new_instance.line_number = line
129
+
130
+ new_instance
131
+ end
132
+
133
+ def rewind
134
+ file.rewind
135
+ end
136
+
137
+ def search(key_val_pair)
138
+ rewind
139
+ @results = file
140
+ @pairs = key_val_pair
141
+
142
+ @pairs.each { |pair| @results = dig(pair, @results) }
143
+
144
+ @results
145
+ end
146
+
147
+ def dig(hash_pair, rows)
148
+ rows.select do |row|
149
+ if row[hash_pair.first] == hash_pair.last
150
+ $. != last_line ? row.push(line_number: $.) : row
151
+ end
152
+ end
153
+ end
154
+
155
+ def front_find(line_number, file_path)
156
+ command = `head -n 1 #{file_path} && head -n #{line_number} #{file_path} | tail -n 1`
157
+ CSV.new(command, file_options).first
158
+ end
159
+
160
+ def back_find(line_number, file_path)
161
+ command = `head -n 1 #{file_path} && tail -n #{(last_line + 1) - line_number} #{file_path} | head -n 1`
162
+ CSV.new(command, file_options).first
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,103 @@
1
+ require './lib/csv_find'
2
+
3
+ class People
4
+ include CsvFind
5
+ csv_file('spec/support/demo.csv', {})
6
+ end
7
+
8
+ describe People do
9
+ before(:all){
10
+ @person1 = People.new(first: 'Mark', last: 'Platt', nickname: 'JCool', line_number: 2)
11
+ @person2 = People.new(first: 'Longinus', last: 'Smith', nickname: 'Pebbles', line_number: 3)
12
+ @person3 = People.new(first: 'Johnny', last: 'Radiation', nickname: 'Pebbles', line_number: 4)
13
+ @person4 = People.new(first: 'Charlie', last: 'Mansfield', nickname: 'Sammykins', line_number: 5)
14
+ }
15
+
16
+ context 'class methods' do
17
+ it "responds to .first" do
18
+ (People).should respond_to(:first)
19
+ end
20
+
21
+ it ".first returns correctly" do
22
+ expect(People.first).to eq @person1
23
+ end
24
+
25
+ it "responds to .last" do
26
+ (People).should respond_to(:last)
27
+ end
28
+
29
+ it ".last returns correctly" do
30
+ expect(People.last).to eq @person4
31
+ end
32
+
33
+ it "responds to .find" do
34
+ (People).should respond_to(:find)
35
+ end
36
+
37
+ it ".find returns correctly" do
38
+ expect(People.find(2)).to eq @person1
39
+ expect(People.find(3)).to eq @person2
40
+ expect(People.find(4)).to eq @person3
41
+ expect(People.find(5)).to eq @person4
42
+ end
43
+
44
+ it "[DEPRECATED] responds to .find_by" do
45
+ (People).should respond_to(:find_by)
46
+ end
47
+
48
+ it "[DEPRECATED] .find_by returns correctly" do
49
+ expect(People.find_by(nickname: 'Pebbles')).to eq @person3
50
+ expect(People.find_by(nickname: 'Pebbles', last: 'Smith')).to eq @person2
51
+ end
52
+
53
+ it ".find_by returns an nil if there are no results" do
54
+ expect(People.find_by(nickname: 'Beastmode')).to eq nil
55
+ end
56
+
57
+
58
+ it "responds to .where" do
59
+ (People).should respond_to(:where)
60
+ end
61
+
62
+ it ".where returns correctly" do
63
+ expect(People.where(nickname: 'Pebbles')).to eq [@person2, @person3]
64
+ expect(People.where(nickname: 'Pebbles', last: 'Radiation')).to eq [@person3]
65
+ end
66
+
67
+ it ".where returns an empty array if there are no results" do
68
+ expect(People.where(nickname: 'Beastmode')).to eq []
69
+ end
70
+
71
+ it "[DEPRECATED] responds to .find_all_by" do
72
+ (People).should respond_to(:find_all_by)
73
+ end
74
+
75
+ it "[DEPRECATED] .find_all_by returns correctly" do
76
+ expect(People.find_all_by(nickname: 'Pebbles')).to eq [@person2, @person3]
77
+ expect(People.find_all_by(nickname: 'Pebbles', last: 'Radiation')).to eq [@person3]
78
+ end
79
+
80
+ it "responds to .each" do
81
+ (People).should respond_to(:each)
82
+ end
83
+
84
+ it ".each line yields" do
85
+ @output = []
86
+ People.each{ |person| @output << person.first }
87
+ expect(@output).to eq ['Mark', 'Longinus', 'Johnny', 'Charlie']
88
+ end
89
+ end
90
+ context 'instance methods' do
91
+ it "responds to .first as defined in the csv" do
92
+ (People.new).should respond_to(:first)
93
+ end
94
+
95
+ it "responds to .last as defined in the csv" do
96
+ (People.new).should respond_to(:last)
97
+ end
98
+
99
+ it "responds to .nickname as defined in the csv" do
100
+ (People.new).should respond_to(:nickname)
101
+ end
102
+ end
103
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: csv_find
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Mark Platt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.14.1
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.14.1
27
+ description: "'csv_find will blah blah blah'"
28
+ email: mplatt@mrkplt.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/csv_find/csv_find.rb
34
+ - spec/csv_find_spec.rb
35
+ homepage: http://mrkplt.com
36
+ licenses:
37
+ - MIT
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.0.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 2.2.2
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: "'blah'"
59
+ test_files:
60
+ - spec/csv_find_spec.rb