active_record_extended 1.1.0 → 2.0.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +87 -15
  3. data/lib/active_record_extended.rb +2 -1
  4. data/lib/active_record_extended/active_record.rb +2 -9
  5. data/lib/active_record_extended/active_record/relation_patch.rb +21 -4
  6. data/lib/active_record_extended/arel.rb +2 -0
  7. data/lib/active_record_extended/arel/aggregate_function_name.rb +40 -0
  8. data/lib/active_record_extended/arel/nodes.rb +32 -41
  9. data/lib/active_record_extended/arel/predications.rb +4 -1
  10. data/lib/active_record_extended/arel/sql_literal.rb +16 -0
  11. data/lib/active_record_extended/arel/visitors/postgresql_decorator.rb +40 -1
  12. data/lib/active_record_extended/query_methods/any_of.rb +10 -8
  13. data/lib/active_record_extended/query_methods/either.rb +1 -1
  14. data/lib/active_record_extended/query_methods/inet.rb +7 -3
  15. data/lib/active_record_extended/query_methods/json.rb +156 -50
  16. data/lib/active_record_extended/query_methods/select.rb +118 -0
  17. data/lib/active_record_extended/query_methods/unionize.rb +14 -43
  18. data/lib/active_record_extended/query_methods/where_chain.rb +14 -6
  19. data/lib/active_record_extended/query_methods/window.rb +93 -0
  20. data/lib/active_record_extended/query_methods/with_cte.rb +102 -35
  21. data/lib/active_record_extended/utilities/order_by.rb +77 -0
  22. data/lib/active_record_extended/utilities/support.rb +178 -0
  23. data/lib/active_record_extended/version.rb +1 -1
  24. data/spec/query_methods/any_of_spec.rb +40 -40
  25. data/spec/query_methods/array_query_spec.rb +14 -14
  26. data/spec/query_methods/either_spec.rb +14 -14
  27. data/spec/query_methods/hash_query_spec.rb +11 -11
  28. data/spec/query_methods/inet_query_spec.rb +33 -31
  29. data/spec/query_methods/json_spec.rb +42 -27
  30. data/spec/query_methods/select_spec.rb +115 -0
  31. data/spec/query_methods/unionize_spec.rb +56 -56
  32. data/spec/query_methods/window_spec.rb +51 -0
  33. data/spec/query_methods/with_cte_spec.rb +22 -12
  34. data/spec/spec_helper.rb +1 -1
  35. data/spec/sql_inspections/any_of_sql_spec.rb +12 -12
  36. data/spec/sql_inspections/arel/aggregate_function_name_spec.rb +41 -0
  37. data/spec/sql_inspections/arel/array_spec.rb +7 -7
  38. data/spec/sql_inspections/arel/inet_spec.rb +7 -7
  39. data/spec/sql_inspections/contains_sql_queries_spec.rb +14 -14
  40. data/spec/sql_inspections/either_sql_spec.rb +11 -11
  41. data/spec/sql_inspections/json_sql_spec.rb +44 -8
  42. data/spec/sql_inspections/unionize_sql_spec.rb +27 -27
  43. data/spec/sql_inspections/window_sql_spec.rb +98 -0
  44. data/spec/sql_inspections/with_cte_sql_spec.rb +52 -23
  45. data/spec/support/models.rb +24 -4
  46. metadata +31 -20
  47. data/lib/active_record_extended/patch/5_0/predicate_builder_decorator.rb +0 -87
  48. data/lib/active_record_extended/utilities.rb +0 -141
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+
5
+ module ActiveRecordExtended
6
+ module Utilities
7
+ module OrderBy
8
+ def inline_order_by(arel_node, ordering_args)
9
+ return arel_node unless scope_preprocess_order_args(ordering_args)
10
+
11
+ Arel::Nodes::InfixOperation.new("ORDER BY", arel_node, ordering_args)
12
+ end
13
+
14
+ def scope_preprocess_order_args(ordering_args)
15
+ return false if ordering_args.blank? || !@scope.respond_to?(:preprocess_order_args, true)
16
+
17
+ # Sanitation check / resolver (ActiveRecord::Relation#preprocess_order_args)
18
+ @scope.send(:preprocess_order_args, ordering_args)
19
+ ordering_args
20
+ end
21
+
22
+ # Processes "ORDER BY" expressions for supported aggregate functions
23
+ def order_by_expression(order_by)
24
+ return false unless order_by && order_by.presence.present?
25
+
26
+ to_ordered_table_path(order_by)
27
+ .tap { |order_args| process_ordering_arguments!(order_args) }
28
+ .tap { |order_args| scope_preprocess_order_args(order_args) }
29
+ end
30
+
31
+ #
32
+ # Turns a hash into a dot notation path.
33
+ #
34
+ # Example:
35
+ # - Using pre-set directions:
36
+ # [{ products: { position: :asc, id: :desc } }]
37
+ # #=> [{ "products.position" => :asc, "products.id" => :desc }]
38
+ #
39
+ # - Using fallback directions:
40
+ # [{products: :position}]
41
+ # #=> [{"products.position" => :asc}]
42
+ #
43
+ def to_ordered_table_path(args)
44
+ flatten_safely(Array.wrap(args)) do |arg|
45
+ next arg unless arg.is_a?(Hash)
46
+
47
+ arg.each_with_object({}) do |(tbl_or_col, obj), new_hash|
48
+ if obj.is_a?(Hash)
49
+ obj.each_pair do |o_key, o_value|
50
+ new_hash["#{tbl_or_col}.#{o_key}"] = o_value
51
+ end
52
+ elsif ::ActiveRecord::QueryMethods::VALID_DIRECTIONS.include?(obj)
53
+ new_hash[tbl_or_col] = obj
54
+ elsif obj.nil?
55
+ new_hash[tbl_or_col.to_s] = :asc
56
+ else
57
+ new_hash["#{tbl_or_col}.#{obj}"] = :asc
58
+ end
59
+ end
60
+ end
61
+ end
62
+
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
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecordExtended
4
+ module Utilities
5
+ module Support
6
+ A_TO_Z_KEYS = ("a".."z").to_a.freeze
7
+
8
+ # We need to ensure we can flatten nested ActiveRecord::Relations
9
+ # that might have been nested due to the (splat)*args parameters
10
+ #
11
+ # Note: calling `Array.flatten[!]/1` will actually remove all AR relations from the array.
12
+ #
13
+ def flatten_to_sql(*values)
14
+ flatten_safely(values) do |value|
15
+ value = yield value if block_given?
16
+ to_arel_sql(value)
17
+ end
18
+ end
19
+ alias to_sql_array flatten_to_sql
20
+
21
+ def flatten_safely(values, &block)
22
+ unless values.is_a?(Array)
23
+ values = yield values if block
24
+ return [values]
25
+ end
26
+
27
+ values.map { |value| flatten_safely(value, &block) }.reduce(:+)
28
+ end
29
+
30
+ # Applies aliases to the given query
31
+ # Ex: `SELECT * FROM users` => `(SELECT * FROM users) AS "members"`
32
+ def nested_alias_escape(query, alias_name)
33
+ sql_query = generate_grouping(query)
34
+ Arel::Nodes::As.new(sql_query, to_arel_sql(double_quote(alias_name)))
35
+ end
36
+
37
+ # Wraps subquery into an Aliased ARRAY
38
+ # Ex: `SELECT * FROM users` => (ARRAY(SELECT * FROM users)) AS "members"
39
+ def wrap_with_array(arel_or_rel_query, alias_name, order_by: false)
40
+ if order_by && arel_or_rel_query.is_a?(ActiveRecord::Relation)
41
+ arel_or_rel_query = arel_or_rel_query.order(order_by)
42
+ end
43
+
44
+ query = Arel::Nodes::Array.new(to_sql_array(arel_or_rel_query))
45
+ nested_alias_escape(query, alias_name)
46
+ end
47
+
48
+ # Wraps query into an aggregated array
49
+ # EX: `(ARRAY_AGG((SELECT * FROM users)) AS "members"`
50
+ # `(ARRAY_AGG(DISTINCT (SELECT * FROM users)) AS "members"`
51
+ # `SELECT ARRAY_AGG((id)) AS "ids" FROM users`
52
+ # `SELECT ARRAY_AGG(DISTINCT (id)) AS "ids" FROM users`
53
+ def wrap_with_agg_array(arel_or_rel_query, alias_name, order_by: false, distinct: false)
54
+ distinct = !(!distinct)
55
+ order_exp = distinct ? nil : order_by # Can't order a distinct agg
56
+ query = group_when_needed(arel_or_rel_query)
57
+ query =
58
+ Arel::Nodes::AggregateFunctionName
59
+ .new("ARRAY_AGG", to_sql_array(query), distinct)
60
+ .order_by(order_exp)
61
+
62
+ nested_alias_escape(query, alias_name)
63
+ end
64
+
65
+ # Will attempt to digest and resolve the from clause
66
+ #
67
+ # If the from clause is a String, it will check to see if a table reference key has been assigned.
68
+ # - If one cannot be detected, one will be appended.
69
+ # - Rails does not allow assigning table references using the `.from/2` method, when its a string / sym type.
70
+ #
71
+ # If the from clause is an AR relation; it will duplicate the object.
72
+ # - Ensures any memorizers are reset (ex: `.to_sql` sets a memorizer on the instance)
73
+ # - Key's can be assigned using the `.from/2` method.
74
+ #
75
+ def from_clause_constructor(from, reference_key)
76
+ case from
77
+ when /\s.?#{reference_key}.?$/ # The from clause is a string and has the tbl reference key
78
+ @scope.unscoped.from(from)
79
+ when String, Symbol
80
+ @scope.unscoped.from("#{from} #{reference_key}")
81
+ else
82
+ replicate_klass = from.respond_to?(:unscoped) ? from.unscoped : @scope.unscoped
83
+ replicate_klass.from(from.dup, reference_key)
84
+ end.unscope(:where)
85
+ end
86
+
87
+ # Will carry defined CTE tables from the nested sub-query and gradually pushes it up to the parents query stack
88
+ # I.E: It pushes `WITH [:cte_name:] AS(...), ..` to the top of the query structure tree
89
+ #
90
+ # SPECIAL GOTCHA NOTE: (if duplicate keys are found) This will favor the parents query `with's` over nested ones!
91
+ def pipe_cte_with!(subquery)
92
+ return self unless subquery.try(:with_values?)
93
+
94
+ # Add subquery CTE's to the parents query stack. (READ THE SPECIAL NOTE ABOVE!)
95
+ if @scope.with_values?
96
+ @scope.cte.pipe_cte_with!(subquery.cte)
97
+ else
98
+ # Top level has no with values
99
+ @scope.with!(subquery.cte)
100
+ end
101
+
102
+ self
103
+ end
104
+
105
+ # Ensures the given value is properly double quoted.
106
+ # This also ensures we don't have conflicts with reversed keywords.
107
+ #
108
+ # IE: `user` is a reserved keyword in PG. But `"user"` is allowed and works the same
109
+ # when used as an column/tbl alias.
110
+ def double_quote(value)
111
+ return if value.nil?
112
+
113
+ case value.to_s
114
+ # Ignore keys that contain double quotes or a Arel.star (*)[all columns]
115
+ # or if a table has already been explicitly declared (ex: users.id)
116
+ when "*", /((^".+"$)|(^[[:alpha:]]+\.[[:alnum:]]+))/
117
+ value
118
+ else
119
+ PG::Connection.quote_ident(value.to_s)
120
+ end
121
+ end
122
+
123
+ # Ensures the key is properly single quoted and treated as a actual PG key reference.
124
+ def literal_key(key)
125
+ case key
126
+ when TrueClass then "'t'"
127
+ when FalseClass then "'f'"
128
+ when Numeric then key
129
+ else
130
+ key = key.to_s
131
+ key.start_with?("'") && key.end_with?("'") ? key : "'#{key}'"
132
+ end
133
+ end
134
+
135
+ # Converts a potential subquery into a compatible Arel SQL node.
136
+ #
137
+ # Note:
138
+ # We convert relations to SQL to maintain compatibility with Rails 5.1.
139
+ # Only Rails 5.2+ maintains bound attributes in Arel, so its better to be safe then sorry.
140
+ # When we drop support for Rails 5.1, we then can then drop the '.to_sql' conversation
141
+
142
+ def to_arel_sql(value)
143
+ case value
144
+ when Arel::Nodes::Node, Arel::Nodes::SqlLiteral, nil
145
+ value
146
+ when ActiveRecord::Relation
147
+ Arel.sql(value.spawn.to_sql)
148
+ else
149
+ Arel.sql(value.respond_to?(:to_sql) ? value.to_sql : value.to_s)
150
+ end
151
+ end
152
+
153
+ def group_when_needed(arel_or_rel_query)
154
+ return arel_or_rel_query unless needs_to_be_grouped?(arel_or_rel_query)
155
+
156
+ generate_grouping(arel_or_rel_query)
157
+ end
158
+
159
+ def needs_to_be_grouped?(query)
160
+ query.respond_to?(:to_sql) || (query.is_a?(String) && /^SELECT.+/i.match?(query))
161
+ end
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
+
173
+ def key_generator
174
+ A_TO_Z_KEYS.sample
175
+ end
176
+ end
177
+ end
178
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordExtended
4
- VERSION = "1.1.0"
4
+ VERSION = "2.0.0"
5
5
  end
