slacker 1.0.14 → 1.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -4
- data/README.markdown +22 -22
- data/Rakefile +11 -11
- data/bin/slacker +32 -32
- data/bin/slacker_new +34 -34
- data/lib/slacker.rb +180 -175
- data/lib/slacker/application.rb +224 -214
- data/lib/slacker/command_line_formatter.rb +61 -61
- data/lib/slacker/configuration.rb +59 -59
- data/lib/slacker/formatter.rb +14 -14
- data/lib/slacker/query_result_matcher.rb +178 -178
- data/lib/slacker/rspec_ext.rb +57 -57
- data/lib/slacker/rspec_monkey.rb +7 -7
- data/lib/slacker/sql.rb +39 -39
- data/lib/slacker/sql_preprocessor.rb +23 -23
- data/lib/slacker/string_helper.rb +16 -16
- data/lib/slacker/version.rb +3 -3
- data/lib/slacker_new/project/data/sample_1/my_table_expected_power_results.csv +11 -11
- data/lib/slacker_new/project/data/sample_1/my_table_initial_data.csv +11 -11
- data/lib/slacker_new/project/data/sample_1/numbers_expected_output.csv +3 -3
- data/lib/slacker_new/project/database.yml +9 -9
- data/lib/slacker_new/project/lib/helpers/my_helper.rb +1 -1
- data/lib/slacker_new/project/spec/sample_1.rb +66 -66
- data/lib/slacker_new/project/sql/sample_1/my_table_on_power.sql.erb +1 -1
- data/lib/slacker_new/project/sql/sample_1/play_with_numbers.sql.erb +16 -16
- data/lib/slacker_new/project/sql/sample_1/sysobjects_with_params.sql.erb +1 -1
- data/slacker.gemspec +27 -27
- data/spec/application_spec.rb +13 -13
- data/spec/query_result_matcher_spec.rb +268 -268
- data/spec/rspec_ext_spec.rb +87 -87
- data/spec/slacker_spec.rb +59 -59
- data/spec/spec_helper.rb +19 -9
- data/spec/test_files/matcher/test_1.csv +3 -3
- data/spec/test_files/test_slacker_project/data/test_1.csv +3 -3
- data/spec/test_files/test_slacker_project/sql/nest/nested_1.sql.erb +1 -1
- data/spec/test_files/test_slacker_project/sql/no_params.sql.erb +2 -2
- data/spec/test_files/test_slacker_project/sql/params.sql.erb +1 -1
- metadata +24 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a49d641b5a1472c597ad1d9e43cd77d5123b8ff
|
4
|
+
data.tar.gz: 155efc3e2c4a0edf77d068bc0671cd4426b98c80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cd59135f982ce7e95a99c4aba462dbb494e06414d8cb8c3e98e2c935fbd65272ab365bc4f3a52df985bf8f97bf318db6442482cb8692dfe24ca93904502f56c
|
7
|
+
data.tar.gz: 4be6cfd40fce2b90c6a51759ec1e302473a9688e86c77ccb37a1e176c83c8ba6fc06a7fbd4f2a62539bc3bf2f5a4decc81ad3413a78c0ceb88b2bfa2515bdc1e
|
data/Gemfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
source "http://rubygems.org"
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in slacker.gemspec
|
4
|
-
gemspec
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in slacker.gemspec
|
4
|
+
gemspec
|
data/README.markdown
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
# Slacker
|
2
|
-
|
3
|
-
Behavior Driven Development for SQL Server
|
4
|
-
|
5
|
-
Slacker is a transacted RSpec-based framework for developing automated tests for SQL Server 2005-2014 programmable objects such as stored procedures, scalar/table functions, triggers, etc.
|
6
|
-
|
7
|
-
# Resources
|
8
|
-
|
9
|
-
* [__Documentation__](https://github.com/vassilvk/slacker/wiki)
|
10
|
-
* [__Mailing List__](https://groups.google.com/forum/#!forum/ruby_slacker)
|
11
|
-
|
12
|
-
|
13
|
-
# LICENSE
|
14
|
-
(The MIT License)
|
15
|
-
|
16
|
-
Copyright (c) Vassil Kovatchev
|
17
|
-
|
18
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
19
|
-
|
20
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
21
|
-
|
22
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
|
+
# Slacker
|
2
|
+
|
3
|
+
Behavior Driven Development for SQL Server
|
4
|
+
|
5
|
+
Slacker is a transacted RSpec-based framework for developing automated tests for SQL Server 2005-2014 programmable objects such as stored procedures, scalar/table functions, triggers, etc.
|
6
|
+
|
7
|
+
# Resources
|
8
|
+
|
9
|
+
* [__Documentation__](https://github.com/vassilvk/slacker/wiki)
|
10
|
+
* [__Mailing List__](https://groups.google.com/forum/#!forum/ruby_slacker)
|
11
|
+
|
12
|
+
|
13
|
+
# LICENSE
|
14
|
+
(The MIT License)
|
15
|
+
|
16
|
+
Copyright (c) Vassil Kovatchev
|
17
|
+
|
18
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
19
|
+
|
20
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
21
|
+
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake'
|
3
|
-
require 'rake/clean'
|
4
|
-
require 'rubygems/package_task'
|
5
|
-
require 'bundler/gem_tasks'
|
6
|
-
require 'rspec/core/rake_task'
|
7
|
-
|
8
|
-
RSpec::Core::RakeTask.new do |t|
|
9
|
-
t.fail_on_error = false
|
10
|
-
t.pattern = 'spec/**/*.rb'
|
11
|
-
end
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rubygems/package_task'
|
5
|
+
require 'bundler/gem_tasks'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
RSpec::Core::RakeTask.new do |t|
|
9
|
+
t.fail_on_error = false
|
10
|
+
t.pattern = 'spec/**/*.rb'
|
11
|
+
end
|
data/bin/slacker
CHANGED
@@ -1,32 +1,32 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'slacker'
|
4
|
-
require 'yaml'
|
5
|
-
require 'slacker/command_line_formatter'
|
6
|
-
|
7
|
-
def db_config_from_file(file_path)
|
8
|
-
dbconfig = nil
|
9
|
-
File.open(file_path) do |dbconfig_file|
|
10
|
-
dbconfig = YAML::load(dbconfig_file)
|
11
|
-
end
|
12
|
-
dbconfig
|
13
|
-
end
|
14
|
-
|
15
|
-
# Preset the application to run on the console
|
16
|
-
Slacker.configure do |config|
|
17
|
-
config.console_enabled = true
|
18
|
-
|
19
|
-
# Setup the target connection based on the contents in database.yml
|
20
|
-
db_config = db_config_from_file(config.expand_path('database.yml'))
|
21
|
-
|
22
|
-
config.db_server = db_config["server"]
|
23
|
-
config.db_name = db_config["database"]
|
24
|
-
config.db_user = db_config["user"]
|
25
|
-
config.db_password = db_config["password"]
|
26
|
-
end
|
27
|
-
|
28
|
-
if Slacker.application.run
|
29
|
-
exit(0)
|
30
|
-
else
|
31
|
-
exit(1)
|
32
|
-
end
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'slacker'
|
4
|
+
require 'yaml'
|
5
|
+
require 'slacker/command_line_formatter'
|
6
|
+
|
7
|
+
def db_config_from_file(file_path)
|
8
|
+
dbconfig = nil
|
9
|
+
File.open(file_path) do |dbconfig_file|
|
10
|
+
dbconfig = YAML::load(dbconfig_file)
|
11
|
+
end
|
12
|
+
dbconfig
|
13
|
+
end
|
14
|
+
|
15
|
+
# Preset the application to run on the console
|
16
|
+
Slacker.configure do |config|
|
17
|
+
config.console_enabled = true
|
18
|
+
|
19
|
+
# Setup the target connection based on the contents in database.yml
|
20
|
+
db_config = db_config_from_file(config.expand_path('database.yml'))
|
21
|
+
|
22
|
+
config.db_server = db_config["server"]
|
23
|
+
config.db_name = db_config["database"]
|
24
|
+
config.db_user = db_config["user"]
|
25
|
+
config.db_password = db_config["password"]
|
26
|
+
end
|
27
|
+
|
28
|
+
if Slacker.application.run
|
29
|
+
exit(0)
|
30
|
+
else
|
31
|
+
exit(1)
|
32
|
+
end
|
data/bin/slacker_new
CHANGED
@@ -1,34 +1,34 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'fileutils'
|
4
|
-
|
5
|
-
def usage
|
6
|
-
<<END
|
7
|
-
Use slacker_new to create a new Slacker project:
|
8
|
-
|
9
|
-
slacker_new <project_name>
|
10
|
-
END
|
11
|
-
end
|
12
|
-
|
13
|
-
def project_template_path
|
14
|
-
File.expand_path("#{File.dirname(__FILE__)}/../lib/slacker_new/project")
|
15
|
-
end
|
16
|
-
|
17
|
-
def slacker_new(project_name)
|
18
|
-
files = Dir.glob("#{project_template_path}/**")
|
19
|
-
FileUtils.mkdir(project_name) unless File.exist?(project_name)
|
20
|
-
FileUtils.cp_r(files, project_name)
|
21
|
-
end
|
22
|
-
|
23
|
-
def project_template_files(project_name)
|
24
|
-
files = Dir.glob("#{project_template_path}/**/*").map{|file| file.gsub(/^#{Regexp.escape(project_template_path)}\//, "./#{project_name}/")}
|
25
|
-
end
|
26
|
-
|
27
|
-
if ARGV.count != 1
|
28
|
-
puts usage
|
29
|
-
else
|
30
|
-
project_name = ARGV[0]
|
31
|
-
puts "Creating project #{project_name}..."
|
32
|
-
slacker_new(project_name)
|
33
|
-
puts project_template_files(project_name)
|
34
|
-
end
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
def usage
|
6
|
+
<<END
|
7
|
+
Use slacker_new to create a new Slacker project:
|
8
|
+
|
9
|
+
slacker_new <project_name>
|
10
|
+
END
|
11
|
+
end
|
12
|
+
|
13
|
+
def project_template_path
|
14
|
+
File.expand_path("#{File.dirname(__FILE__)}/../lib/slacker_new/project")
|
15
|
+
end
|
16
|
+
|
17
|
+
def slacker_new(project_name)
|
18
|
+
files = Dir.glob("#{project_template_path}/**")
|
19
|
+
FileUtils.mkdir(project_name) unless File.exist?(project_name)
|
20
|
+
FileUtils.cp_r(files, project_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def project_template_files(project_name)
|
24
|
+
files = Dir.glob("#{project_template_path}/**/*").map{|file| file.gsub(/^#{Regexp.escape(project_template_path)}\//, "./#{project_name}/")}
|
25
|
+
end
|
26
|
+
|
27
|
+
if ARGV.count != 1
|
28
|
+
puts usage
|
29
|
+
else
|
30
|
+
project_name = ARGV[0]
|
31
|
+
puts "Creating project #{project_name}..."
|
32
|
+
slacker_new(project_name)
|
33
|
+
puts project_template_files(project_name)
|
34
|
+
end
|
data/lib/slacker.rb
CHANGED
@@ -1,175 +1,180 @@
|
|
1
|
-
require 'bundler/setup'
|
2
|
-
require "slacker/version"
|
3
|
-
require 'slacker/application'
|
4
|
-
require 'slacker/configuration'
|
5
|
-
require 'slacker/sql'
|
6
|
-
require 'slacker/formatter'
|
7
|
-
require 'slacker/sql_preprocessor'
|
8
|
-
require 'csv'
|
9
|
-
require 'erb'
|
10
|
-
|
11
|
-
module Slacker
|
12
|
-
class << self
|
13
|
-
def application
|
14
|
-
@application ||= Slacker::Application.new(configuration)
|
15
|
-
end
|
16
|
-
|
17
|
-
def sql(rspec_ext)
|
18
|
-
Slacker::Sql.new(configuration.expand_path('sql'), rspec_ext)
|
19
|
-
end
|
20
|
-
|
21
|
-
def configuration
|
22
|
-
@configuration ||= Slacker::Configuration.new
|
23
|
-
end
|
24
|
-
|
25
|
-
def configure
|
26
|
-
yield configuration
|
27
|
-
end
|
28
|
-
|
29
|
-
def sql_template_path_stack
|
30
|
-
if @sql_template_path_stack.nil?
|
31
|
-
@sql_template_path_stack = []
|
32
|
-
@sql_template_path_stack.push(configuration.expand_path('sql'))
|
33
|
-
end
|
34
|
-
@sql_template_path_stack
|
35
|
-
end
|
36
|
-
|
37
|
-
# Given a template name produce the path to that template
|
38
|
-
def get_sql_template_path(template_name)
|
39
|
-
template_base_dir = template_name[0].chr == '/' ? sql_template_path_stack.first : sql_template_path_stack.last
|
40
|
-
File.expand_path(template_base_dir + '/' + template_name)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Render a template file and return the result
|
44
|
-
def render(template_name, options = {})
|
45
|
-
template_file_path = get_sql_template_path(template_name)
|
46
|
-
|
47
|
-
if !File.exists?(template_file_path)
|
48
|
-
raise "File #{template_file_path} does not exist"
|
49
|
-
end
|
50
|
-
|
51
|
-
begin
|
52
|
-
sql_template_path_stack.push(File.dirname(template_file_path))
|
53
|
-
result = render_text(IO.read(template_file_path, {:mode => 'r:BOM|UTF-8'}), options)
|
54
|
-
rescue => detail
|
55
|
-
# Report errors in the template
|
56
|
-
if detail.backtrace[0] =~ /^\(erb\)/
|
57
|
-
raise "Template error in #{template_name}:\n#{detail.backtrace[0]} : #{detail.message}\n"
|
58
|
-
else
|
59
|
-
raise detail
|
60
|
-
end
|
61
|
-
ensure
|
62
|
-
sql_template_path_stack.pop
|
63
|
-
end
|
64
|
-
|
65
|
-
result
|
66
|
-
end
|
67
|
-
|
68
|
-
# Render a template test and return the result
|
69
|
-
def render_text(template_text, options)
|
70
|
-
ERB.new(template_text, 0, '%<>').result(binding)
|
71
|
-
end
|
72
|
-
|
73
|
-
def filter_golden_master(golden_master)
|
74
|
-
golden_master = case golden_master
|
75
|
-
when String
|
76
|
-
golden_master =~ /\.csv$/ ? get_csv(golden_master) : golden_master
|
77
|
-
else
|
78
|
-
golden_master
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def sql_from_query_string(query_string, options = {})
|
83
|
-
case query_string
|
84
|
-
when /\.sql$/i,/\.erb$/i
|
85
|
-
#Pass the file through an ERb template engine
|
86
|
-
render(query_string, options)
|
87
|
-
else
|
88
|
-
query_string
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def get_csv(csv_file_path)
|
93
|
-
CSV.read(configuration.expand_path("data/#{csv_file_path}"), {
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
def
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
1
|
+
require 'bundler/setup'
|
2
|
+
require "slacker/version"
|
3
|
+
require 'slacker/application'
|
4
|
+
require 'slacker/configuration'
|
5
|
+
require 'slacker/sql'
|
6
|
+
require 'slacker/formatter'
|
7
|
+
require 'slacker/sql_preprocessor'
|
8
|
+
require 'csv'
|
9
|
+
require 'erb'
|
10
|
+
|
11
|
+
module Slacker
|
12
|
+
class << self
|
13
|
+
def application
|
14
|
+
@application ||= Slacker::Application.new(configuration)
|
15
|
+
end
|
16
|
+
|
17
|
+
def sql(rspec_ext)
|
18
|
+
Slacker::Sql.new(configuration.expand_path('sql'), rspec_ext)
|
19
|
+
end
|
20
|
+
|
21
|
+
def configuration
|
22
|
+
@configuration ||= Slacker::Configuration.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def configure
|
26
|
+
yield configuration
|
27
|
+
end
|
28
|
+
|
29
|
+
def sql_template_path_stack
|
30
|
+
if @sql_template_path_stack.nil?
|
31
|
+
@sql_template_path_stack = []
|
32
|
+
@sql_template_path_stack.push(configuration.expand_path('sql'))
|
33
|
+
end
|
34
|
+
@sql_template_path_stack
|
35
|
+
end
|
36
|
+
|
37
|
+
# Given a template name produce the path to that template
|
38
|
+
def get_sql_template_path(template_name)
|
39
|
+
template_base_dir = template_name[0].chr == '/' ? sql_template_path_stack.first : sql_template_path_stack.last
|
40
|
+
File.expand_path(template_base_dir + '/' + template_name)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Render a template file and return the result
|
44
|
+
def render(template_name, options = {})
|
45
|
+
template_file_path = get_sql_template_path(template_name)
|
46
|
+
|
47
|
+
if !File.exists?(template_file_path)
|
48
|
+
raise "File #{template_file_path} does not exist"
|
49
|
+
end
|
50
|
+
|
51
|
+
begin
|
52
|
+
sql_template_path_stack.push(File.dirname(template_file_path))
|
53
|
+
result = render_text(IO.read(template_file_path, {:mode => 'r:BOM|UTF-8'}), options)
|
54
|
+
rescue => detail
|
55
|
+
# Report errors in the template
|
56
|
+
if detail.backtrace[0] =~ /^\(erb\)/
|
57
|
+
raise "Template error in #{template_name}:\n#{detail.backtrace[0]} : #{detail.message}\n"
|
58
|
+
else
|
59
|
+
raise detail
|
60
|
+
end
|
61
|
+
ensure
|
62
|
+
sql_template_path_stack.pop
|
63
|
+
end
|
64
|
+
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
# Render a template test and return the result
|
69
|
+
def render_text(template_text, options)
|
70
|
+
ERB.new(template_text, 0, '%<>').result(binding)
|
71
|
+
end
|
72
|
+
|
73
|
+
def filter_golden_master(golden_master)
|
74
|
+
golden_master = case golden_master
|
75
|
+
when String
|
76
|
+
golden_master =~ /\.csv$/ ? get_csv(golden_master) : golden_master
|
77
|
+
else
|
78
|
+
golden_master
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def sql_from_query_string(query_string, options = {})
|
83
|
+
case query_string
|
84
|
+
when /\.sql$/i,/\.erb$/i
|
85
|
+
#Pass the file through an ERb template engine
|
86
|
+
render(query_string, options)
|
87
|
+
else
|
88
|
+
query_string
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_csv(csv_file_path)
|
93
|
+
CSV.read(configuration.expand_path("data/#{csv_file_path}"), {
|
94
|
+
:headers => true,
|
95
|
+
:encoding => 'Windows-1252',
|
96
|
+
:header_converters => lambda { |h| h.to_sym unless h.nil? }
|
97
|
+
})
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
def hash_array_to_csv(raw_array)
|
102
|
+
csv_array = []
|
103
|
+
raw_array.each do |raw_row|
|
104
|
+
csv_array << CSV::Row.new(raw_row.keys, raw_row.values)
|
105
|
+
end
|
106
|
+
CSV::Table.new(csv_array)
|
107
|
+
end
|
108
|
+
|
109
|
+
def sql_file_from_method_name(base_folder, method_name)
|
110
|
+
file_name = File.join(base_folder, method_name)
|
111
|
+
|
112
|
+
file_name = case
|
113
|
+
when File.exists?("#{file_name}.sql") then "#{file_name}.sql"
|
114
|
+
when File.exists?("#{file_name}.sql.erb") then "#{file_name}.sql.erb"
|
115
|
+
else nil
|
116
|
+
end
|
117
|
+
|
118
|
+
file_name.nil? ? nil : file_name.gsub(/#{Regexp.escape(configuration.expand_path('sql'))}/i, '')
|
119
|
+
end
|
120
|
+
|
121
|
+
def construct_log_name(entry_point, query_string, options)
|
122
|
+
"#{entry_point} '#{query_string}'" + (options.empty? ? '': ", options = #{options.inspect}")
|
123
|
+
end
|
124
|
+
|
125
|
+
# Run a SQL query against an example
|
126
|
+
def query_script(example, sql, log_name=nil)
|
127
|
+
log_name ||= 'Run SQL Script'
|
128
|
+
|
129
|
+
debuggable_sql = SqlPreprocessor.debuggable_sql(sql)
|
130
|
+
executable_sql = SqlPreprocessor.executable_sql(sql, example)
|
131
|
+
|
132
|
+
example.metadata[:sql] += ((example.metadata[:sql] == '' ? '' : "\n\n") + "-- #{log_name.split(/\r\n|\n/).join("\n-- ")}\n#{debuggable_sql}")
|
133
|
+
application.query_script(executable_sql)
|
134
|
+
end
|
135
|
+
|
136
|
+
def load_csv(example, csv, table_name, log_name = nil)
|
137
|
+
csv_a = csv.to_a
|
138
|
+
sql = nil
|
139
|
+
csv_a.each_with_index do |row, index|
|
140
|
+
if index == 0
|
141
|
+
sql = "INSERT INTO #{table_name}(#{row.map{|header| "[#{header}]"}.join(',')})"
|
142
|
+
else
|
143
|
+
sql += ("\nSELECT #{row.map{|val| val.nil? ? 'NULL': "'#{val}'"}.join(',')}" + (index < (csv_a.count - 1) ? ' UNION ALL' : ''))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
query_script(example, sql, log_name) unless sql.nil?
|
147
|
+
end
|
148
|
+
|
149
|
+
def touch_csv(csv_file_or_object, fields, field_generators = {})
|
150
|
+
csv_obj = csv_file_or_object.kind_of?(String) ? get_csv(csv_file_or_object) : csv_file_or_object
|
151
|
+
fields = fields.is_a?(Array) ? fields : [fields]
|
152
|
+
|
153
|
+
# Adjust the csv if we are providing more records than there are in the csv
|
154
|
+
csv_row_count = csv_obj.to_a.count - 1
|
155
|
+
|
156
|
+
(fields.count - csv_row_count).times do |index|
|
157
|
+
csv_obj << csv_obj[index % csv_row_count].fields
|
158
|
+
end
|
159
|
+
|
160
|
+
# Add the field generators to the hard-coded fields
|
161
|
+
field_generators.each do |key, value|
|
162
|
+
fields.each_with_index do |record, index|
|
163
|
+
record[key] = value.to_s + index.to_s
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
fields.each_with_index do |record, index|
|
168
|
+
record.each do |key, value|
|
169
|
+
csv_obj[index][key.to_sym.downcase] = value
|
170
|
+
end
|
171
|
+
end
|
172
|
+
csv_obj
|
173
|
+
end
|
174
|
+
|
175
|
+
def mixin_module(module_class)
|
176
|
+
extend module_class
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|