active_record_extended 1.2.0 → 2.0.3

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 +4 -4
  2. data/README.md +85 -7
  3. data/lib/active_record_extended/active_record.rb +2 -11
  4. data/lib/active_record_extended/active_record/relation_patch.rb +21 -4
  5. data/lib/active_record_extended/arel.rb +1 -0
  6. data/lib/active_record_extended/arel/nodes.rb +24 -21
  7. data/lib/active_record_extended/arel/predications.rb +3 -2
  8. data/lib/active_record_extended/arel/sql_literal.rb +16 -0
  9. data/lib/active_record_extended/arel/visitors/postgresql_decorator.rb +1 -1
  10. data/lib/active_record_extended/query_methods/any_of.rb +5 -4
  11. data/lib/active_record_extended/query_methods/either.rb +2 -1
  12. data/lib/active_record_extended/query_methods/inet.rb +6 -2
  13. data/lib/active_record_extended/query_methods/json.rb +14 -17
  14. data/lib/active_record_extended/query_methods/select.rb +13 -12
  15. data/lib/active_record_extended/query_methods/unionize.rb +13 -7
  16. data/lib/active_record_extended/query_methods/where_chain.rb +17 -8
  17. data/lib/active_record_extended/query_methods/window.rb +93 -0
  18. data/lib/active_record_extended/query_methods/with_cte.rb +104 -37
  19. data/lib/active_record_extended/utilities/order_by.rb +11 -30
  20. data/lib/active_record_extended/utilities/support.rb +21 -18
  21. data/lib/active_record_extended/version.rb +1 -1
  22. data/spec/query_methods/any_of_spec.rb +2 -2
  23. data/spec/query_methods/either_spec.rb +11 -0
  24. data/spec/query_methods/json_spec.rb +5 -5
  25. data/spec/query_methods/select_spec.rb +13 -13
  26. data/spec/query_methods/unionize_spec.rb +5 -5
  27. data/spec/query_methods/window_spec.rb +51 -0
  28. data/spec/query_methods/with_cte_spec.rb +12 -2
  29. data/spec/spec_helper.rb +1 -1
  30. data/spec/sql_inspections/any_of_sql_spec.rb +2 -2
  31. data/spec/sql_inspections/contains_sql_queries_spec.rb +8 -8
  32. data/spec/sql_inspections/either_sql_spec.rb +19 -3
  33. data/spec/sql_inspections/json_sql_spec.rb +7 -1
  34. data/spec/sql_inspections/unionize_sql_spec.rb +2 -2
  35. data/spec/sql_inspections/window_sql_spec.rb +98 -0
  36. data/spec/sql_inspections/with_cte_sql_spec.rb +30 -1
  37. data/spec/support/models.rb +18 -0
  38. metadata +23 -20
  39. data/lib/active_record_extended/patch/5_0/predicate_builder_decorator.rb +0 -87
  40. data/lib/active_record_extended/patch/5_0/regex_match.rb +0 -10
@@ -24,8 +24,8 @@ module ActiveRecordExtended
24
24
  return false unless order_by && order_by.presence.present?
25
25
 
26
26
  to_ordered_table_path(order_by)
27
- .tap(&method(:process_ordering_arguments!))
28
- .tap(&method(:scope_preprocess_order_args))
27
+ .tap { |order_args| process_ordering_arguments!(order_args) }
28
+ .tap { |order_args| scope_preprocess_order_args(order_args) }
29
29
  end
30
30
 
31
31
  #
@@ -60,34 +60,15 @@ module ActiveRecordExtended
60
60
  end
61
61
  end
62
62
 
