arel_toolkit 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/.travis.yml +8 -0
  4. data/CHANGELOG.md +56 -7
  5. data/Gemfile.lock +54 -1
  6. data/Guardfile +19 -12
  7. data/README.md +56 -2
  8. data/Rakefile +8 -0
  9. data/arel_toolkit.gemspec +6 -0
  10. data/bin/console +1 -0
  11. data/lib/arel/extensions/assignment.rb +22 -0
  12. data/lib/arel/extensions/at_time_zone.rb +30 -0
  13. data/lib/arel/extensions/contained_within_equals.rb +10 -0
  14. data/lib/arel/extensions/contains.rb +2 -2
  15. data/lib/arel/extensions/contains_equals.rb +10 -0
  16. data/lib/arel/extensions/delete_manager.rb +9 -0
  17. data/lib/arel/extensions/delete_statement.rb +7 -0
  18. data/lib/arel/extensions/distinct_from.rb +3 -16
  19. data/lib/arel/extensions/equality.rb +2 -4
  20. data/lib/arel/extensions/extract_from.rb +32 -0
  21. data/lib/arel/extensions/insert_manager.rb +5 -0
  22. data/lib/arel/extensions/insert_statement.rb +10 -3
  23. data/lib/arel/extensions/json_get_field.rb +10 -0
  24. data/lib/arel/extensions/json_get_object.rb +10 -0
  25. data/lib/arel/extensions/json_path_get_field.rb +10 -0
  26. data/lib/arel/extensions/json_path_get_object.rb +10 -0
  27. data/lib/arel/extensions/jsonb_all_key_exists.rb +10 -0
  28. data/lib/arel/extensions/jsonb_any_key_exists.rb +10 -0
  29. data/lib/arel/extensions/jsonb_key_exists.rb +10 -0
  30. data/lib/arel/extensions/named_argument.rb +29 -0
  31. data/lib/arel/extensions/not_distinct_from.rb +3 -16
  32. data/lib/arel/extensions/not_equal.rb +2 -4
  33. data/lib/arel/extensions/overlap.rb +1 -1
  34. data/lib/arel/extensions/overlaps.rb +40 -0
  35. data/lib/arel/extensions/overlay.rb +44 -0
  36. data/lib/arel/extensions/position.rb +32 -0
  37. data/lib/arel/extensions/select_manager.rb +9 -0
  38. data/lib/arel/extensions/substring.rb +38 -0
  39. data/lib/arel/extensions/transaction.rb +50 -0
  40. data/lib/arel/extensions/trim.rb +36 -0
  41. data/lib/arel/extensions/type_cast.rb +4 -0
  42. data/lib/arel/{sql_to_arel → extensions}/unbound_column_reference.rb +1 -1
  43. data/lib/arel/extensions/update_manager.rb +9 -0
  44. data/lib/arel/extensions/update_statement.rb +8 -0
  45. data/lib/arel/extensions/variable_set.rb +46 -0
  46. data/lib/arel/extensions/variable_show.rb +31 -0
  47. data/lib/arel/extensions.rb +26 -0
  48. data/lib/arel/middleware/chain.rb +97 -0
  49. data/lib/arel/middleware/postgresql_adapter.rb +26 -0
  50. data/lib/arel/middleware/railtie.rb +11 -0
  51. data/lib/arel/middleware.rb +23 -0
  52. data/lib/arel/sql_formatter.rb +59 -0
  53. data/lib/arel/sql_to_arel/error.rb +6 -0
  54. data/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb +112 -0
  55. data/lib/arel/sql_to_arel/pg_query_visitor.rb +271 -52
  56. data/lib/arel/sql_to_arel/result.rb +17 -0
  57. data/lib/arel/sql_to_arel.rb +4 -3
  58. data/lib/arel_toolkit/version.rb +1 -1
  59. data/lib/arel_toolkit.rb +2 -0
  60. metadata +120 -4
  61. data/lib/arel/sql_to_arel/frame_options.rb +0 -110
