yesql 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -22
  3. data/lib/.rbnext/2.3/yesql/errors/file_path_does_not_exist_error.rb +40 -0
  4. data/lib/.rbnext/2.3/yesql/errors/no_bindings_provided_error.rb +38 -0
  5. data/lib/.rbnext/2.3/yesql/errors/output_argument_error.rb +31 -0
  6. data/lib/.rbnext/2.3/yesql/query/transform_result.rb +48 -0
  7. data/lib/.rbnext/2.7/yesql/bindings/extract.rb +71 -0
  8. data/lib/.rbnext/2.7/yesql/bindings/extractor.rb +38 -0
  9. data/lib/.rbnext/2.7/yesql/bindings/transformed.rb +58 -0
  10. data/lib/.rbnext/2.7/yesql/bindings/utils.rb +16 -0
  11. data/lib/.rbnext/2.7/yesql/errors/file_path_does_not_exist_error.rb +43 -0
  12. data/lib/.rbnext/2.7/yesql/errors/no_bindings_provided_error.rb +41 -0
  13. data/lib/.rbnext/2.7/yesql/query/transform_result.rb +48 -0
  14. data/lib/.rbnext/2.7/yesql/statement.rb +44 -0
  15. data/lib/.rbnext/2.7/yesql/utils/read.rb +20 -0
  16. data/lib/.rbnext/3.0/yesql/bindings/extract.rb +71 -0
  17. data/lib/.rbnext/3.0/yesql/bindings/transformed.rb +58 -0
  18. data/lib/.rbnext/3.0/yesql/common/adapter.rb +18 -0
  19. data/lib/.rbnext/3.0/yesql/config/configuration.rb +32 -0
  20. data/lib/.rbnext/3.0/yesql/errors/file_path_does_not_exist_error.rb +43 -0
  21. data/lib/.rbnext/3.0/yesql/errors/no_bindings_provided_error.rb +41 -0
  22. data/lib/.rbnext/3.0/yesql/params/output.rb +26 -0
  23. data/lib/.rbnext/3.0/yesql/query/performer.rb +44 -0
  24. data/lib/.rbnext/3.0/yesql/query/result.rb +41 -0
  25. data/lib/.rbnext/3.0/yesql/query/transform_result.rb +48 -0
  26. data/lib/.rbnext/3.0/yesql/statement.rb +44 -0
  27. data/lib/.rbnext/3.0/yesql/utils/read.rb +20 -0
  28. data/lib/yesql.rb +25 -31
  29. data/lib/yesql/bindings/extract.rb +15 -21
  30. data/lib/yesql/bindings/extractor.rb +21 -21
  31. data/lib/yesql/bindings/transformed.rb +8 -11
  32. data/lib/yesql/bindings/utils.rb +7 -5
  33. data/lib/yesql/common/adapter.rb +6 -13
  34. data/lib/yesql/config/configuration.rb +4 -5
  35. data/lib/yesql/errors/file_path_does_not_exist_error.rb +22 -17
  36. data/lib/yesql/errors/no_bindings_provided_error.rb +18 -19
  37. data/lib/yesql/errors/output_argument_error.rb +13 -4
  38. data/lib/yesql/params/output.rb +6 -14
  39. data/lib/yesql/query/performer.rb +13 -42
  40. data/lib/yesql/query/result.rb +12 -17
  41. data/lib/yesql/query/transform_result.rb +11 -21
  42. data/lib/yesql/statement.rb +19 -24
  43. data/lib/yesql/utils/read.rb +11 -8
  44. data/lib/yesql/version.rb +1 -1
  45. metadata +47 -17
  46. data/.gitignore +0 -4
  47. data/.rubocop.yml +0 -20
  48. data/Gemfile +0 -9
  49. data/Gemfile.lock +0 -167
  50. data/Rakefile +0 -1
  51. data/bin/console +0 -14
  52. data/bin/setup +0 -8
  53. data/lib/yesql/errors/cache_expiration_error.rb +0 -18
  54. data/yesql.gemspec +0 -28
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module YeSQL
3
+ module ::YeSQL
4
4
  module Bindings