@@ -3,65 +3,65 @@
3
3
  require "spec_helper"
4
4
 
5
5
  RSpec.describe "Active Record Any / None of Methods" do
6
- let!(:one) { Person.create!(personal_id: 1) }
7
- let!(:two) { Person.create!(personal_id: 2) }
8
- let!(:three) { Person.create!(personal_id: 3) }
6
+ let!(:one) { User.create!(personal_id: 1) }
7
+ let!(:two) { User.create!(personal_id: 2) }
8
+ let!(:three) { User.create!(personal_id: 3) }
9
9
 
10
- let!(:tag_one) { Tag.create!(person_id: one.id) }
11
- let!(:tag_two) { Tag.create!(person_id: two.id) }
12
- let!(:tag_three) { Tag.create!(person_id: three.id) }
10
+ let!(:tag_one) { Tag.create!(user_id: one.id) }
11
+ let!(:tag_two) { Tag.create!(user_id: two.id) }
12
+ let!(:tag_three) { Tag.create!(user_id: three.id) }
13
13
 
14
14
  describe "where.any_of/1" do
15
15
  it "Should return queries that match any of the outlined queries" do
16
- query = Person.where.any_of({ personal_id: 1 }, { personal_id: 2 })
16
+ query = User.where.any_of({ personal_id: 1 }, { personal_id: 2 })
17
17
  expect(query).to include(one, two)