@@ -0,0 +1,10 @@
1
+ module Arel
2
+ module Nodes
3
+ # https://www.postgresql.org/docs/9.4/functions-json.html#FUNCTIONS-JSON-OP-TABLE
4
+ class JsonPathGetField < Arel::Nodes::InfixOperation
5
+ def initialize(left, right)
6
+ super(:'#>>', left, right)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Arel
2
+ module Nodes
3
+ # https://www.postgresql.org/docs/9.4/functions-json.html#FUNCTIONS-JSON-OP-TABLE
4
+ class JsonPathGetObject < Arel::Nodes::InfixOperation
5
+ def initialize(left, right)
6
+ super(:'#>', left, right)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Arel
2
+ module Nodes
3
+ # https://www.postgresql.org/docs/9.4/functions-json.html#FUNCTIONS-JSONB-OP-TABLE
4
+ class JsonbAllKeyExists < Arel::Nodes::InfixOperation
5
+ def initialize(left, right)
6
+ super(:'?&', left, right)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Arel
2
+ module Nodes
3
+ # https://www.postgresql.org/docs/9.4/functions-json.html#FUNCTIONS-JSONB-OP-TABLE
4
+ class JsonbAnyKeyExists < Arel::Nodes::InfixOperation
5
+ def initialize(left, right)
6
+ super(:'?|', left, right)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Arel
2
+ module Nodes
3
+ # https://www.postgresql.org/docs/9.4/functions-json.html#FUNCTIONS-JSONB-OP-TABLE
4
+ class JsonbKeyExists < Arel::Nodes::InfixOperation
5
+ def initialize(left, right)
6
+ super(:'?', left, right)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Nodes
6
+ class NamedArgument < Arel::Nodes::Node
7
+ attr_reader :name
8
+ attr_reader :value
9
+
10
+ def initialize(name, value)
11
+ @name = name
12
+ @value = value
13
+ end
14
+ end
15
+ end
16
+
17
+ module Visitors
18
+ class ToSql
19
+ def visit_Arel_Nodes_NamedArgument(o, collector)
20
+ collector << o.name
21
+ collector << ' => '
22
+ visit(o.value, collector)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ # rubocop:enable Naming/MethodName
29
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -1,22 +1,9 @@
1
- # rubocop:disable Naming/MethodName
2
- # rubocop:disable Naming/UncommunicativeMethodParamName
3
-
4
1
  module Arel
5
2
  module Nodes
6
- class NotDistinctFrom < Arel::Nodes::Binary
7
- end
8
- end
9
-
10
- module Visitors
11
- class ToSql
12
- def visit_Arel_Nodes_NotDistinctFrom(o, collector)
13
- visit o.left, collector
14
- collector << ' IS NOT DISTINCT FROM '
15
- visit o.right, collector
3
+ class NotDistinctFrom < Arel::Nodes::InfixOperation
4
+ def initialize(left, right)
5
+ super(:'IS NOT DISTINCT FROM', left, right)
16
6
  end
17
7
  end
18
8
  end
19
9
  end
20
-
21
- # rubocop:enable Naming/MethodName
22
- # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -6,15 +6,13 @@ module Arel
6
6
  class ToSql
7
7
  def visit_Arel_Nodes_NotEqual(o, collector)
8
8
  right = o.right
9
-
10
9
  collector = visit o.left, collector
11
10
 
12
- case right
13
- when Arel::Nodes::Unknown, Arel::Nodes::False, Arel::Nodes::True
11
+ if [Arel::Nodes::Unknown, Arel::Nodes::False, Arel::Nodes::True].include?(right.class)
14
12
  collector << ' IS NOT '
15
13
  visit right, collector
16
14
 
17
- when NilClass
15
+ elsif right.nil?
18
16
  collector << ' IS NOT NULL'
19
17
 
20
18
  else
@@ -1,7 +1,7 @@
1
1
  module Arel
2
2
  module Nodes
3
3
  # https://www.postgresql.org/docs/9.1/functions-array.html
4
- class Overlap < InfixOperation
4
+ class Overlap < Arel::Nodes::InfixOperation
5
5
  def initialize(left, right)
6
6
  super(:'&&', left, right)
7
7
  end