63
- # We'll need to preprocess these arguments for allowing `ActiveRecord::Relation#preprocess_order_args`,
64
- # to check for sanitization issues and convert over to `Arel::Nodes::[Ascending/Descending]`.
65
- # Without reflecting / prepending the parent's table name.
66
- #
67
- if ActiveRecord.gem_version < Gem::Version.new("5.1")
68
- # TODO: Rails 5.0.x order logic will *always* append the parents name to the column when its an HASH obj
69
- # We should really do this stuff better. Maybe even just ignore `preprocess_order_args` altogether?
70
- # Maybe I'm just stupidly over paranoid on just the 'ORDER BY' for some odd reason.
71
- def process_ordering_arguments!(ordering_args)
72
- ordering_args.flatten!
73
- ordering_args.compact!
74
- ordering_args.map! do |arg|
75
- next to_arel_sql(arg) unless arg.is_a?(Hash) # ActiveRecord will reflect if an argument is a symbol
76
- arg.each_with_object([]) do |(field, dir), ordering_object|
77
- ordering_object << to_arel_sql(field).send(dir.to_s.downcase)
78
- end
79
- end.flatten!
80
- end
81
- else
82
- def process_ordering_arguments!(ordering_args)
83
- ordering_args.flatten!
84
- ordering_args.compact!
85
- ordering_args.map! do |arg|
86
- next to_arel_sql(arg) unless arg.is_a?(Hash) # ActiveRecord will reflect if an argument is a symbol
87
- arg.each_with_object({}) do |(field, dir), ordering_obj|
88
- # ActiveRecord will not reflect if the Hash keys are a `Arel::Nodes::SqlLiteral` klass
89
- ordering_obj[to_arel_sql(field)] = dir.to_s.downcase
90
- end
63
+ def process_ordering_arguments!(ordering_args)
64
+ ordering_args.flatten!
65
+ ordering_args.compact!
66
+ ordering_args.map! do |arg|
67
+ next to_arel_sql(arg) unless arg.is_a?(Hash) # ActiveRecord will reflect if an argument is a symbol
68
+
69
+ arg.each_with_object({}) do |(field, dir), ordering_obj|
70
+ # ActiveRecord will not reflect if the Hash keys are a `Arel::Nodes::SqlLiteral` klass
71
+ ordering_obj[to_arel_sql(field)] = dir.to_s.downcase
91
72
  end
92
73
  end
93
74
  end
@@ -20,7 +20,7 @@ module ActiveRecordExtended
20
20
 
21
21
  def flatten_safely(values, &block)
22
22
  unless values.is_a?(Array)
23
- values = yield values if block_given?
23
+ values = yield values if block
24
24
  return [values]
25
25
  end
26
26
 
@@ -30,7 +30,7 @@ module ActiveRecordExtended
30
30
  # Applies aliases to the given query
31
31
  # Ex: `SELECT * FROM users` => `(SELECT * FROM users) AS "members"`
32
32
  def nested_alias_escape(query, alias_name)
33
- sql_query = Arel::Nodes::Grouping.new(to_arel_sql(query))
33
+ sql_query = generate_grouping(query)
34
34
  Arel::Nodes::As.new(sql_query, to_arel_sql(double_quote(alias_name)))
35
35
  end
36
36
 
@@ -81,7 +81,7 @@ module ActiveRecordExtended
81
81
  else
82
82
  replicate_klass = from.respond_to?(:unscoped) ? from.unscoped : @scope.unscoped
83
83
  replicate_klass.from(from.dup, reference_key)
84
- end
84
+ end.unscope(:where)
85
85
  end
86
86
 
87
87
  # Will carry defined CTE tables from the nested sub-query and gradually pushes it up to the parents query stack
@@ -91,20 +91,12 @@ module ActiveRecordExtended
91
91
  def pipe_cte_with!(subquery)
92
92
  return self unless subquery.try(:with_values?)
93
93
 
94
- cte_ary = flatten_safely(subquery.with_values)
95
- subquery.with_values = nil # Remove nested queries with values
96
-
97
- # Add subquery's CTE's to the parents query stack. (READ THE SPECIAL NOTE ABOVE!)
94
+ # Add subquery CTE's to the parents query stack. (READ THE SPECIAL NOTE ABOVE!)
98
95
  if @scope.with_values?
99
- # combine top-level and lower level queries `.with` values into 1 structure
100
- with_hash = cte_ary.each_with_object(@scope.with_values.first) do |from_cte, hash|
101
- hash.reverse_merge!(from_cte)
102
- end
103
-
104
- @scope.with_values = [with_hash]
96
+ @scope.cte.pipe_cte_with!(subquery.cte)
105
97
  else
106
98
  # Top level has no with values
107
- @scope.with!(*cte_ary)
99
+ @scope.with!(subquery.cte)
108
100
  end
109
101
 
110
102
  self
@@ -143,13 +135,13 @@ module ActiveRecordExtended
143
135
  # Converts a potential subquery into a compatible Arel SQL node.
144
136
  #
145
137
  # Note:
146
- # We convert relations to SQL to maintain compatibility with Rails 5.[0/1].
138
+ # We convert relations to SQL to maintain compatibility with Rails 5.1.
147
139
  # Only Rails 5.2+ maintains bound attributes in Arel, so its better to be safe then sorry.