18
18
  expect(query).to_not include(three)
19
19
  end
20
20
 
21
21
  it "Should accept where query predicates" do
22
- personal_one = Person.where(personal_id: 1)
23
- personal_two = Person.where(personal_id: 2)
24
- query = Person.where.any_of(personal_one, personal_two)
22
+ personal_one = User.where(personal_id: 1)
23
+ personal_two = User.where(personal_id: 2)
24
+ query = User.where.any_of(personal_one, personal_two)
25
25
 
26
26
  expect(query).to include(one, two)
27
27
  expect(query).to_not include(three)
28
28
  end
29
29
 
30
30
  it "Should accept query strings" do
31
- personal_one = Person.where(personal_id: 1)
31
+ personal_one = User.where(personal_id: 1)
32
32
 
33
- query = Person.where.any_of(personal_one, "personal_id > 2")
33
+ query = User.where.any_of(personal_one, "personal_id > 2")
34
34
  expect(query).to include(one, three)
35
35
  expect(query).to_not include(two)
36
36
 
37
- query = Person.where.any_of(["personal_id >= ?", 2])
37
+ query = User.where.any_of(["personal_id >= ?", 2])
38
38
  expect(query).to include(two, three)
39
39
  expect(query).to_not include(one)
40
40
  end
41
41
 