@@ -0,0 +1,40 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Nodes
6
+ # https://www.postgresql.org/docs/10/functions-string.html
7
+ class Overlaps < Arel::Nodes::Node
8
+ attr_reader :start1
9
+ attr_reader :end1
10
+ attr_reader :start2
11
+ attr_reader :end2
12
+
13
+ def initialize(start1, end1, start2, end2)
14
+ @start1 = start1
15
+ @end1 = end1
16
+ @start2 = start2
17
+ @end2 = end2
18
+ end
19
+ end
20
+ end
21
+
22
+ module Visitors
23
+ class ToSql
24
+ def visit_Arel_Nodes_Overlaps(o, collector)
25
+ collector << '('
26
+ visit o.start1, collector
27
+ collector << ', '
28
+ visit o.end1, collector
29
+ collector << ') OVERLAPS ('
30
+ visit o.start2, collector
31
+ collector << ', '
32
+ visit o.end2, collector
33
+ collector << ')'
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ # rubocop:enable Naming/MethodName
40
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -0,0 +1,44 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+ # rubocop:disable Metrics/AbcSize
4
+
5
+ module Arel
6
+ module Nodes
7
+ # https://www.postgresql.org/docs/10/functions-string.html
8
+ class Overlay < Arel::Nodes::Node
9
+ attr_reader :string
10
+ attr_reader :substring
11
+ attr_reader :start
12
+ attr_reader :length
13
+
14
+ def initialize(string, substring, start, length = nil)
15
+ @string = string
16
+ @substring = substring
17
+ @start = start
18
+ @length = length
19
+ end
20
+ end
21
+ end
22
+
23
+ module Visitors
24
+ class ToSql
25
+ def visit_Arel_Nodes_Overlay(o, collector)
26
+ collector << 'overlay('
27
+ visit o.string, collector
28
+ collector << ' placing '
29
+ visit o.substring, collector
30
+ collector << ' from '
31
+ visit o.start, collector
32
+ unless o.length.nil?
33
+ collector << ' for '
34
+ visit o.length, collector
35
+ end
36
+ collector << ')'
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ # rubocop:enable Naming/MethodName
43
+ # rubocop:enable Naming/UncommunicativeMethodParamName
44
+ # rubocop:enable Metrics/AbcSize
@@ -0,0 +1,32 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Nodes
6
+ # https://www.postgresql.org/docs/9.1/functions-string.html#FUNCTIONS-STRING-SQL
7
+ class Position < Arel::Nodes::Node
8
+ attr_reader :substring
9
+ attr_reader :string
10
+
11
+ def initialize(substring, string)
12
+ @substring = substring
13
+ @string = string
14
+ end
15
+ end
16
+ end
17
+
18
+ module Visitors
19
+ class ToSql
20
+ def visit_Arel_Nodes_Position(o, collector)
21
+ collector << 'position('
22
+ visit o.substring, collector
23
+ collector << ' in '
24
+ visit o.string, collector
25
+ collector << ')'
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ # rubocop:enable Naming/MethodName
32
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -0,0 +1,9 @@
1
+ Arel::SelectManager.class_eval do
2
+ def ==(other)
3
+ @ast == other.ast && @ctx == other.ctx
4
+ end
5
+
6
+ protected
7
+
8
+ attr_reader :ctx
9
+ end
@@ -0,0 +1,38 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Nodes
6
+ # https://www.postgresql.org/docs/10/functions-string.html
7
+ class Substring < Arel::Nodes::Node
8
+ attr_reader :string
9
+ attr_reader :pattern
10
+ attr_reader :escape
11
+
12
+ def initialize(string, pattern, escape)
13
+ @string = string
14
+ @pattern = pattern
15
+ @escape = escape
16
+ end
17
+ end
18
+ end
19
+
20
+ module Visitors
21
+ class ToSql
22
+ def visit_Arel_Nodes_Substring(o, collector)
23
+ collector << 'substring('
24
+ visit o.string, collector
25
+ collector << ' from '
26
+ visit o.pattern, collector
27
+ unless o.escape.nil?
28
+ collector << ' for '
29
+ visit o.escape, collector
30
+ end
31
+ collector << ')'
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ # rubocop:enable Naming/MethodName
38
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -0,0 +1,50 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+ # rubocop:disable Metrics/CyclomaticComplexity
4
+ # rubocop:disable Metrics/AbcSize
5
+
6
+ module Arel
7
+ module Nodes
8
+ # https://www.postgresql.org/docs/8.3/tutorial-transactions.html
9
+ class Transaction < Arel::Nodes::Node
10
+ attr_reader :type
11
+ attr_reader :options
12
+
13
+ def initialize(type, options)
14
+ @type = type
15
+ @options = options
16
+ end
17
+ end
18
+ end
19
+
20
+ module Visitors
21
+ class ToSql
22
+ def visit_Arel_Nodes_Transaction(o, collector)
23
+ case o.type
24
+ when 0
25
+ collector << 'BEGIN'
26
+ when 2
27
+ collector << 'COMMIT'
28
+ when 3
29
+ collector << 'ROLLBACK'
30
+ when 4
31
+ collector << 'SAVEPOINT '
32
+ collector << o.options.join(' ')
33
+ when 5
34
+ collector << 'RELEASE SAVEPOINT '
35
+ collector << o.options.join(' ')
36
+ when 6
37
+ collector << 'ROLLBACK TO '
38
+ collector << o.options.join(' ')
39
+ else
40
+ raise "Unknown transaction type `#{o.type}`"
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ # rubocop:enable Naming/MethodName
48
+ # rubocop:enable Naming/UncommunicativeMethodParamName
49
+ # rubocop:enable Metrics/CyclomaticComplexity
50
+ # rubocop:enable Metrics/AbcSize
@@ -0,0 +1,36 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Nodes
6
+ # https://www.postgresql.org/docs/10/functions-string.html
7
+ class Trim < Arel::Nodes::Node
8
+ attr_reader :type
9
+ attr_reader :substring
10
+ attr_reader :string
11
+
12
+ def initialize(type, substring, string)
13
+ @type = type
14
+ @substring = substring
15
+ @string = string
16
+ end
17
+ end
18
+ end
19
+
20
+ module Visitors
21
+ class ToSql
22
+ def visit_Arel_Nodes_Trim(o, collector)
23
+ collector << "trim(#{o.type} "
24
+ if o.substring
25
+ visit o.substring, collector
26
+ collector << ' from '
27
+ end
28
+ visit o.string, collector
29
+ collector << ')'
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ # rubocop:enable Naming/MethodName
36
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -12,6 +12,10 @@ module Arel
12
12
  @arg = arg
