seamusabshere-gdocs_bootstrap 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 +44 -0
- data/Rakefile +56 -0
- data/VERSION.yml +4 -0
- data/lib/gdocs_bootstrap.rb +92 -0
- data/test/gdocs_bootstrap_ext_test.rb +34 -0
- data/test/gdocs_bootstrap_test.rb +31 -0
- data/test/test_helper.rb +65 -0
- metadata +63 -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
@@ -0,0 +1,44 @@
|
|
1
|
+
= gdocs_bootstrap
|
2
|
+
|
3
|
+
<tt>
|
4
|
+
class FuelType
|
5
|
+
gdoc_bootstrap :url => 'http://spreadsheets.google.com/pub?key=p70r3FHguhimIdBKyVz3iPA&output=csv&gid=0'
|
6
|
+
end
|
7
|
+
</tt>
|
8
|
+
|
9
|
+
This lets you bootstrap your ActiveRecord models with Google Docs spreadsheets.
|
10
|
+
|
11
|
+
<tt>
|
12
|
+
>> FuelType.bootstrap!
|
13
|
+
=> true
|
14
|
+
</tt>
|
15
|
+
|
16
|
+
== Spreadsheet structure
|
17
|
+
|
18
|
+
The first column is always the key.
|
19
|
+
|
20
|
+
All of the other columns will be included as attributes, based on the column headers.
|
21
|
+
|
22
|
+
<tt>
|
23
|
+
name emission_factor units
|
24
|
+
coal 5246.89 lbs/short ton
|
25
|
+
natural gas 1.25 pounds / therm (nat gas)
|
26
|
+
fuel oil 22.51 lbs/gallon
|
27
|
+
</tt>
|
28
|
+
|
29
|
+
would generate
|
30
|
+
|
31
|
+
<tt>
|
32
|
+
a = FuelType.find_or_create_by_name('coal')
|
33
|
+
a.update_attributes(:name => 'coal', :emission_factor => '5246.89', :units => 'lbs/short ton')
|
34
|
+
|
35
|
+
a = FuelType.find_or_create_by_name('natural gas')
|
36
|
+
a.update_attributes(:name => 'coal', :emission_factor => '1.25', :units => 'pounds / therm (nat gas)')
|
37
|
+
|
38
|
+
a = FuelType.find_or_create_by_name('fuel oil')
|
39
|
+
a.update_attributes(:name => 'coal', :emission_factor => '22.51', :units => 'lbs/gallon')
|
40
|
+
</tt>
|
41
|
+
|
42
|
+
== Copyright
|
43
|
+
|
44
|
+
Copyright (c) 2009 Seamus Abshere. See LICENSE for details.
|
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 = "gdocs_bootstrap"
|
8
|
+
gem.summary = %Q{TODO}
|
9
|
+
gem.email = "seamus@abshere.net"
|
10
|
+
gem.homepage = "http://github.com/seamusabshere/gdocs_bootstrap"
|
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 = "gdocs_bootstrap #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
56
|
+
|
data/VERSION.yml
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fastercsv'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'active_support'
|
5
|
+
|
6
|
+
class GdocsBootstrap
|
7
|
+
attr_accessor :url, :target_class_name, :key_sprintf # set in options
|
8
|
+
attr_accessor :key_name, :headers, :dictionary, :width
|
9
|
+
|
10
|
+
def bootstrap!
|
11
|
+
load_dictionary unless dictionary_loaded?
|
12
|
+
dictionary.each do |k, v|
|
13
|
+
instance_of_target_class = target_class.send("find_or_create_by_#{key_name}", v[key_name])
|
14
|
+
instance_of_target_class.update_attributes(v.except(key_name))
|
15
|
+
end
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def initialize(options = {})
|
22
|
+
@url = options[:url]
|
23
|
+
@target_class_name = options[:target_class_name]
|
24
|
+
@key_sprintf = options[:key_sprintf] || '%s'
|
25
|
+
end
|
26
|
+
|
27
|
+
def dictionary_loaded?
|
28
|
+
!dictionary.nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_dictionary
|
32
|
+
self.dictionary = {}
|
33
|
+
open(url) do |data|
|
34
|
+
FasterCSV.parse(data, :headers => :first_row) do |row|
|
35
|
+
self.width ||= row.fields.size
|
36
|
+
self.key_name ||= row.headers[0].to_sym
|
37
|
+
self.headers ||= row.headers
|
38
|
+
next if row.fields[0].blank?
|
39
|
+
key = interpret_key(row.fields[0])
|
40
|
+
dictionary[key] = interpret_columns(row.fields[0..width])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def interpret_key(k)
|
46
|
+
k = k.to_s.strip
|
47
|
+
k = k.to_i if /\%[0-9\.]*d/.match(key_sprintf)
|
48
|
+
key_sprintf % k
|
49
|
+
end
|
50
|
+
|
51
|
+
def interpret_columns(columns)
|
52
|
+
memo = {}
|
53
|
+
columns.each_with_index do |column, index|
|
54
|
+
# puts "memo.merge!(headers[#{index}].to_sym => column) as memo.merge!(#{headers[index].to_sym} => #{column})"
|
55
|
+
memo.merge!(headers[index].to_sym => column)
|
56
|
+
end
|
57
|
+
memo
|
58
|
+
end
|
59
|
+
|
60
|
+
def target_class
|
61
|
+
target_class_name.constantize
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module ActiveRecord
|
66
|
+
module GdocsBootstrapExt
|
67
|
+
def self.included(klass)
|
68
|
+
klass.class_eval do
|
69
|
+
self.class_inheritable_accessor :gdocs_bootstraps
|
70
|
+
extend ClassMethods
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
module ClassMethods
|
75
|
+
def gdocs_bootstrap(options = {})
|
76
|
+
self.gdocs_bootstraps ||= []
|
77
|
+
options[:target_class_name] ||= self.class_name
|
78
|
+
gdocs_bootstraps << GdocsBootstrap.new(options)
|
79
|
+
end
|
80
|
+
|
81
|
+
def clear_bootstraps
|
82
|
+
self.gdocs_bootstraps = []
|
83
|
+
end
|
84
|
+
|
85
|
+
def bootstrap!
|
86
|
+
gdocs_bootstraps.each { |b| b.bootstrap! }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
ActiveRecord::Base.send :include, ActiveRecord::GdocsBootstrapExt
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class GdocsBootstrapExtTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
GdocsBootstrapTestHelper::Initializer.setup_database
|
6
|
+
end
|
7
|
+
|
8
|
+
def teardown
|
9
|
+
Scrum.clear_bootstraps
|
10
|
+
GdocsBootstrapTestHelper::Initializer.teardown_database
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_mixin_methods
|
14
|
+
assert Scrum.respond_to?(:gdocs_bootstrap)
|
15
|
+
assert Scrum.respond_to?(:clear_bootstraps)
|
16
|
+
assert Scrum.respond_to?(:bootstrap!)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_set_target_class
|
20
|
+
GdocsBootstrap.expects(:new).with(:target_class_name => 'Scrum')
|
21
|
+
Scrum.gdocs_bootstrap
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_set_url
|
25
|
+
GdocsBootstrap.expects(:new).with(:target_class_name => 'Scrum', :url => GOOGLE_DOC_URL)
|
26
|
+
Scrum.gdocs_bootstrap :url => GOOGLE_DOC_URL
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_should_bootstrap
|
30
|
+
Scrum.gdocs_bootstrap :url => GOOGLE_DOC_URL
|
31
|
+
GdocsBootstrap.any_instance.expects(:bootstrap!)
|
32
|
+
Scrum.bootstrap!
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class GdocsBootstrapTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
GdocsBootstrapTestHelper::Initializer.setup_database
|
6
|
+
@bootstrap = GdocsBootstrap.new(:target_class_name => 'Scrum', :url => GOOGLE_DOC_URL)
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
Scrum.clear_bootstraps
|
11
|
+
GdocsBootstrapTestHelper::Initializer.teardown_database
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_have_url
|
15
|
+
assert_equal @bootstrap.url, GOOGLE_DOC_URL
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_have_target_class_name
|
19
|
+
assert_equal @bootstrap.target_class_name, 'Scrum'
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_bootstrap_keys
|
23
|
+
Scrum.expects(:find_or_create_by_name).at_least_once.returns(Scrum.new)
|
24
|
+
@bootstrap.bootstrap!
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_bootstrap_values
|
28
|
+
Scrum.any_instance.expects(:update_attributes).at_least_once
|
29
|
+
@bootstrap.bootstrap!
|
30
|
+
end
|
31
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module GdocsBootstrapTestHelper
|
2
|
+
module Initializer
|
3
|
+
VENDOR_RAILS = File.expand_path('../../../../rails', __FILE__)
|
4
|
+
OTHER_RAILS = File.expand_path('../../../rails', __FILE__)
|
5
|
+
PLUGIN_ROOT = File.expand_path('../../', __FILE__)
|
6
|
+
|
7
|
+
def self.rails_directory
|
8
|
+
if File.exist?(VENDOR_RAILS)
|
9
|
+
VENDOR_RAILS
|
10
|
+
elsif File.exist?(OTHER_RAILS)
|
11
|
+
OTHER_RAILS
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.load_dependencies
|
16
|
+
if rails_directory
|
17
|
+
$:.unshift(File.join(rails_directory, 'activesupport', 'lib'))
|
18
|
+
$:.unshift(File.join(rails_directory, 'activerecord', 'lib'))
|
19
|
+
else
|
20
|
+
require 'rubygems' rescue LoadError
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'active_record'
|
24
|
+
require 'test/unit'
|
25
|
+
require 'mocha'
|
26
|
+
|
27
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
28
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
29
|
+
require 'gdocs_bootstrap'
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.configure_database
|
33
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
|
34
|
+
ActiveRecord::Migration.verbose = false
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.setup_database
|
38
|
+
ActiveRecord::Schema.define do
|
39
|
+
create_table :scrums do |t|
|
40
|
+
t.string :name
|
41
|
+
t.string :emission_factor
|
42
|
+
t.string :units
|
43
|
+
t.timestamps
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.teardown_database
|
49
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
50
|
+
ActiveRecord::Base.connection.drop_table(table)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.start
|
55
|
+
load_dependencies
|
56
|
+
configure_database
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
GdocsBootstrapTestHelper::Initializer.start
|
62
|
+
|
63
|
+
class Scrum < ActiveRecord::Base; end
|
64
|
+
|
65
|
+
GOOGLE_DOC_URL = 'http://spreadsheets.google.com/pub?key=p70r3FHguhimIdBKyVz3iPA&output=csv&gid=0'
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: seamusabshere-gdocs_bootstrap
|
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
|
+
- VERSION.yml
|
30
|
+
- lib/gdocs_bootstrap.rb
|
31
|
+
- test/gdocs_bootstrap_ext_test.rb
|
32
|
+
- test/gdocs_bootstrap_test.rb
|
33
|
+
- test/test_helper.rb
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.com/seamusabshere/gdocs_bootstrap
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options:
|
38
|
+
- --charset=UTF-8
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
version:
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
requirements: []
|
54
|
+
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.2.0
|
57
|
+
signing_key:
|
58
|
+
specification_version: 2
|
59
|
+
summary: TODO
|
60
|
+
test_files:
|
61
|
+
- test/gdocs_bootstrap_ext_test.rb
|
62
|
+
- test/gdocs_bootstrap_test.rb
|
63
|
+
- test/test_helper.rb
|