42
42
  context "Relationship queries" do
43
43
  it "Finds records that are queried from two or more has_many associations" do
44
- person_one_tag = Tag.create!(person_id: one.id)
45
- person_two_tag = Tag.create!(person_id: two.id)
46
- query = Tag.where.any_of(one.hm_tags, two.hm_tags)
44
+ user_one_tag = Tag.create!(user_id: one.id)
45
+ user_two_tag = Tag.create!(user_id: two.id)
46
+ query = Tag.where.any_of(one.hm_tags, two.hm_tags)
47
47
 
48
- expect(query).to include(tag_one, tag_two, person_one_tag, person_two_tag)
48
+ expect(query).to include(tag_one, tag_two, user_one_tag, user_two_tag)
49
49
  expect(query).to_not include(tag_three)
50
50
  end
51
51
 
52
52
  it "Finds records that are dynamically joined" do
53
- person_one_tag = Tag.where(people: { id: one.id }).includes(:person).references(:person)
54
- person_two_tag = Tag.where(people: { id: two.id }).joins(:person)
55
- query = Tag.where.any_of(person_one_tag, person_two_tag)
53
+ user_one_tag = Tag.where(users: { id: one.id }).includes(:user).references(:user)
54
+ user_two_tag = Tag.where(users: { id: two.id }).joins(:user)
55
+ query = Tag.where.any_of(user_one_tag, user_two_tag)
56
56
 