5
5
  module Utils
6
+ include ::YeSQL::Utils::Read
7
+
6
8
  def statement_binds(extractor)
7
- ::YeSQL::Utils::Read.statement(file_path, readable: true)
8
- .scan(::YeSQL::BIND_REGEX).map do |(bind)|
9
- extractor[bind.to_sym][:bind].values_at(:vals, :vars)
10
- end
9
+ statement(readable: true)
10
+ .scan(::YeSQL::BIND_REGEX)
11
+ .map(&:first)
12
+ .map { extractor[_1.to_sym][:bind].values_at(:vals, :vars) }
11
13
  end
12
14
  end
13
15
  end
@@ -1,25 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
3
+ require "forwardable"
4
4
 
5
5
  module ::YeSQL
6
6
  module Common
7
7
  module Adapter
8
- extend Forwardable
8
+ extend ::Forwardable
9
9
 
10
- # `adapter` might be a complex object, but
11
- # for the sake of brevity it's just a string
12
- def adapter
13
- ::ActiveRecord::Base.connection.adapter_name
14
- end
10
+ def mysql? = adapter == "Mysql2"
11
+ def pg? = adapter == "PostgreSQL"
15
12
 
16
- def mysql?
17
- adapter == 'Mysql2'
18
- end
13
+ private
19
14
 
20
- def pg?
21
- adapter == 'PostgreSQL'
22
- end
15
+ def adapter = ::ActiveRecord::Base.connection.adapter_name
23
16
  end
24
17
  end
25
18
  end
@@ -3,20 +3,19 @@
3
3
  module ::YeSQL
4
4
  module Config
5
5
  class Configuration
6
- attr_accessor :path
6
+ attr_accessor :connection, :path
7
7
 
8
- DEFAULT_PATH = 'app/yesql'
8
+ DEFAULT_PATH = "app/yesql"
9
9
 
10
10
  def initialize
11
+ @connection = ""
11
12
  @path = DEFAULT_PATH
12
13
  end
13
14
  end
14
15
  end
15
16
 
16
17
  class << self
17
- def config
18
- @config ||= ::YeSQL::Configuration.new
19
- end
18
+ def config = @config ||= ::YeSQL::Configuration.new
20
19
 
21
20
  def configure
22
21
  yield config if block_given?
@@ -1,17 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module YeSQL
3
+ module ::YeSQL
4
4
  module Errors
5
- module FilePathDoesNotExistError
6
- def validate_file_path_existence(file_path)
7
- return if file_exists?(file_path)
5
+ class FilePathDoesNotExistError
6
+ def initialize(file_path)
7
+ @file_path = file_path
8
+ end
8
9
 
9
- raise NotImplementedError, format(MESSAGE, available_files: available_files,
10
- file_path: file_path, path: ::YeSQL.config.path)
10
+ def validate_file_path_existence
11
+ return if file_exists?
12
+
13
+ raise(
14
+ ::NotImplementedError,
15
+ format(
16
+ MESSAGE,
17
+ available_files: available_files,
18
+ file_path: file_path,
19
+ path: ::YeSQL.config.path
20
+ )
21
+ )
11
22
  end
12
23
 
13
24
  private
14
25
 
26
+ attr_reader :file_path
27
+
15
28
  MESSAGE = <<~MSG
16
29
 
17
30
  SQL file "%<file_path>s" does not exist in %<path>s.
@@ -22,17 +35,9 @@ module YeSQL
22
35
  MSG
23
36
  private_constant :MESSAGE
24
37
 