148
- # When we drop support for Rails 5.[0/1], we then can then drop the '.to_sql' conversation
140
+ # When we drop support for Rails 5.1, we then can then drop the '.to_sql' conversation
149
141
 
150
142
  def to_arel_sql(value)
151
143
  case value
152
- when Arel::Node, Arel::Nodes::SqlLiteral, nil
144
+ when Arel::Nodes::Node, Arel::Nodes::SqlLiteral, nil
153
145
  value
154
146
  when ActiveRecord::Relation
155
147
  Arel.sql(value.spawn.to_sql)
@@ -160,13 +152,24 @@ module ActiveRecordExtended
160
152
 
161
153
  def group_when_needed(arel_or_rel_query)
162
154
  return arel_or_rel_query unless needs_to_be_grouped?(arel_or_rel_query)
163
- Arel::Nodes::Grouping.new(to_arel_sql(arel_or_rel_query))
155
+
156
+ generate_grouping(arel_or_rel_query)
164
157
  end
165
158
 
166
159
  def needs_to_be_grouped?(query)
167
160
  query.respond_to?(:to_sql) || (query.is_a?(String) && /^SELECT.+/i.match?(query))
168
161
  end
169
162
 
163
+ def generate_grouping(expr)
164
+ ::Arel::Nodes::Grouping.new(to_arel_sql(expr))
165
+ end
166
+
167
+ def generate_named_function(function_name, *args)
168
+ args.map! { |arg| to_arel_sql(arg) }
169
+ function_name = function_name.to_s.upcase
170
+ ::Arel::Nodes::NamedFunction.new(to_arel_sql(function_name), args)
171
+ end
172
+
170
173
  def key_generator
171
174
  A_TO_Z_KEYS.sample
172
175
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordExtended
4
- VERSION = "1.2.0"
4
+ VERSION = "2.0.3"
5
5
  end
@@ -61,7 +61,7 @@ RSpec.describe "Active Record Any / None of Methods" do
61
61
  it "Return matched records of a joined table on the parent level" do
62
62
  query = Tag.joins(:user).where.any_of(
63
63
  { users: { personal_id: 1 } },
64
- { users: { personal_id: 3 } },
64
+ { users: { personal_id: 3 } }
65
65
  )
66
66
 
67
67
  expect(query).to include(tag_one, tag_three)
@@ -120,7 +120,7 @@ RSpec.describe "Active Record Any / None of Methods" do
120
120
  it "Return matched records of a joined table on the parent level" do
121
121
  query = Tag.joins(:user).where.none_of(
122
122
  { users: { personal_id: 1 } },
123
- { users: { personal_id: 3 } },
123
+ { users: { personal_id: 3 } }
124
124
  )
125
125
 
126
126
  expect(query).to include(tag_two)
@@ -23,6 +23,17 @@ RSpec.describe "Active Record Either Methods" do
23
23
  expect(query).to_not include(three)
24
24
  end
25
25
  end
26
+
27
+ context "Through association .either_joins/2" do
28
+ let!(:four) { User.create! }
29
+ let!(:group) { Group.create!(users: [four]) }
30
+
31
+ it "Should only only return records that belong to profile L or has group" do
32
+ query = User.either_joins(:profile_l, :groups)
33
+ expect(query).to include(one, four)
34
+ expect(query).to_not include(three, two)
35
+ end
36
+ end
26
37
  end
27
38
 
28
39
  describe ".either_order/2" do
@@ -47,7 +47,7 @@ RSpec.describe "Active Record JSON methods" do
47
47
  end
48
48
 
49
49
  it "allows for casting results in an aggregate-able Array function" do
50
- query = User.select(:id).select_row_to_json(sub_query, key: :tag_row, as: :results, cast_as_array: true)
50
+ query = User.select(:id).select_row_to_json(sub_query, key: :tag_row, as: :results, cast_with: :array)
51
51
  expect(query.take.results).to be_a(Array).and(be_present)
52
52
  expect(query.take.results.first).to be_a(Hash)
53
53
  end
@@ -61,14 +61,14 @@ RSpec.describe "Active Record JSON methods" do
61
61
 
62
62
  describe ".json_build_object" do
63
63
  let(:sub_query) do
64
- User.select_row_to_json(from: User.select(:id), cast_as_array: true, as: :ids).where(id: user_one.id)
64
+ User.select_row_to_json(from: User.select(:id), cast_with: :array, as: :ids).where(id: user_one.id)
65
65
  end
