stairwell 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.bin/bundle +109 -0
- data/.bin/coderay +29 -0
- data/.bin/pry +29 -0
- data/.bin/rake +27 -0
- data/Gemfile +3 -5
- data/Gemfile.lock +8 -15
- data/Rakefile +8 -6
- data/bin/console +5 -6
- data/lib/stairwell/bind_transformer.rb +17 -15
- data/lib/stairwell/query.rb +12 -41
- data/lib/stairwell/type_object_assigner.rb +35 -0
- data/lib/stairwell/types/base_type.rb +26 -11
- data/lib/stairwell/types/boolean_type.rb +7 -5
- data/lib/stairwell/types/column_name_type.rb +10 -8
- data/lib/stairwell/types/date_time_type.rb +7 -5
- data/lib/stairwell/types/date_type.rb +7 -5
- data/lib/stairwell/types/float_type.rb +7 -5
- data/lib/stairwell/types/in_type.rb +17 -15
- data/lib/stairwell/types/integer_type.rb +7 -5
- data/lib/stairwell/types/null_type.rb +7 -5
- data/lib/stairwell/types/string_type.rb +7 -5
- data/lib/stairwell/types/table_name_type.rb +10 -8
- data/lib/stairwell/version.rb +3 -1
- data/lib/stairwell.rb +21 -14
- data/stairwell.gemspec +17 -15
- data/test.db +0 -0
- metadata +37 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9eb7f5f503d74ee340bc8e9011dcf587604c20d6fd959a5b006def17769b71a
|
4
|
+
data.tar.gz: 6bcbbc5866685ef8d767428a33b5862b58952a849e37237f869622ba720806d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc068d002df5eddc9026ae6ce34c786697712c2b475255fdcf5e0a0e8eaedbe9b3dc138f505ca6328342cc2e7a99648fd78087ae26b6946a481ddaefec35d943
|
7
|
+
data.tar.gz: 8d9b86448fe37776e4aef1c4a7620946af302f016516c06fe931975e6d00b9128ee1ce2d087567850bc384ff0fa147fbbf82a93cb6a2e94de9daf09918e009c4
|
data/.bin/bundle
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
bundler_version = nil
|
28
|
+
update_index = nil
|
29
|
+
ARGV.each_with_index do |a, i|
|
30
|
+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
+
bundler_version = a
|
32
|
+
end
|
33
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
+
bundler_version = $1
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../Gemfile", __dir__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, ".locked")
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
lockfile_contents = File.read(lockfile)
|
59
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
+
Regexp.last_match(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundler_requirement
|
64
|
+
@bundler_requirement ||=
|
65
|
+
env_var_version ||
|
66
|
+
cli_arg_version ||
|
67
|
+
bundler_requirement_for(lockfile_version)
|
68
|
+
end
|
69
|
+
|
70
|
+
def bundler_requirement_for(version)
|
71
|
+
return "#{Gem::Requirement.default}.a" unless version
|
72
|
+
|
73
|
+
bundler_gem_version = Gem::Version.new(version)
|
74
|
+
|
75
|
+
bundler_gem_version.approximate_recommendation
|
76
|
+
end
|
77
|
+
|
78
|
+
def load_bundler!
|
79
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
80
|
+
|
81
|
+
activate_bundler
|
82
|
+
end
|
83
|
+
|
84
|
+
def activate_bundler
|
85
|
+
gem_error = activation_error_handling do
|
86
|
+
gem "bundler", bundler_requirement
|
87
|
+
end
|
88
|
+
return if gem_error.nil?
|
89
|
+
require_error = activation_error_handling do
|
90
|
+
require "bundler/version"
|
91
|
+
end
|
92
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
93
|
+
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
94
|
+
exit 42
|
95
|
+
end
|
96
|
+
|
97
|
+
def activation_error_handling
|
98
|
+
yield
|
99
|
+
nil
|
100
|
+
rescue StandardError, LoadError => e
|
101
|
+
e
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
m.load_bundler!
|
106
|
+
|
107
|
+
if m.invoked_as_script?
|
108
|
+
load Gem.bin_path("bundler", "bundle")
|
109
|
+
end
|
data/.bin/coderay
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'coderay' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("coderay", "coderay")
|
data/.bin/pry
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'pry' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("pry", "pry")
|
data/.bin/rake
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
+
|
13
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
+
|
15
|
+
if File.file?(bundle_binstub)
|
16
|
+
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
|
17
|
+
load(bundle_binstub)
|
18
|
+
else
|
19
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require "rubygems"
|
25
|
+
require "bundler/setup"
|
26
|
+
|
27
|
+
load Gem.bin_path("rake", "rake")
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
stairwell (0.
|
4
|
+
stairwell (0.5.0)
|
5
5
|
activerecord (>= 4.2.11)
|
6
|
+
rake
|
6
7
|
sqlite3
|
8
|
+
zeitwerk (~> 2.5)
|
7
9
|
|
8
10
|
GEM
|
9
11
|
remote: https://rubygems.org/
|
@@ -26,36 +28,27 @@ GEM
|
|
26
28
|
tzinfo (~> 2.0)
|
27
29
|
base64 (0.1.1)
|
28
30
|
bigdecimal (3.1.4)
|
29
|
-
coderay (1.1.3)
|
30
31
|
concurrent-ruby (1.2.2)
|
31
32
|
connection_pool (2.4.1)
|
32
33
|
drb (2.1.1)
|
33
34
|
ruby2_keywords
|
34
35
|
i18n (1.14.1)
|
35
36
|
concurrent-ruby (~> 1.0)
|
36
|
-
method_source (1.0.0)
|
37
|
-
mini_portile2 (2.8.5)
|
38
37
|
minitest (5.20.0)
|
39
38
|
mutex_m (0.1.2)
|
40
|
-
|
41
|
-
coderay (~> 1.1)
|
42
|
-
method_source (~> 1.0)
|
43
|
-
rake (12.3.3)
|
39
|
+
rake (13.1.0)
|
44
40
|
ruby2_keywords (0.0.5)
|
45
|
-
sqlite3 (1.6.7)
|
46
|
-
mini_portile2 (~> 2.8.0)
|
41
|
+
sqlite3 (1.6.7-x86_64-darwin)
|
47
42
|
timeout (0.4.0)
|
48
43
|
tzinfo (2.0.6)
|
49
44
|
concurrent-ruby (~> 1.0)
|
45
|
+
zeitwerk (2.6.12)
|
50
46
|
|
51
47
|
PLATFORMS
|
52
|
-
|
48
|
+
x86_64-darwin-20
|
53
49
|
|
54
50
|
DEPENDENCIES
|
55
|
-
minitest (~> 5.0)
|
56
|
-
pry
|
57
|
-
rake (~> 12.0)
|
58
51
|
stairwell!
|
59
52
|
|
60
53
|
BUNDLED WITH
|
61
|
-
2.
|
54
|
+
2.4.10
|
data/Rakefile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rake/testtask'
|
3
5
|
|
4
6
|
Rake::TestTask.new(:test) do |t|
|
5
|
-
t.libs <<
|
6
|
-
t.libs <<
|
7
|
-
t.test_files = FileList[
|
7
|
+
t.libs << 'test'
|
8
|
+
t.libs << 'lib'
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
8
10
|
end
|
9
11
|
|
10
|
-
task :
|
12
|
+
task default: :test
|
data/bin/console
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'stairwell'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
8
9
|
|
9
10
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
require "pry"
|
11
|
-
Pry.start
|
12
11
|
|
13
|
-
|
14
|
-
|
12
|
+
require 'irb'
|
13
|
+
IRB.start(__FILE__)
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Stairwell
|
2
4
|
class BindTransformer
|
3
|
-
|
4
|
-
attr_accessor :sql, :bind_hash, :depleting_bind_hash, :converted_sql
|
5
|
+
attr_reader :sql, :bind_hash, :depleting_bind_hash, :converted_sql
|
5
6
|
|
6
7
|
def initialize(sql, bind_hash)
|
7
8
|
@sql = sql
|
@@ -16,32 +17,33 @@ module Stairwell
|
|
16
17
|
# and error will raise
|
17
18
|
# The sql string will then have the appropropriate values substituted
|
18
19
|
# with quoted values to ensure safety.
|
19
|
-
|
20
|
-
def transform
|
20
|
+
def run
|
21
21
|
convert_sql
|
22
22
|
validate_bind_hash
|
23
23
|
converted_sql
|
24
24
|
end
|
25
25
|
|
26
|
+
private
|
27
|
+
|
26
28
|
def convert_sql
|
27
|
-
@converted_sql
|
28
|
-
replace =
|
29
|
+
@converted_sql = sql.gsub(/(:?):([a-zA-Z]\w*)/) do |_|
|
30
|
+
replace = ::Regexp.last_match(2).to_sym
|
29
31
|
validate_sql(replace)
|
30
32
|
bind_hash[replace].quote
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
def validate_sql(attr)
|
37
|
-
raise SqlBindMismatch, ":#{attr} in your query is missing from your args" unless bind_hash[attr]
|
36
|
+
def validate_sql(attr)
|
37
|
+
raise SqlBindMismatch, ":#{attr} in your query is missing from your args" unless bind_hash[attr]
|
38
38
|
|
39
|
-
|
40
|
-
|
39
|
+
depleting_bind_hash.delete(attr)
|
40
|
+
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
end
|
42
|
+
def validate_bind_hash
|
43
|
+
return if depleting_bind_hash.empty?
|
45
44
|
|
45
|
+
raise SqlBindMismatch,
|
46
|
+
":#{depleting_bind_hash.keys.join(', ')} in your bind hash is missing from your query: #{sql}"
|
47
|
+
end
|
46
48
|
end
|
47
49
|
end
|
data/lib/stairwell/query.rb
CHANGED
@@ -1,62 +1,33 @@
|
|
1
|
-
|
2
|
-
require "stairwell/types/boolean_type"
|
3
|
-
require "stairwell/types/column_name_type"
|
4
|
-
require "stairwell/types/date_time_type"
|
5
|
-
require "stairwell/types/date_type"
|
6
|
-
require "stairwell/types/float_type"
|
7
|
-
require "stairwell/types/integer_type"
|
8
|
-
require "stairwell/types/in_type"
|
9
|
-
require "stairwell/types/string_type"
|
10
|
-
require "stairwell/types/null_type"
|
11
|
-
require "stairwell/types/table_name_type"
|
1
|
+
# frozen_string_literal: true
|
12
2
|
|
13
3
|
module Stairwell
|
14
4
|
class Query
|
15
|
-
|
16
5
|
class << self
|
17
|
-
attr_accessor :bind_hash, :all_validations, :sql_string
|
18
|
-
|
19
6
|
def validate_type(*args)
|
20
7
|
@all_validations ||= {}
|
21
8
|
@all_validations.merge!(Hash[*args])
|
22
9
|
end
|
23
10
|
|
24
11
|
def sql(**args)
|
25
|
-
|
26
|
-
|
27
|
-
|
12
|
+
raise InvalidBindCount, 'Incorrect amount of args passed' if args.keys.sort != all_validations.keys.sort
|
13
|
+
|
14
|
+
@type_hash = args.each_with_object({}) do |(name, value), hash|
|
15
|
+
hash[name] = TypeObjectAssigner.run(name:, value:, all_validations:)
|
16
|
+
end
|
17
|
+
transformer.run
|
28
18
|
end
|
29
19
|
|
30
20
|
def query(string)
|
31
|
-
@sql_string = string
|
21
|
+
@sql_string = string.squish
|
32
22
|
end
|
33
23
|
|
34
24
|
private
|
35
25
|
|
36
|
-
|
37
|
-
raise InvalidBindCount.new("Incorrect amount of args passed") unless correct_args?
|
38
|
-
|
39
|
-
bind_hash.each do |bind_name, bind_value|
|
40
|
-
type = all_validations[bind_name]
|
41
|
-
if type.is_a?(Array)
|
42
|
-
type = type.first
|
43
|
-
type_object = Types::InType.new(bind_value, type)
|
44
|
-
end
|
45
|
-
type_object ||= Object.const_get(TYPE_CLASSES[type]).new(bind_value)
|
46
|
-
|
47
|
-
raise InvalidBindType.new("#{bind_name} is not #{all_validations[bind_name]}") unless type_object.valid?
|
26
|
+
attr_reader :type_hash, :all_validations, :sql_string
|
48
27
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
def transformed_sql_string
|
54
|
-
BindTransformer.new(sql_string.squish!, bind_hash).transform
|
55
|
-
end
|
56
|
-
|
57
|
-
def correct_args?
|
58
|
-
bind_hash.keys.sort == all_validations.keys.sort
|
59
|
-
end
|
28
|
+
def transformer
|
29
|
+
BindTransformer.new(sql_string, type_hash)
|
30
|
+
end
|
60
31
|
end
|
61
32
|
end
|
62
33
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Stairwell
|
4
|
+
class TypeObjectAssigner
|
5
|
+
attr_reader :name, :value, :all_validations
|
6
|
+
|
7
|
+
def self.run(...)
|
8
|
+
new(...).run
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(name:, value:, all_validations:)
|
12
|
+
@name = name
|
13
|
+
@value = value
|
14
|
+
@all_validations = all_validations
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
type_object
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def proposed_type
|
24
|
+
all_validations[name]
|
25
|
+
end
|
26
|
+
|
27
|
+
def type_object
|
28
|
+
if proposed_type.is_a?(Array)
|
29
|
+
Types::InType.new(value, proposed_type.first)
|
30
|
+
else
|
31
|
+
Object.const_get(TYPE_CLASSES[proposed_type]).new(value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,17 +1,32 @@
|
|
1
|
-
|
2
|
-
class BaseType
|
3
|
-
attr_reader :value
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class BaseType
|
6
|
+
attr_reader :value
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def initialize(value)
|
9
|
+
@value = value
|
10
|
+
validate!
|
11
|
+
end
|
12
|
+
|
13
|
+
def quote
|
14
|
+
connection.quote(value)
|
15
|
+
end
|
16
|
+
|
17
|
+
def connection
|
18
|
+
@connection ||= ActiveRecord::Base.connection
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate!
|
22
|
+
return if valid?
|
23
|
+
|
24
|
+
raise InvalidBindType, "#{value} is not #{type_name}"
|
25
|
+
end
|
12
26
|
|
13
|
-
|
14
|
-
|
27
|
+
def type_name
|
28
|
+
self.class.name.split('::').last.gsub('Type', '').downcase
|
29
|
+
end
|
15
30
|
end
|
16
31
|
end
|
17
32
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class BooleanType < BaseType
|
6
|
+
def valid?
|
7
|
+
value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class ColumnNameType < BaseType
|
6
|
+
def valid?
|
7
|
+
value.is_a?(String)
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
def quote
|
11
|
+
connection.quote_column_name(value)
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class DateTimeType < BaseType
|
6
|
+
def valid?
|
7
|
+
value.is_a?(String)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class DateType < BaseType
|
6
|
+
def valid?
|
7
|
+
value.is_a?(String)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class FloatType < BaseType
|
6
|
+
def valid?
|
7
|
+
value.is_a?(Float)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,28 +1,30 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class InType
|
6
|
+
attr_reader :value, :type
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
def initialize(value, type)
|
9
|
+
@value = value
|
10
|
+
@type = type
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
def quote
|
14
|
+
contained_values.map(&:quote).join(', ')
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
def valid?
|
18
|
+
value.is_a?(Array) && contained_values.all?(&:valid?)
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
+
private
|
21
22
|
|
22
23
|
def contained_values
|
23
24
|
value.map do |contained|
|
24
25
|
Object.const_get(Stairwell::TYPE_CLASSES[type]).new(contained)
|
25
26
|
end
|
26
27
|
end
|
28
|
+
end
|
27
29
|
end
|
28
30
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class IntegerType < BaseType
|
6
|
+
def valid?
|
7
|
+
value.is_a?(Integer)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class NullType < BaseType
|
6
|
+
def valid?
|
7
|
+
value.is_a?(NilClass)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class StringType < BaseType
|
6
|
+
def valid?
|
7
|
+
value.is_a?(String)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Stairwell
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module Stairwell
|
4
|
+
module Types
|
5
|
+
class TableNameType < BaseType
|
6
|
+
def valid?
|
7
|
+
value.is_a?(String)
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
def quote
|
11
|
+
connection.quote_table_name(value)
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
data/lib/stairwell/version.rb
CHANGED
data/lib/stairwell.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require "stairwell/version"
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_record'
|
5
4
|
|
6
5
|
module Stairwell
|
7
6
|
class Error < StandardError; end
|
@@ -10,22 +9,30 @@ module Stairwell
|
|
10
9
|
class SqlBindMismatch < StandardError; end
|
11
10
|
|
12
11
|
TYPE_CLASSES = {
|
13
|
-
string:
|
14
|
-
integer:
|
15
|
-
boolean:
|
16
|
-
float:
|
17
|
-
date:
|
18
|
-
date_time:
|
19
|
-
null:
|
20
|
-
column_name:
|
21
|
-
table_name:
|
12
|
+
string: 'Stairwell::Types::StringType',
|
13
|
+
integer: 'Stairwell::Types::IntegerType',
|
14
|
+
boolean: 'Stairwell::Types::BooleanType',
|
15
|
+
float: 'Stairwell::Types::FloatType',
|
16
|
+
date: 'Stairwell::Types::DateType',
|
17
|
+
date_time: 'Stairwell::Types::DateTimeType',
|
18
|
+
null: 'Stairwell::Types::NullType',
|
19
|
+
column_name: 'Stairwell::Types::ColumnNameType',
|
20
|
+
table_name: 'Stairwell::Types::TableNameType'
|
22
21
|
}.freeze
|
23
22
|
|
24
23
|
# for development and testing
|
25
24
|
unless defined?(Rails)
|
26
|
-
ActiveRecord::Base.establish_connection(
|
25
|
+
::ActiveRecord::Base.establish_connection(
|
27
26
|
adapter: 'sqlite3',
|
28
27
|
database: 'test.db'
|
29
28
|
)
|
30
29
|
end
|
31
30
|
end
|
31
|
+
|
32
|
+
require 'date'
|
33
|
+
require 'zeitwerk'
|
34
|
+
|
35
|
+
loader = Zeitwerk::Loader.for_gem
|
36
|
+
loader.ignore("#{__dir__}/kamal/sshkit_with_ext.rb")
|
37
|
+
loader.setup
|
38
|
+
loader.eager_load # We need all commands loaded.
|
data/stairwell.gemspec
CHANGED
@@ -1,35 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'lib/stairwell/version'
|
2
4
|
|
3
5
|
Gem::Specification.new do |spec|
|
4
|
-
spec.name =
|
6
|
+
spec.name = 'stairwell'
|
5
7
|
spec.version = Stairwell::VERSION
|
6
|
-
spec.authors = [
|
8
|
+
spec.authors = ['tobyond']
|
7
9
|
|
8
|
-
spec.summary =
|
9
|
-
spec.description =
|
10
|
-
spec.homepage =
|
11
|
-
spec.license =
|
12
|
-
spec.required_ruby_version = Gem::Requirement.new(
|
10
|
+
spec.summary = 'stairwell for sql'
|
11
|
+
spec.description = 'I actually like SQL, and want to use it in my Ruby projects.'
|
12
|
+
spec.homepage = 'https://github.com/tobyond/stairwell'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.2.0')
|
13
15
|
|
14
16
|
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
15
17
|
|
16
|
-
spec.metadata[
|
17
|
-
spec.metadata[
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
19
|
+
spec.metadata['source_code_uri'] = 'https://github.com/tobyond/stairwell'
|
18
20
|
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
19
21
|
|
20
22
|
# Specify which files should be added to the gem when it is released.
|
21
23
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
-
spec.files
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
25
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
26
|
end
|
25
|
-
spec.bindir =
|
27
|
+
spec.bindir = 'exe'
|
26
28
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
-
spec.require_paths = [
|
29
|
+
spec.require_paths = ['lib']
|
28
30
|
|
29
31
|
spec.add_dependency 'activerecord', '>= 4.2.11'
|
32
|
+
spec.add_dependency 'rake'
|
33
|
+
spec.add_dependency 'zeitwerk', '~> 2.5'
|
30
34
|
|
31
35
|
# for development and testing
|
32
|
-
unless defined?(Rails)
|
33
|
-
spec.add_dependency 'sqlite3'
|
34
|
-
end
|
36
|
+
spec.add_dependency 'sqlite3' unless defined?(Rails)
|
35
37
|
end
|
data/test.db
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stairwell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tobyond
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10
|
11
|
+
date: 2023-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -24,6 +24,34 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.2.11
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: zeitwerk
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.5'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.5'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: sqlite3
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,12 +66,16 @@ dependencies:
|
|
38
66
|
- - ">="
|
39
67
|
- !ruby/object:Gem::Version
|
40
68
|
version: '0'
|
41
|
-
description:
|
69
|
+
description: I actually like SQL, and want to use it in my Ruby projects.
|
42
70
|
email:
|
43
71
|
executables: []
|
44
72
|
extensions: []
|
45
73
|
extra_rdoc_files: []
|
46
74
|
files:
|
75
|
+
- ".bin/bundle"
|
76
|
+
- ".bin/coderay"
|
77
|
+
- ".bin/pry"
|
78
|
+
- ".bin/rake"
|
47
79
|
- ".gitignore"
|
48
80
|
- ".travis.yml"
|
49
81
|
- Gemfile
|
@@ -56,6 +88,7 @@ files:
|
|
56
88
|
- lib/stairwell.rb
|
57
89
|
- lib/stairwell/bind_transformer.rb
|
58
90
|
- lib/stairwell/query.rb
|
91
|
+
- lib/stairwell/type_object_assigner.rb
|
59
92
|
- lib/stairwell/types/base_type.rb
|
60
93
|
- lib/stairwell/types/boolean_type.rb
|
61
94
|
- lib/stairwell/types/column_name_type.rb
|
@@ -84,7 +117,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
84
117
|
requirements:
|
85
118
|
- - ">="
|
86
119
|
- !ruby/object:Gem::Version
|
87
|
-
version: 2.
|
120
|
+
version: 3.2.0
|
88
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
122
|
requirements:
|
90
123
|
- - ">="
|