57
57
  expect(query).to include(tag_one, tag_two)
58
58
  expect(query).to_not include(tag_three)
59
59
  end
60
60
 
61
61
  it "Return matched records of a joined table on the parent level" do
62
- query = Tag.joins(:person).where.any_of(
63
- { people: { personal_id: 1 } },
64
- { people: { personal_id: 3 } },
62
+ query = Tag.joins(:user).where.any_of(
63
+ { users: { personal_id: 1 } },
64
+ { users: { personal_id: 3 } }
65
65
  )
66
66
 
67
67
  expect(query).to include(tag_one, tag_three)
@@ -72,55 +72,55 @@ RSpec.describe "Active Record Any / None of Methods" do
72
72
 
73
73
  describe "where.none_of/1" do
74
74
  it "Should return queries that match none of the outlined queries" do
75
- query = Person.where.none_of({ personal_id: 1 }, { personal_id: 2 })
75
+ query = User.where.none_of({ personal_id: 1 }, { personal_id: 2 })
76
76
  expect(query).to include(three)
77
77
  expect(query).to_not include(one, two)
78
78
  end
79
79
 
80
80
  it "Should accept where query predicates" do
81
- personal_one = Person.where(personal_id: 1)
82
- personal_two = Person.where(personal_id: 2)
83
- query = Person.where.none_of(personal_one, personal_two)
81
+ personal_one = User.where(personal_id: 1)
82
+ personal_two = User.where(personal_id: 2)
83
+ query = User.where.none_of(personal_one, personal_two)
84
84
 
85
85
  expect(query).to include(three)
86
86
  expect(query).to_not include(one, two)
87
87
  end
88
88
 
89
89
  it "Should accept query strings" do
90
- personal_one = Person.where(personal_id: 1)
90
+ personal_one = User.where(personal_id: 1)
91
91
 
92
- query = Person.where.none_of(personal_one, "personal_id > 2")
92
+ query = User.where.none_of(personal_one, "personal_id > 2")
93
93
  expect(query).to include(two)
94
94
  expect(query).to_not include(one, three)
95
95
 
96
- query = Person.where.none_of(["personal_id >= ?", 2])
96
+ query = User.where.none_of(["personal_id >= ?", 2])
97
97
  expect(query).to include(one)
98
98
  expect(query).to_not include(two, three)
99
99
  end
100
100
 
101
101
  context "Relationship queries" do
102
102
  it "Finds records that are queried from two or more has_many associations" do
103
- person_one_tag = Tag.create!(person_id: one.id)
104
- person_two_tag = Tag.create!(person_id: two.id)
105
- query = Tag.where.none_of(one.hm_tags, two.hm_tags)
103
+ user_one_tag = Tag.create!(user_id: one.id)
104
+ user_two_tag = Tag.create!(user_id: two.id)
105
+ query = Tag.where.none_of(one.hm_tags, two.hm_tags)
106
106
 
107
107
  expect(query).to include(tag_three)
108
- expect(query).to_not include(tag_one, tag_two, person_one_tag, person_two_tag)
108
+ expect(query).to_not include(tag_one, tag_two, user_one_tag, user_two_tag)
109
109
  end
110
110
 
111
111
  it "Finds records that are dynamically joined" do
112
- person_one_tag = Tag.where(people: { id: one.id }).includes(:person).references(:person)
113
- person_two_tag = Tag.where(people: { id: two.id }).joins(:person)
114
- query = Tag.where.none_of(person_one_tag, person_two_tag)
112
+ user_one_tag = Tag.where(users: { id: one.id }).includes(:user).references(:user)
113
+ user_two_tag = Tag.where(users: { id: two.id }).joins(:user)
114
+ query = Tag.where.none_of(user_one_tag, user_two_tag)
115
115
 
116
116
  expect(query).to include(tag_three)
117
117
  expect(query).to_not include(tag_one, tag_two)
118
118
  end
119
119
 
120
120
  it "Return matched records of a joined table on the parent level" do
121
- query = Tag.joins(:person).where.none_of(
122
- { people: { personal_id: 1 } },
123
- { people: { personal_id: 3 } },
121
+ query = Tag.joins(:user).where.none_of(
122
+ { users: { personal_id: 1 } },
123
+ { users: { personal_id: 3 } }
124
124
  )
125
125
 
126
126
  expect(query).to include(tag_two)
@@ -3,28 +3,28 @@
3
3
  require "spec_helper"
4
4
 
5
5
  RSpec.describe "Active Record Array Query Methods" do
6
- let!(:one) { Person.create!(tags: [1, 2, 3], personal_id: 33) }
7
- let!(:two) { Person.create!(tags: [3, 1, 5], personal_id: 88) }
8
- let!(:three) { Person.create!(tags: [2, 8, 20], personal_id: 33) }
6
+ let!(:one) { User.create!(tags: [1, 2, 3], personal_id: 33) }
7
+ let!(:two) { User.create!(tags: [3, 1, 5], personal_id: 88) }
8
+ let!(:three) { User.create!(tags: [2, 8, 20], personal_id: 33) }
9
9
 
10
10
  describe "#overlap" do
11
11
  it "Should return matched records" do
12
- query = Person.where.overlap(tags: [1])
12
+ query = User.where.overlap(tags: [1])
13
13
  expect(query).to include(one, two)
14
14
  expect(query).to_not include(three)
15
15
 
16
- query = Person.where.overlap(tags: [2, 3])
16
+ query = User.where.overlap(tags: [2, 3])
17
17
  expect(query).to include(one, two, three)
18
18
  end
19
19
  end
20
20
 
21
21
  describe "#contains" do
22
22
  it "returns records that contain elements in an array" do
23
- query = Person.where.contains(tags: [1, 3])
23
+ query = User.where.contains(tags: [1, 3])
24
24
  expect(query).to include(one, two)
25
25
  expect(query).to_not include(three)
26
26
 
27
- query = Person.where.contains(tags: [8, 2])
27
+ query = User.where.contains(tags: [8, 2])
28
28
  expect(query).to include(three)
29
29
  expect(query).to_not include(one, two)
30
30
  end
@@ -32,31 +32,31 @@ RSpec.describe "Active Record Array Query Methods" do
32
32
 
33
33
  describe "#any" do
34
34
  it "should return any records that match" do
35
- query = Person.where.any(tags: 3)
35
+ query = User.where.any(tags: 3)
36
36
  expect(query).to include(one, two)
37
37
  expect(query).to_not include(three)
38
38
  end
39
39
 
40
40
  it "allows chaining" do
41
- query = Person.where.any(tags: 3).where(personal_id: 33)
41
+ query = User.where.any(tags: 3).where(personal_id: 33)
42
42
  expect(query).to include(one)
43
43
  expect(query).to_not include(two, three)
44
44
  end
45
45
  end
46
46
 
47
47
  describe "#all" do
48
- let!(:contains_all) { Person.create!(tags: [1], personal_id: 1) }
49
- let!(:contains_all_two) { Person.create!(tags: [1], personal_id: 2) }
50
- let!(:contains_some) { Person.create!(tags: [1, 2], personal_id: 2) }
48
+ let!(:contains_all) { User.create!(tags: [1], personal_id: 1) }
49
+ let!(:contains_all_two) { User.create!(tags: [1], personal_id: 2) }
50
+ let!(:contains_some) { User.create!(tags: [1, 2], personal_id: 2) }
51
51
 
52
52
  it "should return any records that match" do
53
- query = Person.where.all(tags: 1)
53
+ query = User.where.all(tags: 1)
54
54
  expect(query).to include(contains_all, contains_all_two)
55
55
  expect(query).to_not include(contains_some)
56
56
  end
57
57
 
58
58
  it "allows chaining" do
59
- query = Person.where.all(tags: 1).where(personal_id: 1)
59
+ query = User.where.all(tags: 1).where(personal_id: 1)
60
60
  expect(query).to include(contains_all)
61
61
  expect(query).to_not include(contains_all_two, contains_some)
62
62
  end