66
66
 
67
67
  it "defaults the column alias if one is not provided" do
68
68
  query = User.json_build_object(:personal, sub_query)
69
69
  expect(query.size).to eq(1)
70
70
  expect(query.take.results).to match(
71
- "personal" => match("ids" => match_array([{ "id" => user_one.id }, { "id" => user_two.id }])),
71
+ "personal" => match("ids" => match_array([{ "id" => user_one.id }, { "id" => user_two.id }]))
72
72
  )
73
73
  end
74
74
 
@@ -98,7 +98,7 @@ RSpec.describe "Active Record JSON methods" do
98
98
  :personal,
99
99
  sub_query.where.not(id: user_one),
100
100
  value: "COALESCE(array_agg(\"personal\"), '{}')",
101
- as: :cool_dudes,
101
+ as: :cool_dudes
102
102
  )
103
103
 
104
104
  expect(query.take.cool_dudes["personal"]).to be_a(Array).and(be_empty)
@@ -110,7 +110,7 @@ RSpec.describe "Active Record JSON methods" do
110
110
  :personal,
111
111
  sub_query.where.not(id: user_one),
112
112
  value: "COALESCE(array_agg(personal), '{}')",
113
- as: :cool_dudes,
113
+ as: :cool_dudes
114
114
  )
115
115
  end.to output.to_stderr
116
116
  end
@@ -15,7 +15,7 @@ RSpec.describe "Active Record Select Methods" do
15
15
  it "can accept a subquery" do
16
16
  subquery = Tag.select("count(*)").joins("JOIN users u ON tags.user_id = u.id").where("u.ip = users.ip")
17
17
  query =
18
- User.foster_select(tag_count: [subquery, cast_with: :array_agg, distinct: true])
18
+ User.foster_select(tag_count: [subquery, { cast_with: :array_agg, distinct: true }])
19
19
  .joins(:hm_tags)
20
20
  .group(:ip)
21
21
  .take
@@ -25,8 +25,8 @@ RSpec.describe "Active Record Select Methods" do
25
25
 
26
26
  it "can be ordered" do
27
27
  query = User.foster_select(
28
- asc_ordered_numbers: [:number, cast_with: :array_agg, order_by: { number: :asc }],
29
- desc_ordered_numbers: [:number, cast_with: :array_agg, order_by: { number: :desc }],
28
+ asc_ordered_numbers: [:number, { cast_with: :array_agg, order_by: { number: :asc } }],
29
+ desc_ordered_numbers: [:number, { cast_with: :array_agg, order_by: { number: :desc } }]
30
30
  ).take
31
31
 
32
32
  expect(query.asc_ordered_numbers).to eq(number_set.to_a.sort)
@@ -50,10 +50,10 @@ RSpec.describe "Active Record Select Methods" do
50
50
 
51
51
  it "will return a boolean expression" do
52
52
  query = User.foster_select(
53
- truthly_expr: ["users.number > 0", cast_with: :bool_and],
54
- falsey_expr: ["users.number > 200", cast_with: :bool_and],
55
- other_true_expr: ["users.number > 4", cast_with: :bool_or],
56
- other_false_expr: ["users.number > 6", cast_with: :bool_or],
53
+ truthly_expr: ["users.number > 0", { cast_with: :bool_and }],
54
+ falsey_expr: ["users.number > 200", { cast_with: :bool_and }],
55
+ other_true_expr: ["users.number > 4", { cast_with: :bool_or }],
56
+ other_false_expr: ["users.number > 6", { cast_with: :bool_or }]
57
57
  ).take
58
58
 
59
59
  expect(query.truthly_expr).to be_truthy
@@ -67,19 +67,19 @@ RSpec.describe "Active Record Select Methods" do
67
67
  before { 2.times.flat_map { |i| Array.new(2) { |j| User.create!(number: (i + 1) * j + 3) } } }
68
68
 
69
69
  it "max" do
70
- query = User.foster_select(max_num: [:number, cast_with: :max]).take
70
+ query = User.foster_select(max_num: [:number, { cast_with: :max }]).take
71
71
  expect(query.max_num).to eq(5)
72
72
  end
73
73
 
74
74
  it "min" do
75
- query = User.foster_select(max_num: [:number, cast_with: :min]).take
75
+ query = User.foster_select(max_num: [:number, { cast_with: :min }]).take
76
76
  expect(query.max_num).to eq(3)