25
- def file_exists?(file_path)
26
- path_files.any? { |filename| filename.include?("#{file_path}.sql") }
27
- end
28
-
29
- def available_files
30
- path_files.map { |file| "- #{file}\n" }.join
31
- end
32
-
33
- def path_files
34
- @path_files ||= Dir["#{::YeSQL.config.path}/**/*.sql"]
35
- end
38
+ def file_exists? = path_files.any? { _1.include?("#{file_path}.sql") }
39
+ def path_files = @path_files ||= Dir["#{::YeSQL.config.path}/**/*.sql"]
40
+ def available_files = path_files.map { "- #{_1}\n" }.join
36
41
  end
37
42
  end
38
43
  end
@@ -1,20 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql/utils/read'
3
+ require "yesql/utils/read"
4
4
 
5
5
  module ::YeSQL
6
6
  module Errors
7
- module NoBindingsProvidedError
8
- def validate_statement_bindings(binds, file_path)
9
- return unless statement_binds(file_path).size.positive?
7
+ class NoBindingsProvidedError
8
+ include ::YeSQL::Utils::Read
10
9
 
11
- format(MESSAGE, renderable_statement_binds(file_path)).tap do |message|
12
- raise ::ArgumentError, message unless binds.is_a?(::Hash) && !binds.empty?
13
- end
10
+ def initialize(binds, file_path)
11
+ @binds = binds
12
+ @file_path = file_path
13
+ end
14
+
15
+ def validate_statement_bindings
16
+ return unless statement_binds.size.positive?
17
+ return if expected_binds?
18
+
19
+ raise ::ArgumentError, format(MESSAGE, renderable_statement_binds)
14
20
  end
15
21
 
16
22
  private
17
23
 
24
+ attr_reader :binds, :file_path
25
+
18
26
  MESSAGE = <<~MSG
19
27
 
20
28
  YeSQL invoked without bindings.
@@ -25,18 +33,9 @@ module ::YeSQL
25
33
  MSG
26
34
  private_constant :MESSAGE
27
35
 
28
- def statement_binds(file_path)
29
- ::YeSQL::Utils::Read.statement(file_path)
30
- .scan(::YeSQL::BIND_REGEX).tap do |scanned_binds|
31
- break [] if scanned_binds.size.zero?
32
-
33
- break scanned_binds.sort
34
- end
35
- end
36
-
37
- def renderable_statement_binds(file_path)
38
- statement_binds(file_path).flatten.map { |bind| "- `#{bind}`\n" }.join
39
- end
36
+ def statement_binds = statement.scan(::YeSQL::BIND_REGEX).tap { break (_1 || []).sort }
37
+ def renderable_statement_binds = statement_binds.flatten.map { "- `#{_1}`\n" }.join
38
+ def expected_binds? = binds.is_a?(::Hash) && !binds.empty?
40
39
  end
41
40
  end
42
41
  end
@@ -1,14 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module YeSQL
3
+ module ::YeSQL
4
4
  module Errors
5
- module OutputArgumentError
6
- def validate_output_options(output)
5
+ class OutputArgumentError
6
+ def initialize(output)
7
+ @output = output
8
+ end
9
+
10
+ def validate_output_options
7
11
  return if output.nil?
12
+ return if OPTIONS.include?(output.to_sym)
8
13
 
9
- raise ArgumentError, format(MESSAGE, output) unless OPTIONS.include?(output.to_sym)
14
+ raise ArgumentError, format(MESSAGE, output)
10
15
  end
11
16
 
17
+ private
18
+
19
+ attr_reader :output
20
+
12
21
  MESSAGE = <<~MSG
13
22
  Unsupported `output` option given `%s`. Possible values are:
14
23
  - `columns`: returns an array with the columns from the result.
@@ -1,28 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
4
- require 'forwardable'
3
+ require "yesql"
4
+ require "forwardable"
5
5
 
6
6
  module ::YeSQL
7
7
  module Params
8
8
  class Output
9
- extend Forwardable
9
+ extend ::Forwardable
10
10
 
11
11
  def initialize(output)
12
12
  @output = output.to_s
13
13
  end