13
13
  @type_name = type_name
14
14
  end
15
+
16
+ def ==(other)
17
+ arg == other.arg && type_name == other.type_name
18
+ end
15
19
  end
16
20
  end
17
21
 
@@ -1,5 +1,5 @@
1
1
  module Arel
2
- module SqlToArel
2
+ module Nodes
3
3
  class UnboundColumnReference < ::Arel::Nodes::SqlLiteral; end
4
4
  end
5
5
  end
@@ -0,0 +1,9 @@
1
+ Arel::UpdateManager.class_eval do
2
+ def ==(other)
3
+ @ast == other.ast && @ctx == other.ctx
4
+ end
5
+
6
+ protected
7
+
8
+ attr_reader :ctx
9
+ end
@@ -8,6 +8,14 @@ module Arel
8
8
  attr_accessor :with
9
9
  attr_accessor :froms
10
10
  attr_accessor :returning
11
+
12
+ alias_method :old_initialize, :initialize
13
+ def initialize
14
+ old_initialize
15
+
16
+ @froms = []
17
+ @returning = []
18
+ end
11
19
  end
12
20
  end
13
21
 
@@ -0,0 +1,46 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Nodes
6
+ # https://www.postgresql.org/docs/9.3/sql-set.html
7
+ class VariableSet < Arel::Nodes::Node
8
+ attr_reader :type
9
+ attr_reader :args
10
+ attr_reader :name
11
+ attr_reader :local
12
+
13
+ def initialize(type, args, name, local)
14
+ @type = type
15
+ @args = args
16
+ @name = name
17
+ @local = local
18
+ end
19
+ end
20
+ end
21
+
22
+ module Visitors
23
+ class ToSql
24
+ def visit_Arel_Nodes_VariableSet(o, collector)
25
+ collector << 'SET '
26
+ collector << 'LOCAL ' if o.local
27
+
28
+ if o.name == 'timezone'
29
+ collector << 'TIME ZONE '
30
+ else
31
+ collector << o.name
32
+ collector << ' TO '
33
+ end
34
+
35
+ if o.args.empty?
36
+ collector << 'DEFAULT'
37
+ else
38
+ inject_join(o.args, collector, ', ')
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ # rubocop:enable Naming/MethodName
46
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -0,0 +1,31 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Nodes
6
+ # https://www.postgresql.org/docs/9.1/sql-show.html
7
+ class VariableShow < Arel::Nodes::Node
8
+ attr_reader :name
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ end
13
+ end
14
+ end
15
+
16
+ module Visitors
17
+ class ToSql
18
+ def visit_Arel_Nodes_VariableShow(o, collector)
19
+ collector << 'SHOW '
20
+ collector << if o.name == 'timezone'
21
+ 'TIME ZONE'
22
+ else
23
+ o.name
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ # rubocop:enable Naming/MethodName
31
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -44,6 +44,8 @@ require 'arel/extensions/bitwise_xor'
44
44
  require 'arel/extensions/exponentiation'
45
45
  require 'arel/extensions/contains'
46
46
  require 'arel/extensions/contained_by'
47
+ require 'arel/extensions/contained_within_equals'
48
+ require 'arel/extensions/contains_equals'
47
49
  require 'arel/extensions/overlap'
48
50
  require 'arel/extensions/select_statement'
49
51
  require 'arel/extensions/insert_statement'
@@ -64,6 +66,30 @@ require 'arel/extensions/equality'
64
66
  require 'arel/extensions/named_function'
65
67
  require 'arel/extensions/intersect_all'