77
77
  end
78
78
 
79
79
  it "sum" do
80
80
  query = User.foster_select(
81
- num_sum: [:number, cast_with: :sum],
82
- distinct_sum: [:number, cast_with: :sum, distinct: true],
81
+ num_sum: [:number, { cast_with: :sum }],
82
+ distinct_sum: [:number, { cast_with: :sum, distinct: true }]
83
83
  ).take
84
84
 
85
85
  expect(query.num_sum).to eq(15)
@@ -88,8 +88,8 @@ RSpec.describe "Active Record Select Methods" do
88
88
 
89
89
  it "avg" do
90
90
  query = User.foster_select(
91
- num_avg: [:number, cast_with: :avg],
92
- distinct_avg: [:number, cast_with: :avg, distinct: true],
91
+ num_avg: [:number, { cast_with: :avg }],
92
+ distinct_avg: [:number, { cast_with: :avg, distinct: true }]
93
93
  ).take
94
94
 
95
95
  expect(query.num_avg).to eq(3.75)
@@ -17,13 +17,13 @@ RSpec.describe "Active Record Union Methods" do
17
17
 
18
18
  it "should raise an error if the select statements do not align" do
19
19
  expect { misaligned_cmd.to_a }.to(
20
- raise_error(ActiveRecord::StatementInvalid, /each [[:alpha:]]+ query must have the same number of columns/),
20
+ raise_error(ActiveRecord::StatementInvalid, /each [[:alpha:]]+ query must have the same number of columns/)
21
21
  )
22
22
  end
23
23
 
24
24
  it "should raise an argument error if there are less then two union statements" do
25
25
  expect { lacking_union_cmd.to_a }.to(
26
- raise_error(ArgumentError, "You are required to provide 2 or more unions to join!"),
26
+ raise_error(ArgumentError, "You are required to provide 2 or more unions to join!")
27
27
  )
28
28
  end
29
29
  end
@@ -88,7 +88,7 @@ RSpec.describe "Active Record Union Methods" do
88
88
  query =
89
89
  User.union.intersect(
90
90
  User.select(:id, "profile_ls.likes").joins(:profile_l).where(profile_ls: { likes: 100 }),
91
- User.select(:id, "profile_ls.likes").joins(:profile_l).where("profile_ls.likes < 150"),
91
+ User.select(:id, "profile_ls.likes").joins(:profile_l).where("profile_ls.likes < 150")
92
92
  )
93
93
 
94
94
  expect(query.pluck(:id)).to have_attributes(size: 1).and(eq([user_one_pl.id]))
@@ -129,7 +129,7 @@ RSpec.describe "Active Record Union Methods" do
129
129
  query =
130
130
  User.union.all(
131
131
  User.where(id: user_one.id),
132
- User.where(id: user_three.id),
132
+ User.where(id: user_three.id)
133
133
  ).order_union(id: :desc)
134
134
 
135
135
  expect(query).to eq([user_three, user_one])
@@ -144,7 +144,7 @@ RSpec.describe "Active Record Union Methods" do
144
144
  query =
145
145
  User.union.intersect(
146
146
  User.where("id < ?", user_three.id),
147
- User.where("id >= ?", user_one.id),
147
+ User.where("id >= ?", user_one.id)
148
148
  ).order_union(id: :desc)
149
149
 