14
14
 
15
- def columns?
16
- output == 'columns'
17
- end
18
-
19
- def rows?
20
- output == 'rows'
21
- end
22
-
23
- def hash?
24
- output == 'hash'
25
- end
15
+ def columns? = output == "columns"
16
+ def rows? = output == "rows"
17
+ def hash? = output == "hash"
26
18
 
27
19
  def_delegator(:output, :to_sym)
28
20
 
@@ -1,58 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
4
- require 'yesql/bindings/utils'
5
- require 'yesql/common/adapter'
6
- require 'yesql/bindings/transformed'
7
- require 'yesql/query/result'
8
- require 'yesql/query/transform_result'
9
- require 'yesql/params/output'
10
-
11
- module YeSQL
3
+ require "yesql"
4
+ require "yesql/bindings/utils"
5
+ require "yesql/common/adapter"
6
+ require "yesql/bindings/transformed"
7
+ require "yesql/query/result"
8
+ require "yesql/query/transform_result"
9
+ require "yesql/params/output"
10
+
11
+ module ::YeSQL
12
12
  module Query
13
13
  class Performer
14
14
  include ::YeSQL::Bindings::Utils
15
15
 
16
- # rubocop:disable Metrics/ParameterLists
17
- def initialize(bind_statement:,
18
- bindings: {},
19
- cache: {},
20
- file_path:,
21
- output: :rows,
22
- prepare: false)
16
+ def initialize(bind_statement:, file_path:, bindings: {}, output: :rows, prepare: false)
23
17
  @bind_statement = bind_statement
24
- @cache = cache
25
- @cache_key = cache[:key] || file_path
26
- @expires_in = cache[:expires_in]
27
18
  @file_path = file_path
28
19
  @named_bindings = bindings.transform_keys(&:to_sym)
29
20
  @output = ::YeSQL::Params::Output.new(output)
30
21
  @prepare = prepare
31
22
  end
32
- # rubocop:enable Metrics/ParameterLists
33
-
34
- def call
35
- return transformed_result if cache.empty?
36
23
 
37
- Rails.cache.fetch(cache_key, expires_in: expires_in) { transformed_result }
38
- end
24
+ def call = ::YeSQL::Query::TransformResult.new(output: output, result: query_result).call
39
25
 
40
26
  private
41
27
 
42
- attr_reader :bind_statement,
43
- :cache,
44
- :cache_key,
45
- :expires_in,
46
- :file_path,
47
- :named_bindings,
48
- :output,
49
- :prepare,
50
- :rows
51
-
52
- def transformed_result
53
- @transformed_result ||=
54
- ::YeSQL::Query::TransformResult.new(output: output, result: query_result).call
55
- end
28
+ attr_reader :bind_statement, :file_path, :named_bindings, :output, :prepare
56
29
 
57
30
  def query_result