66
68
  require 'arel/extensions/except_all'
69
+ require 'arel/extensions/select_manager'
70
+ require 'arel/extensions/insert_manager'
71
+ require 'arel/extensions/update_manager'
72
+ require 'arel/extensions/delete_manager'
73
+ require 'arel/extensions/at_time_zone'
74
+ require 'arel/extensions/extract_from'
75
+ require 'arel/extensions/json_get_object'
76
+ require 'arel/extensions/json_get_field'
77
+ require 'arel/extensions/json_path_get_object'
78
+ require 'arel/extensions/json_path_get_field'
79
+ require 'arel/extensions/jsonb_key_exists'
80
+ require 'arel/extensions/jsonb_any_key_exists'
81
+ require 'arel/extensions/jsonb_all_key_exists'
82
+ require 'arel/extensions/transaction'
83
+ require 'arel/extensions/unbound_column_reference'
84
+ require 'arel/extensions/assignment'
85
+ require 'arel/extensions/variable_set'
86
+ require 'arel/extensions/variable_show'
87
+ require 'arel/extensions/position'
88
+ require 'arel/extensions/overlay'
89
+ require 'arel/extensions/substring'
90
+ require 'arel/extensions/overlaps'
91
+ require 'arel/extensions/trim'
92
+ require 'arel/extensions/named_argument'
67
93
 
68
94
  module Arel
69
95
  module Extensions
@@ -0,0 +1,97 @@
1
+ module Arel
2
+ module Middleware
3
+ class Chain
4
+ def initialize(internal_middleware = [], internal_context = {})
5
+ @internal_middleware = internal_middleware
6
+ @internal_context = internal_context
7
+ end
8
+
9
+ def execute(sql, binds = [])
10
+ return sql if internal_middleware.length.zero?
11
+
12
+ result = Arel.sql_to_arel(sql, binds: binds)
13
+ updated_context = context.merge(original_sql: sql)
14
+
15
+ internal_middleware.each do |middleware_item|
16
+ result = result.map do |arel|
17
+ middleware_item.call(arel, updated_context)
18
+ end
19
+ end
20
+
21
+ result.to_sql
22
+ end
23
+
24
+ def current
25
+ internal_middleware.dup
26
+ end
27
+
28
+ def apply(middleware, &block)
29
+ continue_chain(middleware, internal_context, &block)
30
+ end
31
+
32
+ def only(middleware, &block)
33
+ continue_chain(middleware, internal_context, &block)
34
+ end
35
+
36
+ def none(&block)
37
+ continue_chain([], internal_context, &block)
38
+ end
39
+
40
+ def except(without_middleware, &block)
41
+ new_middleware = internal_middleware.reject do |middleware|
42
+ middleware == without_middleware
43
+ end
44
+
45
+ continue_chain(new_middleware, internal_context, &block)
46
+ end
47
+
48
+ def insert_before(new_middleware, existing_middleware, &block)
49
+ index = internal_middleware.index(existing_middleware)
50
+ updated_middleware = internal_middleware.insert(index, new_middleware)
51
+ continue_chain(updated_middleware, internal_context, &block)
52
+ end
53
+
54
+ def insert_after(new_middleware, existing_middleware, &block)
55
+ index = internal_middleware.index(existing_middleware)
56
+ updated_middleware = internal_middleware.insert(index + 1, new_middleware)
57
+ continue_chain(updated_middleware, internal_context, &block)
58
+ end
59
+
60
+ def context(new_context = nil, &block)
61
+ if new_context.nil? && !block.nil?
62
+ raise 'You cannot do a block statement while calling context without arguments'
63
+ end
64
+
65
+ return internal_context if new_context.nil?
66
+
67
+ continue_chain(internal_middleware, new_context, &block)
68
+ end
69
+
70
+ protected
71
+
72
+ attr_reader :internal_middleware
73
+ attr_reader :internal_context
74
+
75
+ private
76
+
77
+ def continue_chain(middleware, context, &block)
78
+ new_chain = Arel::Middleware::Chain.new(middleware, context)
79
+ maybe_execute_block(new_chain, &block)
80
+ end
81
+
82
+ def maybe_execute_block(new_chain, &block)
83
+ return new_chain if block.nil?
84
+
85
+ previous_chain = Middleware.current_chain
86
+ Arel::Middleware.current_chain = new_chain
87
+ yield block
88
+ ensure
89
+ Arel::Middleware.current_chain = previous_chain
90
+ end
91
+
92
+ def current_chain
93
+ Arel::Middleware.current_chain
94
+ end
95
+ end
96
+ end
97
+ end