150
150
  expect(query).to eq([user_two, user_one])
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe "Active Record Window Function Query Methods" do
6
+ let!(:user_one) { User.create! }
7
+ let!(:user_two) { User.create! }
8
+
9
+ let!(:tag_one) { Tag.create!(user: user_one, tag_number: 1) }
10
+ let!(:tag_two) { Tag.create!(user: user_two, tag_number: 2) }
11
+
12
+ let!(:tag_three) { Tag.create!(user: user_one, tag_number: 3) }
13
+ let!(:tag_four) { Tag.create!(user: user_two, tag_number: 4) }
14
+
15
+ let(:tag_group1) { [tag_one, tag_three] }
16
+ let(:tag_group2) { [tag_two, tag_four] }
17
+
18
+ describe ".window_select" do
19
+ context "when using ROW_NUMBER() ordered in asc" do
20
+ let(:base_query) do
21
+ Tag.define_window(:w).partition_by(:user_id, order_by: :tag_number).select(:id)
22
+ end
23
+
24
+ it "should return tag_one with r_id 1 and tag_three with r_id 2" do
25
+ results = base_query.select_window(:row_number, over: :w, as: :r_id).group_by(&:id)
26
+ tag_group1.each.with_index { |tag, idx| expect(results[tag.id].first.r_id).to eq(idx + 1) }
27
+ end
28
+
29
+ it "should return tag_two with r_id 1 and tag_four with r_id 2" do
30
+ results = base_query.select_window(:row_number, over: :w, as: :r_id).group_by(&:id)
31
+ tag_group2.each.with_index { |tag, idx| expect(results[tag.id].first.r_id).to eq(idx + 1) }
32
+ end
33
+ end
34
+
35
+ context "when using ROW_NUMBER() ordered in desc" do
36
+ let(:base_query) do
37
+ Tag.define_window(:w).partition_by(:user_id, order_by: { tag_number: :desc }).select(:id)
38
+ end
39
+
40
+ it "should return tag_one with r_id 2 and tag_three with r_id 1" do
41
+ results = base_query.select_window(:row_number, over: :w, as: :r_id).group_by(&:id)
42
+ tag_group1.reverse_each.with_index { |tag, idx| expect(results[tag.id].first.r_id).to eq(idx + 1) }
43
+ end
44
+
45
+ it "should return tag_two with r_id 2 and tag_four with r_id 1" do
46
+ results = base_query.select_window(:row_number, over: :w, as: :r_id).group_by(&:id)
47
+ tag_group2.reverse_each.with_index { |tag, idx| expect(results[tag.id].first.r_id).to eq(idx + 1) }
48
+ end
49
+ end
50
+ end
51
+ end
@@ -3,8 +3,8 @@
3
3
  require "spec_helper"
4
4
 
5
5
  RSpec.describe "Active Record With CTE Query Methods" do
6
- let!(:user_one) { User.create! }
7
- let!(:user_two) { User.create! }
6
+ let!(:user_one) { User.create! }
7
+ let!(:user_two) { User.create! }
8
8
  let!(:profile_one) { ProfileL.create!(user_id: user_one.id, likes: 200) }
9
9
  let!(:profile_two) { ProfileL.create!(user_id: user_two.id, likes: 500) }
10
10
 
@@ -35,6 +35,16 @@ RSpec.describe "Active Record With CTE Query Methods" do
35
35
 
36
36
  expect(query).to match_array([user_one])
37
37
  end
38
+
39
+ it "should contain a unique list of ordered CTE keys when merging in multiple children" do
40
+ x = User.with(profile: ProfileL.where("likes < 300"))
41
+ y = User.with(profile: ProfileL.where("likes > 400"))
42
+ z = y.merge(x).joins("JOIN profile ON profile.id = users.id") # Y should reject X's CTE (FIFO)
43
+ query = User.with(my_profile: z).joins("JOIN my_profile ON my_profile.id = users.id")
44
+
45
+ expect(query.cte.with_keys).to eq([:profile, :my_profile])
46
+ expect(query).to match_array([user_two])
47
+ end
38
48
  end
39
49
  end
40
50
  end
data/spec/spec_helper.rb CHANGED
@@ -13,7 +13,7 @@ end
13
13
  ActiveRecord::Base.establish_connection(ENV["DATABASE_URL"])
14
14
 
15
15
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require File.expand_path(f) }
16
- Dir["#{File.dirname(__FILE__)}/**/*examples.rb"].each { |f| require f }
16
+ Dir["#{File.dirname(__FILE__)}/**/*examples.rb"].sort.each { |f| require f }
17
17
 
18
18
  RSpec.configure do |config|
19
19
  # Enable flags like --only-failures and --next-failure
@@ -5,8 +5,8 @@ require "spec_helper"
5
5
  RSpec.describe "Any / None of SQL Queries" do
6
6
  let(:equal_query) { '"users"."personal_id" = 1' }
7
7
  let(:or_query) { 'OR "users"."personal_id" = 2' }
8
- let(:equal_or) { equal_query + " " + or_query }
9
- let(:join_query) { /INNER JOIN \"tags\" ON \"tags\".\"user_id\" = \"users\".\"id/ }
8
+ let(:equal_or) { "#{equal_query} #{or_query}" }
9
+ let(:join_query) { /INNER JOIN "tags" ON "tags"."user_id" = "users"."id/ }
10
10
 
11
11
  describe "where.any_of/1" do
12
12
  it "should group different column arguments into nested or conditions" do