slacker 1.0.9 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +4 -4
  3. data/README.markdown +22 -22
  4. data/Rakefile +11 -11
  5. data/bin/slacker +28 -29
  6. data/bin/slacker_new +34 -34
  7. data/lib/slacker.rb +175 -175
  8. data/lib/slacker/application.rb +211 -206
  9. data/lib/slacker/command_line_formatter.rb +59 -59
  10. data/lib/slacker/command_line_formatter2.rb +61 -0
  11. data/lib/slacker/configuration.rb +59 -59
  12. data/lib/slacker/formatter.rb +14 -19
  13. data/lib/slacker/query_result_matcher.rb +178 -178
  14. data/lib/slacker/rspec_ext.rb +49 -49
  15. data/lib/slacker/rspec_monkey.rb +7 -7
  16. data/lib/slacker/sql.rb +39 -39
  17. data/lib/slacker/sql_preprocessor.rb +23 -23
  18. data/lib/slacker/string_helper.rb +16 -16
  19. data/lib/slacker/version.rb +3 -3
  20. data/lib/slacker_new/project/data/sample_1/my_table_expected_power_results.csv +11 -11
  21. data/lib/slacker_new/project/data/sample_1/my_table_initial_data.csv +11 -11
  22. data/lib/slacker_new/project/data/sample_1/numbers_expected_output.csv +3 -3
  23. data/lib/slacker_new/project/database.yml +9 -9
  24. data/lib/slacker_new/project/lib/helpers/my_helper.rb +1 -1
  25. data/lib/slacker_new/project/spec/sample_1.rb +66 -66
  26. data/lib/slacker_new/project/sql/sample_1/my_table_on_power.sql.erb +1 -1
  27. data/lib/slacker_new/project/sql/sample_1/play_with_numbers.sql.erb +16 -16
  28. data/lib/slacker_new/project/sql/sample_1/sysobjects_with_params.sql.erb +1 -1
  29. data/slacker.gemspec +27 -26
  30. data/spec/application_spec.rb +13 -13
  31. data/spec/query_result_matcher_spec.rb +268 -268
  32. data/spec/rspec_ext_spec.rb +87 -87
  33. data/spec/slacker_spec.rb +59 -59
  34. data/spec/spec_helper.rb +9 -9
  35. data/spec/test_files/matcher/test_1.csv +3 -3
  36. data/spec/test_files/test_slacker_project/data/test_1.csv +3 -3
  37. data/spec/test_files/test_slacker_project/sql/nest/nested_1.sql.erb +1 -1
  38. data/spec/test_files/test_slacker_project/sql/no_params.sql.erb +2 -2
  39. data/spec/test_files/test_slacker_project/sql/params.sql.erb +1 -1
  40. metadata +19 -20
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2VhYWRjODA5Yjc1MjhlMjkyYWViZGM0YzVhM2ZjODE4MDU3MDRiZA==
5
+ data.tar.gz: !binary |-
6
+ ZWE5ZjUyYzRiNmQ5OTY0MDdlNWQ4Yzc3NDE4YmUwNjA2MmE0YTE3OA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MDQyY2I0M2FiZjM2MDc5ODhlNTg1YjI3ZTE2ZDVlY2ZkNDE1YzI2ZGIzOTcz
10
+ NDY0Yzk0NWQwOWVlZDk5NDJjYzJjOTY1NjlmZTQ0ZTg4N2E4ZDc4YzVjM2Iy
11
+ ODlmOGZmYmY4YjNmNTU0YzhlMWQxNmY0YzUwMjZmYzRiMTVmMDQ=
12
+ data.tar.gz: !binary |-
13
+ ZDA5MmEyYjRmMTE0Njc1YjMxMTA3NWQ1YTdjN2Q1MWY1NTMxOWZkZDhmNWY3
14
+ YmYyZjU5NjcxMzczYzU0ZGUyMjg3OGM2NTA5MDgwNzgwZDZkZWJlMjBjYmRj
15
+ NjBhZTJlZGM4MGQ1YWJmMzNmYzI1MTU0N2E3ZTZlMGQwOTg1NjE=
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
@@ -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 and 2008 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) 2012 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
@@ -1,29 +1,28 @@
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
- config.formatter = Slacker::CommandLineFormatter.new($stdout)
19
-
20
- # Setup the target connection based on the contents in database.yml
21
- db_config = db_config_from_file(config.expand_path('database.yml'))
22
-
23
- config.db_server = db_config["server"]
24
- config.db_name = db_config["database"]
25
- config.db_user = db_config["user"]
26
- config.db_password = db_config["password"]
27
- end
28
-
29
- Slacker.application.run
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'slacker'
4
+ require 'yaml'
5
+ require 'slacker/command_line_formatter2'
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
+ Slacker.application.run
@@ -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
@@ -1,175 +1,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), 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}"), {:headers => true, :encoding => 'Windows-1252', :header_converters => :symbol})
94
- end
95
-
96
- def hash_array_to_csv(raw_array)
97
- csv_array = []
98
- raw_array.each do |raw_row|
99
- csv_array << CSV::Row.new(raw_row.keys, raw_row.values)
100
- end
101
- CSV::Table.new(csv_array)
102
- end
103
-
104
- def sql_file_from_method_name(base_folder, method_name)
105
- file_name = File.join(base_folder, method_name)
106
-
107
- file_name = case
108
- when File.exists?("#{file_name}.sql") then "#{file_name}.sql"
109
- when File.exists?("#{file_name}.sql.erb") then "#{file_name}.sql.erb"
110
- else nil
111
- end
112
-
113
- file_name.nil? ? nil : file_name.gsub(/#{Regexp.escape(configuration.expand_path('sql'))}/i, '')
114
- end
115
-
116
- def construct_log_name(entry_point, query_string, options)
117
- "#{entry_point} '#{query_string}'" + (options.empty? ? '': ", options = #{options.inspect}")
118
- end
119
-
120
- # Run a SQL query against an example
121
- def query_script(example, sql, log_name=nil)
122
- log_name ||= 'Run SQL Script'
123
-
124
- debuggable_sql = SqlPreprocessor.debuggable_sql(sql)
125
- executable_sql = SqlPreprocessor.executable_sql(sql, example)
126
-
127
- example.metadata[:sql] += ((example.metadata[:sql] == '' ? '' : "\n\n") + "-- #{log_name.split(/\r\n|\n/).join("\n-- ")}\n#{debuggable_sql}")
128
- application.query_script(executable_sql)
129
- end
130
-
131
- def load_csv(example, csv, table_name, log_name = nil)
132
- csv_a = csv.to_a
133
- sql = nil
134
- csv_a.each_with_index do |row, index|
135
- if index == 0
136
- sql = "INSERT INTO #{table_name}(#{row.map{|header| "[#{header}]"}.join(',')})"
137
- else
138
- sql += ("\nSELECT #{row.map{|val| val.nil? ? 'NULL': "'#{val}'"}.join(',')}" + (index < (csv_a.count - 1) ? ' UNION ALL' : ''))
139
- end
140
- end
141
- query_script(example, sql, log_name) unless sql.nil?
142
- end
143
-
144
- def touch_csv(csv_file_or_object, fields, field_generators = {})
145
- csv_obj = csv_file_or_object.kind_of?(String) ? get_csv(csv_file_or_object) : csv_file_or_object
146
- fields = fields.is_a?(Array) ? fields : [fields]
147
-
148
- # Adjust the csv if we are providing more records than there are in the csv
149
- csv_row_count = csv_obj.to_a.count - 1
150
-
151
- (fields.count - csv_row_count).times do |index|
152
- csv_obj << csv_obj[index % csv_row_count].fields
153
- end
154
-
155
- # Add the field generators to the hard-coded fields
156
- field_generators.each do |key, value|
157
- fields.each_with_index do |record, index|
158
- record[key] = value.to_s + index.to_s
159
- end
160
- end
161
-
162
- fields.each_with_index do |record, index|
163
- record.each do |key, value|
164
- csv_obj[index][key.to_sym.downcase] = value
165
- end
166
- end
167
- csv_obj
168
- end
169
-
170
- def mixin_module(module_class)
171
- extend module_class
172
- end
173
-
174
- end
175
- end
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), 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}"), {:headers => true, :encoding => 'Windows-1252', :header_converters => :symbol})
94
+ end
95
+
96
+ def hash_array_to_csv(raw_array)
97
+ csv_array = []
98
+ raw_array.each do |raw_row|
99
+ csv_array << CSV::Row.new(raw_row.keys, raw_row.values)
100
+ end
101
+ CSV::Table.new(csv_array)
102
+ end
103
+
104
+ def sql_file_from_method_name(base_folder, method_name)
105
+ file_name = File.join(base_folder, method_name)
106
+
107
+ file_name = case
108
+ when File.exists?("#{file_name}.sql") then "#{file_name}.sql"
109
+ when File.exists?("#{file_name}.sql.erb") then "#{file_name}.sql.erb"
110
+ else nil
111
+ end
112
+
113
+ file_name.nil? ? nil : file_name.gsub(/#{Regexp.escape(configuration.expand_path('sql'))}/i, '')
114
+ end
115
+
116
+ def construct_log_name(entry_point, query_string, options)
117
+ "#{entry_point} '#{query_string}'" + (options.empty? ? '': ", options = #{options.inspect}")
118
+ end
119
+
120
+ # Run a SQL query against an example
121
+ def query_script(example, sql, log_name=nil)
122
+ log_name ||= 'Run SQL Script'
123
+
124
+ debuggable_sql = SqlPreprocessor.debuggable_sql(sql)
125
+ executable_sql = SqlPreprocessor.executable_sql(sql, example)
126
+
127
+ example.metadata[:sql] += ((example.metadata[:sql] == '' ? '' : "\n\n") + "-- #{log_name.split(/\r\n|\n/).join("\n-- ")}\n#{debuggable_sql}")
128
+ application.query_script(executable_sql)
129
+ end
130
+
131
+ def load_csv(example, csv, table_name, log_name = nil)
132
+ csv_a = csv.to_a
133
+ sql = nil
134
+ csv_a.each_with_index do |row, index|
135
+ if index == 0
136
+ sql = "INSERT INTO #{table_name}(#{row.map{|header| "[#{header}]"}.join(',')})"
137
+ else
138
+ sql += ("\nSELECT #{row.map{|val| val.nil? ? 'NULL': "'#{val}'"}.join(',')}" + (index < (csv_a.count - 1) ? ' UNION ALL' : ''))
139
+ end
140
+ end
141
+ query_script(example, sql, log_name) unless sql.nil?
142
+ end
143
+
144
+ def touch_csv(csv_file_or_object, fields, field_generators = {})
145
+ csv_obj = csv_file_or_object.kind_of?(String) ? get_csv(csv_file_or_object) : csv_file_or_object
146
+ fields = fields.is_a?(Array) ? fields : [fields]
147
+
148
+ # Adjust the csv if we are providing more records than there are in the csv
149
+ csv_row_count = csv_obj.to_a.count - 1
150
+
151
+ (fields.count - csv_row_count).times do |index|
152
+ csv_obj << csv_obj[index % csv_row_count].fields
153
+ end
154
+
155
+ # Add the field generators to the hard-coded fields
156
+ field_generators.each do |key, value|
157
+ fields.each_with_index do |record, index|
158
+ record[key] = value.to_s + index.to_s
159
+ end
160
+ end
161
+
162
+ fields.each_with_index do |record, index|
163
+ record.each do |key, value|
164
+ csv_obj[index][key.to_sym.downcase] = value
165
+ end
166
+ end
167
+ csv_obj
168
+ end
169
+
170
+ def mixin_module(module_class)
171
+ extend module_class
172
+ end
173
+
174
+ end
175
+ end