58
31
  @query_result ||= ::YeSQL::Query::Result.new(binds: binds,
@@ -65,9 +38,7 @@ module YeSQL
65
38
  ::YeSQL::Bindings::Transformed.new(statement_binds: statement_binds(extractor)).call
66
39
  end
67
40
 
68
- def extractor
69
- ::YeSQL::Bindings::Extractor.new(bindings: named_bindings).call
70
- end
41
+ def extractor = ::YeSQL::Bindings::Extractor.new(bindings: named_bindings).call
71
42
  end
72
43
  end
73
44
  end
@@ -1,46 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
4
- require 'forwardable'
5
- require 'yesql/common/adapter'
3
+ require "yesql"
4
+ require "forwardable"
5
+ require "yesql/common/adapter"
6
6
 
7
7
  module ::YeSQL
8
8
  module Query
9
9
  class Result
10
- extend Forwardable
10
+ extend ::Forwardable
11
11
 
12
12
  include ::YeSQL::Common::Adapter
13
13
 
14
- def initialize(binds: [], bind_statement:, file_path:, prepare:)
14
+ def initialize(bind_statement:, file_path:, prepare:, binds: [])
15
15
  @binds = binds
16
16
  @bind_statement = bind_statement
17
- @connection = ActiveRecord::Base.connection
18
17
  @file_path = file_path
19
18
  @prepare_option = prepare
20
19
  end
21
20
 
22
21
  def call
23
- return view_result if view?
24
- return rails5_result if ::Rails::VERSION::MAJOR == 5 && mysql?
22
+ return view_result if view?
23
+ return rails5_result if ::ActiveRecord::VERSION::MAJOR == 5 && mysql?
25
24
 
26
25
  exec_query(bound, file_path, binds, prepare: prepare_option)
27
26
  end
28
27
 
29
28
  private
30
29
 
31
- attr_reader :binds, :bind_statement, :connection, :file_path, :prepare_option
30
+ attr_reader :binds, :bind_statement, :file_path, :prepare_option
32
31
 
33
32
  def_delegators(:bind_statement, :bound, :to_s, :view?)
34
- def_delegators(:connection, :exec_query, :raw_connection)
33
+ def_delegators(:connection, :exec_query, :raw_connection)
35
34
  def_delegators(:raw_connection, :prepare)
36
35
 
37
- def view_result
38
- exec_query(bound)
39
- end
40
-
41
- def rails5_result
42
- prepare(bound).execute(*binds)
43
- end
36
+ def view_result = exec_query(bound)
37
+ def rails5_result = prepare(bound).execute(*binds)
38
+ def connection = @connection ||= ActiveRecord::Base.connection
44
39
  end
45
40
  end
46
41
  end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yesql'
4
- require 'yesql/common/adapter'
5
- require 'forwardable'
3
+ require "yesql"
4
+ require "yesql/common/adapter"
5
+ require "forwardable"
6
6
 
7
7
  module ::YeSQL
8
8
  module Query
9
9
  class TransformResult
10
- extend Forwardable
10
+ extend ::Forwardable
11
11
 
12
12
  include ::YeSQL::Common::Adapter
13
13
 
@@ -17,7 +17,7 @@ module ::YeSQL
17
17
  end
18
18
 
19
19
  def call
20
- if ::Rails::VERSION::MAJOR == 5 && mysql?
20
+ if rails_5? && mysql?
21
21
  return columns if columns?
22
22
  return rows_values if rows?
23
23
  return array_of_symbol_hashes if hash?
@@ -32,27 +32,17 @@ module ::YeSQL
32
32
 
33
33
  attr_reader :output, :result
34
34
 
35
- def_delegators(:result, :rows, :to_a)
35
+ def_delegators(:result, :fields, :rows, :to_a)
36
36
  def_delegators(:output, :columns?, :hash?, :rows?)
37
37
 
38
- def rows_values
39
- to_a.map { |e| e.respond_to?(:values) ? e.values : e }
40
- end
41
-
42
38
  def array_of_symbol_hashes
43
- to_a.tap { |rows| break hashed_rows(rows) if ::Rails::VERSION::MAJOR == 5 }
44
- .map { |e| e.respond_to?(:symbolize_keys) ? e.symbolize_keys : e }
45
- end
46
-
47
- def hashed_rows(rows)
48
- rows.map { |row| columns.zip(row).to_h }
39
+ to_a.tap { break hashed_rows(_1) if rails_5? }.map { _1&.symbolize_keys || _1 }
49
40
  end
50
41
 
51
- def columns
52
- return result.fields if result.respond_to?(:fields)
53
-
54
- result.columns
55
- end
42
+ def columns = fields || result.columns
43
+ def rows_values = to_a.map { _1.respond_to?(:values) ? _1.values : _1 }
44
+ def hashed_rows(rows) = rows.map { columns.zip(_1).to_h }
45
+ def rails_5? = ::ActiveRecord::VERSION::MAJOR == 5
56
46
  end
57
47
  end
58
48
  end