activewarehouse-etl 0.9.1 → 0.9.5.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. data/.gitignore +7 -0
  2. data/0.9-UPGRADE +6 -0
  3. data/CHANGELOG +182 -150
  4. data/Gemfile +4 -0
  5. data/HOW_TO_RELEASE +9 -0
  6. data/README +18 -2
  7. data/Rakefile +35 -91
  8. data/active_support_logger.patch +78 -0
  9. data/activewarehouse-etl.gemspec +30 -0
  10. data/lib/etl.rb +10 -2
  11. data/lib/etl/batch/directives.rb +11 -1
  12. data/lib/etl/control/control.rb +2 -2
  13. data/lib/etl/control/destination.rb +27 -7
  14. data/lib/etl/control/destination/database_destination.rb +8 -6
  15. data/lib/etl/control/destination/excel_destination.rb +91 -0
  16. data/lib/etl/control/destination/file_destination.rb +6 -4
  17. data/lib/etl/control/destination/insert_update_database_destination.rb +133 -0
  18. data/lib/etl/control/destination/update_database_destination.rb +109 -0
  19. data/lib/etl/control/source.rb +3 -2
  20. data/lib/etl/control/source/database_source.rb +14 -10
  21. data/lib/etl/control/source/file_source.rb +2 -2
  22. data/lib/etl/engine.rb +17 -15
  23. data/lib/etl/execution.rb +0 -1
  24. data/lib/etl/execution/batch.rb +3 -1
  25. data/lib/etl/execution/migration.rb +5 -0
  26. data/lib/etl/parser/delimited_parser.rb +20 -1
  27. data/lib/etl/parser/excel_parser.rb +112 -0
  28. data/lib/etl/processor/bulk_import_processor.rb +4 -2
  29. data/lib/etl/processor/database_join_processor.rb +68 -0
  30. data/lib/etl/processor/escape_csv_processor.rb +77 -0
  31. data/lib/etl/processor/filter_row_processor.rb +51 -0
  32. data/lib/etl/processor/ftp_downloader_processor.rb +68 -0
  33. data/lib/etl/processor/ftp_uploader_processor.rb +65 -0
  34. data/lib/etl/processor/imapattachment_downloader_processor.rb +91 -0
  35. data/lib/etl/processor/pop3attachment_downloader_processor.rb +90 -0
  36. data/lib/etl/processor/sftp_downloader_processor.rb +63 -0
  37. data/lib/etl/processor/sftp_uploader_processor.rb +63 -0
  38. data/lib/etl/processor/zip_file_processor.rb +27 -0
  39. data/lib/etl/transform/calculation_transform.rb +71 -0
  40. data/lib/etl/transform/foreign_key_lookup_transform.rb +25 -7
  41. data/lib/etl/transform/ordinalize_transform.rb +3 -1
  42. data/lib/etl/transform/split_fields_transform.rb +27 -0
  43. data/lib/etl/version.rb +1 -7
  44. data/test-matrix.yml +10 -0
  45. data/test/.gitignore +1 -0
  46. data/test/.ignore +2 -0
  47. data/test/all.ebf +6 -0
  48. data/test/apache_combined_log.ctl +11 -0
  49. data/test/batch_test.rb +41 -0
  50. data/test/batch_with_error.ebf +6 -0
  51. data/test/batched1.ctl +0 -0
  52. data/test/batched2.ctl +0 -0
  53. data/test/block_processor.ctl +6 -0
  54. data/test/block_processor_error.ctl +1 -0
  55. data/test/block_processor_pre_post_process.ctl +4 -0
  56. data/test/block_processor_remove_rows.ctl +5 -0
  57. data/test/block_processor_test.rb +38 -0
  58. data/test/config/Gemfile.rails-2.3.x +3 -0
  59. data/test/config/Gemfile.rails-2.3.x.lock +38 -0
  60. data/test/config/Gemfile.rails-3.0.x +3 -0
  61. data/test/config/Gemfile.rails-3.0.x.lock +49 -0
  62. data/test/config/common.rb +21 -0
  63. data/test/connection/mysql/connection.rb +9 -0
  64. data/test/connection/mysql/schema.sql +36 -0
  65. data/test/connection/postgresql/connection.rb +13 -0
  66. data/test/connection/postgresql/schema.sql +39 -0
  67. data/test/control_test.rb +43 -0
  68. data/test/data/apache_combined_log.txt +3 -0
  69. data/test/data/bulk_import.txt +3 -0
  70. data/test/data/bulk_import_with_empties.txt +3 -0
  71. data/test/data/decode.txt +3 -0
  72. data/test/data/delimited.txt +3 -0
  73. data/test/data/encode_source_latin1.txt +2 -0
  74. data/test/data/excel.xls +0 -0
  75. data/test/data/excel2.xls +0 -0
  76. data/test/data/fixed_width.txt +3 -0
  77. data/test/data/multiple_delimited_1.txt +3 -0
  78. data/test/data/multiple_delimited_2.txt +3 -0
  79. data/test/data/people.txt +3 -0
  80. data/test/data/sax.xml +14 -0
  81. data/test/data/xml.xml +16 -0
  82. data/test/date_dimension_builder_test.rb +96 -0
  83. data/test/delimited.ctl +30 -0
  84. data/test/delimited_absolute.ctl +33 -0
  85. data/test/delimited_destination_db.ctl +25 -0
  86. data/test/delimited_excel.ctl +31 -0
  87. data/test/delimited_insert_update.ctl +34 -0
  88. data/test/delimited_update.ctl +34 -0
  89. data/test/delimited_with_bulk_load.ctl +34 -0
  90. data/test/destination_test.rb +275 -0
  91. data/test/directive_test.rb +23 -0
  92. data/test/encode_processor_test.rb +32 -0
  93. data/test/engine_test.rb +32 -0
  94. data/test/errors.ctl +24 -0
  95. data/test/etl_test.rb +42 -0
  96. data/test/excel.ctl +24 -0
  97. data/test/excel2.ctl +25 -0
  98. data/test/fixed_width.ctl +35 -0
  99. data/test/generator_test.rb +14 -0
  100. data/test/inline_parser.ctl +17 -0
  101. data/test/mocks/mock_destination.rb +26 -0
  102. data/test/mocks/mock_source.rb +25 -0
  103. data/test/model_source.ctl +14 -0
  104. data/test/multiple_delimited.ctl +22 -0
  105. data/test/multiple_source_delimited.ctl +39 -0
  106. data/test/parser_test.rb +224 -0
  107. data/test/performance/delimited.ctl +30 -0
  108. data/test/processor_test.rb +44 -0
  109. data/test/row_processor_test.rb +17 -0
  110. data/test/sax.ctl +26 -0
  111. data/test/scd/1.txt +1 -0
  112. data/test/scd/2.txt +1 -0
  113. data/test/scd/3.txt +1 -0
  114. data/test/scd_test.rb +257 -0
  115. data/test/scd_test_type_1.ctl +43 -0
  116. data/test/scd_test_type_2.ctl +34 -0
  117. data/test/screen_test.rb +9 -0
  118. data/test/screen_test_error.ctl +3 -0
  119. data/test/screen_test_fatal.ctl +3 -0
  120. data/test/source_test.rb +139 -0
  121. data/test/test_helper.rb +34 -0
  122. data/test/transform_test.rb +101 -0
  123. data/test/vendor/adapter_extensions-0.5.0/CHANGELOG +26 -0
  124. data/test/vendor/adapter_extensions-0.5.0/LICENSE +16 -0
  125. data/test/vendor/adapter_extensions-0.5.0/README +7 -0
  126. data/test/vendor/adapter_extensions-0.5.0/Rakefile +158 -0
  127. data/test/vendor/adapter_extensions-0.5.0/lib/adapter_extensions.rb +12 -0
  128. data/test/vendor/adapter_extensions-0.5.0/lib/adapter_extensions/connection_adapters/abstract_adapter.rb +44 -0
  129. data/test/vendor/adapter_extensions-0.5.0/lib/adapter_extensions/connection_adapters/mysql_adapter.rb +63 -0
  130. data/test/vendor/adapter_extensions-0.5.0/lib/adapter_extensions/connection_adapters/postgresql_adapter.rb +52 -0
  131. data/test/vendor/adapter_extensions-0.5.0/lib/adapter_extensions/connection_adapters/sqlserver_adapter.rb +44 -0
  132. data/test/vendor/adapter_extensions-0.5.0/lib/adapter_extensions/version.rb +10 -0
  133. data/test/xml.ctl +31 -0
  134. metadata +229 -70
  135. data/lib/etl/execution/record.rb +0 -18
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ScreenTest < Test::Unit::TestCase
4
+ def test_screen
5
+ assert_raises(SystemExit) do
6
+ ETL::Engine.process(File.dirname(__FILE__) + '/screen_test_fatal.ctl')
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ screen(:error){
2
+ ETL::Screen::RowCountScreen.new(self, :rows => 1)
3
+ }
@@ -0,0 +1,3 @@
1
+ screen(:fatal){
2
+ ETL::Screen::RowCountScreen.new(self, :rows => 1)
3
+ }
@@ -0,0 +1,139 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class Person < ActiveRecord::Base
4
+ end
5
+ class SourceTest < Test::Unit::TestCase
6
+ context "a file source" do
7
+ context "with delimited data" do
8
+ setup do
9
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/delimited.ctl')
10
+ configuration = {
11
+ :file => 'data/delimited.txt',
12
+ :parser => :delimited
13
+ }
14
+ definition = self.definition + [:sex]
15
+
16
+ source = ETL::Control::FileSource.new(control, configuration, definition)
17
+ @rows = source.collect { |row| row }
18
+ end
19
+ should "find 3 rows in the delimited file" do
20
+ assert_equal 3, @rows.length
21
+ end
22
+ end
23
+ end
24
+
25
+ context "a file source with a glob" do
26
+ setup do
27
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/multiple_delimited.ctl')
28
+ configuration = {
29
+ :file => 'data/multiple_delimited_*.txt',
30
+ :parser => :delimited
31
+ }
32
+
33
+ source = ETL::Control::FileSource.new(control, configuration, definition)
34
+ @rows = source.collect { |row| row }
35
+ end
36
+ should "find 6 rows in total" do
37
+ assert_equal 6, @rows.length
38
+ end
39
+ end
40
+
41
+ context "a file source with an absolute path" do
42
+ setup do
43
+ FileUtils.cp(File.dirname(__FILE__) + '/data/delimited.txt', '/tmp/delimited_abs.txt')
44
+
45
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) +
46
+ '/delimited_absolute.ctl')
47
+ configuration = {
48
+ :file => '/tmp/delimited_abs.txt',
49
+ :parser => :delimited
50
+ }
51
+ definition = self.definition + [:sex]
52
+
53
+ source = ETL::Control::FileSource.new(control, configuration, definition)
54
+ @rows = source.collect { |row| row }
55
+ end
56
+ should "find 3 rows" do
57
+ assert_equal 3, @rows.length
58
+ end
59
+ end
60
+
61
+ context "multiple sources" do
62
+ setup do
63
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) +
64
+ '/multiple_source_delimited.ctl')
65
+ @rows = control.sources.collect { |source| source.collect { |row| row }}.flatten!
66
+ end
67
+ should "find 12 rows" do
68
+ assert_equal 12, @rows.length
69
+ end
70
+ end
71
+
72
+ context "a database source" do
73
+ setup do
74
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/delimited.ctl')
75
+ configuration = {
76
+ :database => 'etl_unittest',
77
+ :target => :operational_database,
78
+ :table => 'people',
79
+ }
80
+ definition = [
81
+ :first_name,
82
+ :last_name,
83
+ :ssn,
84
+ ]
85
+ @source = ETL::Control::DatabaseSource.new(control, configuration, definition)
86
+ end
87
+ should "set the local file for extraction storage" do
88
+ assert_match %r{source_data/localhost/etl_unittest/people/\d+.csv}, @source.local_file.to_s
89
+ end
90
+ should "find 1 row" do
91
+ Person.delete_all
92
+ assert_equal 0, Person.count
93
+ Person.create!(:first_name => 'Bob', :last_name => 'Smith', :ssn => '123456789')
94
+ assert_equal 1, Person.count
95
+ rows = @source.collect { |row| row }
96
+ assert_equal 1, rows.length
97
+ end
98
+ end
99
+
100
+ context "a file source with an xml parser" do
101
+ setup do
102
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) +
103
+ '/xml.ctl')
104
+ @rows = control.sources.collect{ |source| source.collect { |row| row }}.flatten!
105
+ end
106
+ should "find 2 rows" do
107
+ assert_equal 2, @rows.length
108
+ end
109
+ end
110
+
111
+ context "a model source" do
112
+ setup do
113
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/model_source.ctl')
114
+ configuration = {
115
+
116
+ }
117
+ definition = [
118
+ :first_name,
119
+ :last_name,
120
+ :ssn
121
+ ]
122
+ end
123
+ should_eventually "find n rows" do
124
+
125
+ end
126
+ end
127
+
128
+ def definition
129
+ [
130
+ :first_name,
131
+ :last_name,
132
+ :ssn,
133
+ {
134
+ :name => :age,
135
+ :type => :integer
136
+ }
137
+ ]
138
+ end
139
+ end
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
5
+ $:.unshift(File.dirname(__FILE__))
6
+
7
+ Dir[File.dirname(__FILE__) + "/vendor/**/lib"].each { |lib| $:.unshift(lib) }
8
+
9
+ require 'test/unit'
10
+ require 'pp'
11
+ require 'etl'
12
+ require 'shoulda'
13
+ require 'flexmock/test_unit'
14
+
15
+ ETL::Engine.init(:config => File.dirname(__FILE__) + '/config/database.yml')
16
+ ETL::Engine.logger = Logger.new(STDOUT)
17
+ # ETL::Engine.logger.level = Logger::DEBUG
18
+ ETL::Engine.logger.level = Logger::FATAL
19
+
20
+ db = ENV['DB'] ||= 'mysql'
21
+ require "connection/#{db}/connection"
22
+ ActiveRecord::Base.establish_connection :operational_database
23
+ ETL::Execution::Job.delete_all
24
+
25
+ require 'mocks/mock_source'
26
+ require 'mocks/mock_destination'
27
+
28
+ # shortcut to launch a ctl file
29
+ def process(file)
30
+ Engine.process(File.join(File.dirname(__FILE__), file))
31
+ end
32
+
33
+ puts "ActiveRecord::VERSION = #{ActiveRecord::VERSION::STRING}"
34
+
@@ -0,0 +1,101 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class MyResolver
4
+ def resolve(value)
5
+ 4
6
+ end
7
+ end
8
+
9
+ class TransformTest < Test::Unit::TestCase
10
+ def test_sha1_transform
11
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/delimited.ctl')
12
+ digest_value = 'a9993e364706816aba3e25717850c26c9cd0d89d'
13
+ assert_equal digest_value, ETL::Transform::Sha1Transform.new(
14
+ control, nil
15
+ ).transform('test', 'abc', [])
16
+ end
17
+ def test_block_transform
18
+ #transforms = [Proc.new(){|name, value, row| value[0,2]}]
19
+ #assert_equal '11', ETL::Transform::Transform.transform(:ssn, '1111223333', [], transforms)
20
+ end
21
+ def test_decode_transform
22
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/delimited.ctl')
23
+ configuration = {:decode_table_path => 'data/decode.txt'}
24
+
25
+ t = ETL::Transform::DecodeTransform.new(control, nil, configuration)
26
+
27
+ assert_equal 'Male', t.transform(nil, 'M', [])
28
+ assert_equal 'Female', t.transform(nil, 'F', [])
29
+ assert_equal 'Unknown', t.transform(nil, '', [])
30
+ assert_equal 'Unknown', t.transform(nil, 'blah', [])
31
+ end
32
+ def test_string_to_date_transform
33
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/delimited.ctl')
34
+ t = ETL::Transform::StringToDateTransform.new(control, nil)
35
+
36
+ assert_equal Date.parse('2005-01-01'), t.transform(nil, '2005-01-01', [])
37
+ assert_equal Date.parse('2004-10-20 20:30:00'), t.transform(nil, '2004-10-20', [])
38
+ end
39
+ def test_date_to_string_transform
40
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/delimited.ctl')
41
+ t = ETL::Transform::DateToStringTransform.new(control, nil)
42
+
43
+ d1 = Date.parse('2005-01-01')
44
+ t1 = Time.parse('2004-10-20 23:03:23')
45
+ assert_equal '2005-01-01', t.transform(nil, d1, [])
46
+ assert_equal '2004-10-20', t.transform(nil, t1, [])
47
+
48
+ t = ETL::Transform::DateToStringTransform.new(control, nil, {:format => '%m/%d/%Y'})
49
+
50
+ assert_equal '01/01/2005', t.transform(nil, d1, [])
51
+ assert_equal '10/20/2004', t.transform(nil, t1, [])
52
+ end
53
+ def test_string_to_datetime_transform
54
+ v = '1/1/1900 04:34:30'
55
+ t = ETL::Transform::StringToDateTimeTransform.new(flexmock(:control), nil)
56
+ assert_equal DateTime.parse(v), t.transform(nil, v, nil)
57
+ end
58
+ def test_foreign_key_lookup_transform
59
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/delimited.ctl')
60
+ configuration = {:collection => {'foo' => 1, 'bar' => 2, 'baz' => 3}}
61
+ t = ETL::Transform::ForeignKeyLookupTransform.new(control, nil, configuration)
62
+
63
+ assert_equal 1, t.transform(nil, 'foo', nil)
64
+ assert_equal 2, t.transform(nil, 'bar', nil)
65
+ assert_equal 3, t.transform(nil, 'baz', nil)
66
+ assert_raises(ETL::ResolverError, 'Foreign key for bing not found and no resolver specified') do
67
+ assert_equal 4, t.transform(nil, 'bing', nil)
68
+ end
69
+
70
+ configuration = {:collection => {'foo' => 1, 'bar' => 2, 'baz' => 3}, :resolver => MyResolver}
71
+ t = ETL::Transform::ForeignKeyLookupTransform.new(control, nil, configuration)
72
+ assert_equal 1, t.transform(nil, 'foo', nil)
73
+ assert_equal 2, t.transform(nil, 'bar', nil)
74
+ assert_equal 3, t.transform(nil, 'baz', nil)
75
+ assert_equal 4, t.transform(nil, 'bing', nil)
76
+ end
77
+ def test_type_transform
78
+ control = ETL::Control::Control.parse(File.dirname(__FILE__) + '/delimited.ctl')
79
+ assert_equal 10, ETL::Transform::TypeTransform.new(control, nil, {:type => :number}).transform(nil, '10', nil)
80
+
81
+ assert_equal BigDecimal::ROUND_HALF_UP, BigDecimal.mode(BigDecimal::ROUND_MODE)
82
+ decimal_transformed = ETL::Transform::TypeTransform.new(
83
+ control, nil, {:type => :decimal, :scale => 4}
84
+ ).transform(nil, '10.0000000000000000000000000000000001', nil)
85
+ assert_equal '10.0000000000000000000000000000000001', decimal_transformed.to_s('F')
86
+ end
87
+ def test_non_existent_transformer
88
+
89
+ end
90
+ def test_default_transform
91
+ t = ETL::Transform::DefaultTransform.new(flexmock('control'), nil, {:default_value => 'foo'})
92
+ assert_equal 'foo', t.transform(nil, '', nil)
93
+ assert_equal 'foo', t.transform(nil, nil, nil)
94
+ assert_equal 'bar', t.transform(nil, 'bar', nil)
95
+ end
96
+ def test_ordinalize_transform
97
+ t = ETL::Transform::OrdinalizeTransform.new(flexmock('control'), nil, {})
98
+ assert_equal '1st', t.transform(nil, 1, nil)
99
+ assert_equal '10th', t.transform(nil, 10, nil)
100
+ end
101
+ end
@@ -0,0 +1,26 @@
1
+ 0.1.0 - March 5, 2007
2
+ * Initial release
3
+
4
+ 0.1.1 - March 5, 2007
5
+ * Bug fixes
6
+
7
+ 0.1.2 - March 5, 2007
8
+ * Bug fixes
9
+
10
+ 0.2.0 - March 6, 2007
11
+ * SQL Server adapter included (Seth Ladd)
12
+
13
+ 0.3.0 - March 8, 2007
14
+ * PostgreSQL adapter included
15
+ * Added tests for bulk loading
16
+ * bulk_load method now handles table missing and file missing as error cases
17
+
18
+ 0.3.1 - May 4, 2007
19
+ * Added support for modifying SELECT statements to add an INSERT INTO.
20
+
21
+ 0.4 - September 17, 2007
22
+ * Added copy_table method that can copy the structure and data from one table to another. Currently implemented in MySQL (tested), PostgreSQL (tested) and SQL Server adapters (untested).
23
+ * Added support for SELECT..INTO for PostgreSQL.
24
+
25
+ 0.5 -
26
+ * Updated dependencies for gem to current versions of ActiveRecord, ActiveSupport and Rake. May not be compatible with Rails versions less than 2.x.
@@ -0,0 +1,16 @@
1
+ Copyright (c) 2007 Anthony Eden
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4
+ associated documentation files (the "Software"), to deal in the Software without restriction, including
5
+ without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6
+ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
7
+ following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial
10
+ portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
13
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
14
+ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
15
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
16
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ This library provides extensions to Rails' ActiveRecord adapters.
2
+
3
+ As of version 0.5, adapter_extensions has dependencies on ActiveSupport and ActiveRecord 2.1.x or higher.
4
+
5
+ To use the MySQL adapter extensions with Rails 2.x, you must patch the mysql_adapter with the mysql_adapter_opt_local_infile.patch.
6
+
7
+ To execute the unit tests you must first construct a adapter_extensions_unittest database.
@@ -0,0 +1,158 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/packagetask'
5
+ require 'rake/gempackagetask'
6
+ require 'rake/contrib/rubyforgepublisher'
7
+ require 'date'
8
+
9
+ require File.join(File.dirname(__FILE__), 'lib/adapter_extensions', 'version')
10
+
11
+ PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
12
+ PKG_NAME = 'adapter_extensions'
13
+ PKG_VERSION = AdapterExtensions::VERSION::STRING + PKG_BUILD
14
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
15
+ PKG_DESTINATION = ENV["PKG_DESTINATION"] || "../#{PKG_NAME}"
16
+
17
+ RELEASE_NAME = "REL #{PKG_VERSION}"
18
+
19
+ RUBY_FORGE_PROJECT = "activewarehouse"
20
+ RUBY_FORGE_USER = "aeden"
21
+
22
+ desc 'Default: run unit tests.'
23
+ task :default => :test
24
+
25
+ desc 'Test the ETL application.'
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = true
30
+ # TODO: reset the database
31
+ end
32
+
33
+ namespace :rcov do
34
+ desc 'Measures test coverage'
35
+ task :test do
36
+ rm_f 'coverage.data'
37
+ mkdir 'coverage' unless File.exist?('coverage')
38
+ rcov = "rcov --aggregate coverage.data --text-summary -Ilib"
39
+ system("#{rcov} test/*_test.rb test/**/*_test.rb")
40
+ system("open coverage/index.html") if PLATFORM['darwin']
41
+ end
42
+ end
43
+
44
+ desc 'Generate documentation for the AdapterExtensions library.'
45
+ Rake::RDocTask.new(:rdoc) do |rdoc|
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = 'Extensions for Rails adapters'
48
+ rdoc.options << '--line-numbers' << '--inline-source'
49
+ rdoc.rdoc_files.include('README')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
52
+
53
+ PKG_FILES = FileList[
54
+ 'CHANGELOG',
55
+ 'README',
56
+ 'LICENSE',
57
+ 'Rakefile',
58
+ 'doc/**/*',
59
+ 'lib/**/*',
60
+ ] - [ 'test' ]
61
+
62
+ spec = Gem::Specification.new do |s|
63
+ s.name = 'adapter_extensions'
64
+ s.version = PKG_VERSION
65
+ s.summary = "Extensions to Rails ActiveRecord adapters."
66
+ s.description = <<-EOF
67
+ Provides various extensions to the Rails ActiveRecord adapters.
68
+ EOF
69
+
70
+ s.add_dependency('rake', '>= 0.8.3')
71
+ s.add_dependency('activesupport', '>= 2.1.0')
72
+ s.add_dependency('activerecord', '>= 2.1.0')
73
+ s.add_dependency('fastercsv', '>= 1.0.0')
74
+
75
+ s.rdoc_options << '--exclude' << '.'
76
+ s.has_rdoc = false
77
+
78
+ s.files = PKG_FILES.to_a.delete_if {|f| f.include?('.svn')}
79
+ s.require_path = 'lib'
80
+
81
+ s.author = "Anthony Eden"
82
+ s.email = "anthonyeden@gmail.com"
83
+ s.homepage = "http://activewarehouse.rubyforge.org/adapter_extensions"
84
+ s.rubyforge_project = "activewarehouse"
85
+ end
86
+
87
+ Rake::GemPackageTask.new(spec) do |pkg|
88
+ pkg.gem_spec = spec
89
+ pkg.need_tar = true
90
+ pkg.need_zip = true
91
+ end
92
+
93
+ namespace :github do
94
+ desc "Update Github Gemspec"
95
+ task :update_gemspec do
96
+ File.open(File.join(File.dirname(__FILE__), "#{spec.name}.gemspec"), "w"){|f| f << spec.to_ruby}
97
+ end
98
+ end
99
+
100
+
101
+
102
+ desc "Generate code statistics"
103
+ task :lines do
104
+ lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
105
+
106
+ for file_name in FileList["lib/**/*.rb"]
107
+ next if file_name =~ /vendor/
108
+ f = File.open(file_name)
109
+
110
+ while line = f.gets
111
+ lines += 1
112
+ next if line =~ /^\s*$/
113
+ next if line =~ /^\s*#/
114
+ codelines += 1
115
+ end
116
+ puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
117
+
118
+ total_lines += lines
119
+ total_codelines += codelines
120
+
121
+ lines, codelines = 0, 0
122
+ end
123
+
124
+ puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
125
+ end
126
+
127
+ desc "Publish the release files to RubyForge."
128
+ task :release => [ :package ] do
129
+ `rubyforge login`
130
+
131
+ for ext in %w( gem tgz zip )
132
+ release_command = "rubyforge add_release activewarehouse #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}"
133
+ puts release_command
134
+ system(release_command)
135
+ end
136
+ end
137
+
138
+ desc "Publish the API documentation"
139
+ task :pdoc => [:rdoc] do
140
+ Rake::SshDirPublisher.new("aeden@rubyforge.org", "/var/www/gforge-projects/activewarehouse/adapter_extensions/rdoc", "rdoc").upload
141
+ end
142
+
143
+ desc "Install the gem from a local generated package"
144
+ task :install => [:package] do
145
+ windows = RUBY_PLATFORM =~ /mswin/
146
+ sudo = windows ? '' : 'sudo'
147
+ gem = windows ? 'gem.bat' : 'gem'
148
+ `#{sudo} #{gem} install pkg/#{PKG_NAME}-#{PKG_VERSION}`
149
+ end
150
+
151
+ desc "Reinstall the gem from a local package copy"
152
+ task :reinstall => [:package] do
153
+ windows = RUBY_PLATFORM =~ /mswin/
154
+ sudo = windows ? '' : 'sudo'
155
+ gem = windows ? 'gem.bat' : 'gem'
156
+ `#{sudo} #{gem} uninstall #{PKG_NAME} -x`
157
+ `#{sudo} #{gem} install pkg/#{PKG_NAME}-#{PKG_VERSION}`
158
+ end