seamusabshere-csv_dictionary 0.0.1
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/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +56 -0
- data/lib/csv_dictionary.rb +236 -0
- data/test/csv_dictionary_ext_test.rb +82 -0
- data/test/csv_dictionary_test.rb +60 -0
- data/test/test_helper.rb +71 -0
- metadata +62 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Seamus Abshere
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "csv_dictionary"
|
8
|
+
gem.summary = %Q{TODO}
|
9
|
+
gem.email = "seamus@abshere.net"
|
10
|
+
gem.homepage = "http://github.com/seamusabshere/csv_dictionary"
|
11
|
+
gem.authors = ["Seamus Abshere"]
|
12
|
+
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
Rake::TestTask.new(:test) do |test|
|
21
|
+
test.libs << 'lib' << 'test'
|
22
|
+
test.pattern = 'test/**/*_test.rb'
|
23
|
+
test.verbose = true
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
require 'rcov/rcovtask'
|
28
|
+
Rcov::RcovTask.new do |test|
|
29
|
+
test.libs << 'test'
|
30
|
+
test.pattern = 'test/**/*_test.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
rescue LoadError
|
34
|
+
task :rcov do
|
35
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
task :default => :test
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
if File.exist?('VERSION.yml')
|
45
|
+
config = YAML.load(File.read('VERSION.yml'))
|
46
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
47
|
+
else
|
48
|
+
version = ""
|
49
|
+
end
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "csv_dictionary #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
56
|
+
|
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fastercsv'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'active_support'
|
5
|
+
|
6
|
+
class CsvDictionary
|
7
|
+
attr_accessor :url, :key_sprintf, :key_name, :sheet # set in options
|
8
|
+
attr_accessor :dictionary, :value_name
|
9
|
+
|
10
|
+
def replace_attributes!(attributes)
|
11
|
+
load_dictionary unless dictionary_loaded?
|
12
|
+
attributes[value_name] = lookup(attributes[key_name])
|
13
|
+
attributes.delete(key_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def lookup(key)
|
17
|
+
load_dictionary unless dictionary_loaded?
|
18
|
+
dictionary[interpret_key(key)]
|
19
|
+
rescue
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def initialize(key_name, options = {})
|
26
|
+
@key_name = key_name
|
27
|
+
@sheet = options[:sheet] ? options[:sheet] - 1 : nil
|
28
|
+
@key_sprintf = options[:key_sprintf] || '%s'
|
29
|
+
@url = options[:url]
|
30
|
+
validate
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate
|
34
|
+
raise 'Please specify a key name.' if key_name.blank?
|
35
|
+
raise 'Please specify a url.' if url.blank?
|
36
|
+
raise ':sheet option is only supported for Google Docs Spreadsheet URLs.' if not sheet.nil? and not google_docs_spreadsheet_url?(url)
|
37
|
+
if google_docs_spreadsheet_url?(url) and /\&gid=(.*)(\&|$)/.match(url)
|
38
|
+
raise "Your Google Docs Spreadsheet URL includes a sheet number (&gid=#{$1}). Please remove it and set the sheet with :sheet => #{$1.to_i + 1}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def google_docs_spreadsheet_url?(url)
|
43
|
+
url.include?('spreadsheets.google.com')
|
44
|
+
end
|
45
|
+
|
46
|
+
def dictionary_loaded?
|
47
|
+
!dictionary.nil?
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_dictionary
|
51
|
+
self.dictionary = {}
|
52
|
+
open(interpret_url(url)) do |data|
|
53
|
+
FasterCSV.parse(data, :headers => :first_row) do |row|
|
54
|
+
self.value_name ||= row.headers[1].to_sym
|
55
|
+
next if row.fields[0..1].any? { |c| c.blank? }
|
56
|
+
key = interpret_key(row.fields[0])
|
57
|
+
value = row.fields[1].to_s.strip
|
58
|
+
dictionary[key] = value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def interpret_url(url)
|
64
|
+
if google_docs_spreadsheet_url?(url)
|
65
|
+
url = url.gsub(/\&output=.*(\&|$)/, '')
|
66
|
+
url << "&output=csv&gid=#{sheet}"
|
67
|
+
end
|
68
|
+
url
|
69
|
+
end
|
70
|
+
|
71
|
+
def interpret_key(k)
|
72
|
+
k = k.to_s.strip
|
73
|
+
k = k.to_i if /\%[0-9\.]*d/.match(key_sprintf)
|
74
|
+
key_sprintf % k
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module ActiveRecord
|
79
|
+
module CsvDictionaryExt
|
80
|
+
def self.included(klass)
|
81
|
+
klass.class_eval do
|
82
|
+
self.class_inheritable_accessor :csv_dictionaries
|
83
|
+
extend ClassMethods
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
module ClassMethods
|
88
|
+
def csv_dictionary(key_name, options = {})
|
89
|
+
class_eval { @old_method_missing = instance_method(:method_missing) }
|
90
|
+
self.csv_dictionaries ||= {}
|
91
|
+
csv_dictionaries[key_name] = CsvDictionary.new(key_name, options)
|
92
|
+
extend InstanceMethods
|
93
|
+
end
|
94
|
+
|
95
|
+
def clear_csv_dictionaries
|
96
|
+
self.csv_dictionaries = {}
|
97
|
+
end
|
98
|
+
|
99
|
+
def replace_csv_dictionary_attributes!(attributes)
|
100
|
+
csv_dictionaries.values.each { |d| d.replace_attributes!(attributes) }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
module InstanceMethods
|
105
|
+
def all_attributes_or_csv_dictionary_attributes_exists?(attribute_names)
|
106
|
+
attribute_names = expand_attribute_names_for_aggregates(attribute_names)
|
107
|
+
attribute_names.all? { |name| column_methods_hash.include?(name.to_sym) or csv_dictionaries.has_key?(name.to_sym) }
|
108
|
+
end
|
109
|
+
|
110
|
+
# like Rails 2.3.2
|
111
|
+
# copied from http://github.com/rails/rails/raw/dd2eb1ea7c34eb6496feaf7e42100f37a8dae76b/activerecord/lib/active_record/base.rb
|
112
|
+
def method_missing_with_csv_dictionary_attributes(method_id, *arguments, &block)
|
113
|
+
if match = DynamicFinderMatch.match(method_id)
|
114
|
+
attribute_names = match.attribute_names
|
115
|
+
return method_missing_without_csv_dictionary_attributes(method_id, arguments, block) unless all_attributes_or_csv_dictionary_attributes_exists?(attribute_names)
|
116
|
+
if match.finder?
|
117
|
+
finder = match.finder
|
118
|
+
bang = match.bang?
|
119
|
+
# def self.find_by_login_and_activated(*args)
|
120
|
+
# options = args.extract_options!
|
121
|
+
# attributes = construct_attributes_from_arguments(
|
122
|
+
# [:login,:activated],
|
123
|
+
# args
|
124
|
+
# )
|
125
|
+
#
|
126
|
+
# replace_csv_dictionary_attributes!(attributes) # ADDED BY SEAMUS
|
127
|
+
#
|
128
|
+
# finder_options = { :conditions => attributes }
|
129
|
+
# validate_find_options(options)
|
130
|
+
# set_readonly_option!(options)
|
131
|
+
#
|
132
|
+
# if options[:conditions]
|
133
|
+
# with_scope(:find => finder_options) do
|
134
|
+
# find(:first, options)
|
135
|
+
# end
|
136
|
+
# else
|
137
|
+
# find(:first, options.merge(finder_options))
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
self.class_eval %{
|
141
|
+
def self.#{method_id}(*args)
|
142
|
+
options = args.extract_options!
|
143
|
+
attributes = construct_attributes_from_arguments(
|
144
|
+
[:#{attribute_names.join(',:')}],
|
145
|
+
args
|
146
|
+
)
|
147
|
+
|
148
|
+
replace_csv_dictionary_attributes!(attributes)
|
149
|
+
|
150
|
+
finder_options = { :conditions => attributes }
|
151
|
+
validate_find_options(options)
|
152
|
+
set_readonly_option!(options)
|
153
|
+
|
154
|
+
#{'result = ' if bang}if options[:conditions]
|
155
|
+
with_scope(:find => finder_options) do
|
156
|
+
find(:#{finder}, options)
|
157
|
+
end
|
158
|
+
else
|
159
|
+
find(:#{finder}, options.merge(finder_options))
|
160
|
+
end
|
161
|
+
#{'result || raise(RecordNotFound, "Couldn\'t find #{name} with #{attributes.to_a.collect {|pair| "#{pair.first} = #{pair.second}"}.join(\', \')}")' if bang}
|
162
|
+
end
|
163
|
+
}, __FILE__, __LINE__
|
164
|
+
send(method_id, *arguments)
|
165
|
+
elsif match.instantiator?
|
166
|
+
instantiator = match.instantiator
|
167
|
+
# def self.find_or_create_by_user_id(*args)
|
168
|
+
# guard_protected_attributes = false
|
169
|
+
#
|
170
|
+
# if args[0].is_a?(Hash)
|
171
|
+
# guard_protected_attributes = true
|
172
|
+
# attributes = args[0].with_indifferent_access
|
173
|
+
# find_attributes = attributes.slice(*[:user_id])
|
174
|
+
# else
|
175
|
+
# find_attributes = attributes = construct_attributes_from_arguments([:user_id], args)
|
176
|
+
# end
|
177
|
+
#
|
178
|
+
# replace_csv_dictionary_attributes!(attributes) # ADDED BY SEAMUS
|
179
|
+
# replace_csv_dictionary_attributes!(find_attributes) # ADDED BY SEAMUS
|
180
|
+
#
|
181
|
+
# options = { :conditions => find_attributes }
|
182
|
+
# set_readonly_option!(options)
|
183
|
+
#
|
184
|
+
# record = find(:first, options)
|
185
|
+
#
|
186
|
+
# if record.nil?
|
187
|
+
# record = self.new { |r| r.send(:attributes=, attributes, guard_protected_attributes) }
|
188
|
+
# yield(record) if block_given?
|
189
|
+
# record.save
|
190
|
+
# record
|
191
|
+
# else
|
192
|
+
# record
|
193
|
+
# end
|
194
|
+
# end
|
195
|
+
self.class_eval %{
|
196
|
+
def self.#{method_id}(*args)
|
197
|
+
guard_protected_attributes = false
|
198
|
+
|
199
|
+
if args[0].is_a?(Hash)
|
200
|
+
guard_protected_attributes = true
|
201
|
+
attributes = args[0].with_indifferent_access
|
202
|
+
find_attributes = attributes.slice(*[:#{attribute_names.join(',:')}])
|
203
|
+
replace_csv_dictionary_attributes!(attributes)
|
204
|
+
replace_csv_dictionary_attributes!(find_attributes)
|
205
|
+
else
|
206
|
+
find_attributes = attributes = construct_attributes_from_arguments([:#{attribute_names.join(',:')}], args)
|
207
|
+
replace_csv_dictionary_attributes!(attributes) # only have to do this once, since find_attributes.object_id == attributes.object_id
|
208
|
+
end
|
209
|
+
|
210
|
+
options = { :conditions => find_attributes }
|
211
|
+
set_readonly_option!(options)
|
212
|
+
|
213
|
+
record = find(:first, options)
|
214
|
+
|
215
|
+
if record.nil?
|
216
|
+
record = self.new { |r| r.send(:attributes=, attributes, guard_protected_attributes) }
|
217
|
+
#{'yield(record) if block_given?'}
|
218
|
+
#{'record.save' if instantiator == :create}
|
219
|
+
record
|
220
|
+
else
|
221
|
+
record
|
222
|
+
end
|
223
|
+
end
|
224
|
+
}, __FILE__, __LINE__
|
225
|
+
send(method_id, *arguments, &block)
|
226
|
+
end
|
227
|
+
else
|
228
|
+
method_missing_without_csv_dictionary_attributes(method_id, arguments, block)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
alias_method_chain :method_missing, :csv_dictionary_attributes
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
ActiveRecord::Base.send :include, ActiveRecord::CsvDictionaryExt
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CsvDictionaryExtTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
CsvDictionaryTestHelper.setup_database
|
6
|
+
end
|
7
|
+
|
8
|
+
def teardown
|
9
|
+
Aircraft.clear_csv_dictionaries
|
10
|
+
CsvDictionaryTestHelper.teardown_database
|
11
|
+
end
|
12
|
+
|
13
|
+
# sanity check
|
14
|
+
def test_should_have_dictionary_value_name
|
15
|
+
assert_nothing_raised do
|
16
|
+
Aircraft.new.brighter_planet_aircraft_class_code
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# sanity check
|
21
|
+
def test_should_not_have_dictionary_key_name
|
22
|
+
assert_raise NoMethodError do
|
23
|
+
Aircraft.new.bts_aircraft_type
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_mixin_methods
|
28
|
+
assert Aircraft.respond_to?(:csv_dictionary)
|
29
|
+
assert Aircraft.respond_to?(:clear_csv_dictionaries)
|
30
|
+
assert Aircraft.respond_to?(:replace_csv_dictionary_attributes!)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_should_not_affect_other_activerecord_models
|
34
|
+
Aircraft.csv_dictionary :bts_aircraft_type, :url => CSV_URL
|
35
|
+
assert Hash === Aircraft.csv_dictionaries
|
36
|
+
assert NilClass === Scrum.csv_dictionaries
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_configure_csv_dictionary
|
40
|
+
key_name = :bts_aircraft_type
|
41
|
+
options = { :url => GDOCS_URL, :sheet => 1 }
|
42
|
+
CsvDictionary.expects(:new).with(key_name, options)
|
43
|
+
Aircraft.csv_dictionary key_name, options
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_should_replace_attributes
|
47
|
+
Aircraft.csv_dictionary :bts_aircraft_type, :url => CSV_URL
|
48
|
+
Aircraft.csv_dictionaries[:bts_aircraft_type].expects(:replace_attributes!)
|
49
|
+
Aircraft.replace_csv_dictionary_attributes!({})
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_should_recognize_dynamic_finders
|
53
|
+
fixture = Aircraft.find_or_create_by_brighter_planet_aircraft_class_code('SJ')
|
54
|
+
Aircraft.csv_dictionary :bts_aircraft_type, :url => CSV_URL
|
55
|
+
Aircraft.csv_dictionaries[:bts_aircraft_type].expects(:lookup).with('103').returns('SJ').times(4)
|
56
|
+
assert_equal fixture, Aircraft.find_by_bts_aircraft_type('103')
|
57
|
+
assert_equal fixture, Aircraft.find_by_bts_aircraft_type_and_brighter_planet_aircraft_class_code('103', 'SJ')
|
58
|
+
assert_equal [fixture], Aircraft.find_all_by_bts_aircraft_type('103')
|
59
|
+
assert_equal [fixture], Aircraft.find_all_by_bts_aircraft_type_and_brighter_planet_aircraft_class_code('103', 'SJ')
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_should_recognize_dynamic_initializers
|
63
|
+
fixture = Aircraft.find_or_create_by_brighter_planet_aircraft_class_code('SJ')
|
64
|
+
Aircraft.csv_dictionary :bts_aircraft_type, :url => CSV_URL
|
65
|
+
Aircraft.csv_dictionaries[:bts_aircraft_type].expects(:lookup).with('103').returns('SJ').twice
|
66
|
+
assert_equal fixture, Aircraft.find_or_create_by_bts_aircraft_type('103')
|
67
|
+
assert_equal fixture, Aircraft.find_or_create_by_bts_aircraft_type_and_brighter_planet_aircraft_class_code('103', 'SJ')
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_should_not_recognize_bad_dynamic_finders
|
71
|
+
Aircraft.csv_dictionary :bts_aircraft_type, :url => CSV_URL
|
72
|
+
assert_raise NoMethodError do
|
73
|
+
Aircraft.find_or_create_by_foobar('X')
|
74
|
+
end
|
75
|
+
assert_raise NoMethodError do
|
76
|
+
Aircraft.find_or_create_by_foobar_and_id('X', 'Y')
|
77
|
+
end
|
78
|
+
assert_raise NoMethodError do
|
79
|
+
Aircraft.find_or_create_by_foobar_and_bts_aircraft_type('X', 'Y')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CsvDictionaryTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
CsvDictionaryTestHelper.setup_database
|
6
|
+
@dictionary = CsvDictionary.new(:bts_aircraft_type, :url => GDOCS_URL, :sheet => 1)
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
Aircraft.clear_csv_dictionaries
|
11
|
+
CsvDictionaryTestHelper.teardown_database
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_set_key_name
|
15
|
+
assert_equal :bts_aircraft_type, @dictionary.key_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_set_url
|
19
|
+
dictionary = CsvDictionary.new(:bts_aircraft_type, :url => CSV_URL)
|
20
|
+
assert_equal CSV_URL, dictionary.url
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_interpret_gdocs_urls
|
24
|
+
assert_equal GDOCS_URL + '&output=csv&gid=0', @dictionary.send(:interpret_url, @dictionary.url)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_raise_if_gdocs_url_includes_gid
|
28
|
+
assert_raise RuntimeError do
|
29
|
+
CsvDictionary.new(:bts_aircraft_type, :url => GDOCS_URL + '&gid=1')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_should_raise_if_sheet_option_set_on_non_gdocs_url
|
34
|
+
assert_raise RuntimeError do
|
35
|
+
CsvDictionary.new(:bts_aircraft_type, :url => CSV_URL, :sheet => 1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_set_default_sheet
|
40
|
+
assert_equal 0, @dictionary.sheet
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_should_replace_attributes
|
44
|
+
attributes = { :bts_aircraft_type => '103' }
|
45
|
+
@dictionary.expects(:lookup).with('103').returns('SJ')
|
46
|
+
@dictionary.replace_attributes!(attributes)
|
47
|
+
assert_equal({ :brighter_planet_aircraft_class_code => 'SJ' }, attributes)
|
48
|
+
end
|
49
|
+
|
50
|
+
# real http call
|
51
|
+
def test_should_set_value_name_after_dictionary_loaded
|
52
|
+
@dictionary.send(:load_dictionary)
|
53
|
+
assert_equal :brighter_planet_aircraft_class_code, @dictionary.value_name
|
54
|
+
end
|
55
|
+
|
56
|
+
# real http call
|
57
|
+
def test_should_lookup
|
58
|
+
assert_equal 'SJ', @dictionary.lookup('103')
|
59
|
+
end
|
60
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module CsvDictionaryTestHelper
|
2
|
+
VENDOR_RAILS = File.expand_path('../../../../rails', __FILE__)
|
3
|
+
OTHER_RAILS = File.expand_path('../../../rails', __FILE__)
|
4
|
+
PLUGIN_ROOT = File.expand_path('../../', __FILE__)
|
5
|
+
|
6
|
+
def self.rails_directory
|
7
|
+
if File.exist?(VENDOR_RAILS)
|
8
|
+
VENDOR_RAILS
|
9
|
+
elsif File.exist?(OTHER_RAILS)
|
10
|
+
OTHER_RAILS
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load_dependencies
|
15
|
+
if rails_directory
|
16
|
+
$:.unshift(File.join(rails_directory, 'activesupport', 'lib'))
|
17
|
+
$:.unshift(File.join(rails_directory, 'activerecord', 'lib'))
|
18
|
+
else
|
19
|
+
require 'rubygems' rescue LoadError
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'active_record'
|
23
|
+
require 'test/unit'
|
24
|
+
require 'mocha'
|
25
|
+
|
26
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
27
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
28
|
+
require 'csv_dictionary'
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.configure_database
|
32
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
|
33
|
+
ActiveRecord::Migration.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.setup_database
|
37
|
+
ActiveRecord::Schema.define do
|
38
|
+
create_table :aircraft do |t|
|
39
|
+
t.string :brighter_planet_aircraft_class_code
|
40
|
+
t.timestamps
|
41
|
+
end
|
42
|
+
create_table :scrums do |t|
|
43
|
+
t.string :name
|
44
|
+
t.timestamps
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.teardown_database
|
50
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
51
|
+
ActiveRecord::Base.connection.drop_table(table)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.start
|
56
|
+
load_dependencies
|
57
|
+
configure_database
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
CsvDictionaryTestHelper.start
|
62
|
+
|
63
|
+
ActiveSupport::Inflector.inflections do |inflect|
|
64
|
+
inflect.uncountable('aircraft')
|
65
|
+
end
|
66
|
+
|
67
|
+
class Aircraft < ActiveRecord::Base; end
|
68
|
+
class Scrum < ActiveRecord::Base; end
|
69
|
+
|
70
|
+
GDOCS_URL = 'http://spreadsheets.google.com/pub?key=p70r3FHguhimD8YmyA34RdA'
|
71
|
+
CSV_URL = 'http://static.brighterplanet.com/science/data/transport/air/bts_aircraft_types-brighter_planet_aircraft_classes.csv'
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: seamusabshere-csv_dictionary
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Seamus Abshere
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-04-07 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: seamus@abshere.net
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
- Rakefile
|
29
|
+
- lib/csv_dictionary.rb
|
30
|
+
- test/csv_dictionary_ext_test.rb
|
31
|
+
- test/csv_dictionary_test.rb
|
32
|
+
- test/test_helper.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://github.com/seamusabshere/csv_dictionary
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options:
|
37
|
+
- --charset=UTF-8
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
requirements: []
|
53
|
+
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 1.2.0
|
56
|
+
signing_key:
|
57
|
+
specification_version: 2
|
58
|
+
summary: TODO
|
59
|
+
test_files:
|
60
|
+
- test/csv_dictionary_ext_test.rb
|
61
|
+
- test/csv_dictionary_test.rb
|
62
|
+
- test/test_helper.rb
|