where_exists 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/where_exists.rb +54 -12
- data/lib/where_exists/version.rb +1 -1
- data/test/db/test.db +0 -0
- data/test/has_and_belongs_to_many.rb +92 -0
- data/test/has_many_through_test.rb +5 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09bda87b615e0962be005bda294cc0227e1d76ce'
|
4
|
+
data.tar.gz: 4cb809c77b97dfaad246f1a90be28e75cc2bb5a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4ca719701af78dfc661a35cb815adf49d1206072f0fa3db2af6a411677f7394ad19547706f0f14265462955231847922821732caa9c64ca4e22186cefeb1127
|
7
|
+
data.tar.gz: 6e147f5238c544d0691cfb982d38cc560b5baf6a97d82f5529b94cafed6683c9e1a0b7706b6d967e2cc0913b905906c0d3192d64e064407f60774cd6c309f94c
|
data/lib/where_exists.rb
CHANGED
@@ -23,8 +23,16 @@ module WhereExists
|
|
23
23
|
queries = where_exists_for_belongs_to_query(association, where_parameters)
|
24
24
|
when :has_many, :has_one
|
25
25
|
queries = where_exists_for_has_many_query(association, where_parameters)
|
26
|
+
when :has_and_belongs_to_many
|
27
|
+
queries = where_exists_for_habtm_query(association, where_parameters)
|
26
28
|
else
|
27
|
-
|
29
|
+
inspection = nil
|
30
|
+
begin
|
31
|
+
inspection = association.macros.inspect
|
32
|
+
rescue
|
33
|
+
inspection = association.macro
|
34
|
+
end
|
35
|
+
raise ArgumentError.new("where_exists: not supported association – #{inspection}")
|
28
36
|
end
|
29
37
|
|
30
38
|
if does_exist
|
@@ -33,7 +41,7 @@ module WhereExists
|
|
33
41
|
not_string = "NOT "
|
34
42
|
end
|
35
43
|
|
36
|
-
queries_sql = queries.map{|query| "EXISTS (" + query.to_sql + ")"}.join(" OR ")
|
44
|
+
queries_sql = queries.map { |query| "EXISTS (" + query.to_sql + ")" }.join(" OR ")
|
37
45
|
|
38
46
|
self.where("#{not_string}(#{queries_sql})")
|
39
47
|
end
|
@@ -62,7 +70,7 @@ module WhereExists
|
|
62
70
|
query = query.where(*where_parameters)
|
63
71
|
end
|
64
72
|
if association_scope
|
65
|
-
|
73
|
+
query = query.instance_exec(&association_scope)
|
66
74
|
end
|
67
75
|
if polymorphic
|
68
76
|
other_type = connection.quote(associated_model.name)
|
@@ -92,10 +100,6 @@ module WhereExists
|
|
92
100
|
|
93
101
|
result = associated_model.select("1").where("#{associated_ids} = #{self_ids}")
|
94
102
|
|
95
|
-
if association_scope
|
96
|
-
result = result.instance_exec(&association_scope)
|
97
|
-
end
|
98
|
-
|
99
103
|
if association.options[:as]
|
100
104
|
other_types = quote_table_and_column_name(associated_model.table_name, association.type)
|
101
105
|
self_class = connection.quote(self.name)
|
@@ -103,11 +107,49 @@ module WhereExists
|
|
103
107
|
end
|
104
108
|
|
105
109
|
if through
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
110
|
+
return [result.where_exists(next_association.name, *where_parameters)]
|
111
|
+
end
|
112
|
+
|
113
|
+
if where_parameters != []
|
114
|
+
result = result.where(*where_parameters)
|
115
|
+
end
|
116
|
+
if association_scope
|
117
|
+
result = result.instance_exec(&association_scope)
|
118
|
+
end
|
119
|
+
|
120
|
+
[result]
|
121
|
+
end
|
122
|
+
|
123
|
+
def where_exists_for_habtm_query(association, where_parameters)
|
124
|
+
association_scope = association.scope
|
125
|
+
|
126
|
+
associated_model = association.klass
|
127
|
+
|
128
|
+
primary_key = association.options[:primary_key] || self.primary_key
|
129
|
+
|
130
|
+
join_table = [self.table_name, associated_model.table_name].sort.join("_")
|
131
|
+
|
132
|
+
self_ids = quote_table_and_column_name(self.table_name, primary_key)
|
133
|
+
join_ids = quote_table_and_column_name(join_table, association.foreign_key)
|
134
|
+
associated_join_ids = quote_table_and_column_name(join_table, "#{associated_model.name.downcase}_id")
|
135
|
+
associated_ids = quote_table_and_column_name(associated_model.table_name, associated_model.primary_key)
|
136
|
+
|
137
|
+
result =
|
138
|
+
associated_model.
|
139
|
+
select("1").
|
140
|
+
joins(
|
141
|
+
<<-SQL
|
142
|
+
INNER JOIN #{connection.quote_table_name(join_table)}
|
143
|
+
ON #{associated_ids} = #{associated_join_ids}
|
144
|
+
SQL
|
145
|
+
).
|
146
|
+
where("#{join_ids} = #{self_ids}")
|
147
|
+
|
148
|
+
if where_parameters != []
|
149
|
+
result = result.where(*where_parameters)
|
150
|
+
end
|
151
|
+
if association_scope
|
152
|
+
result = result.instance_exec(&association_scope)
|
111
153
|
end
|
112
154
|
|
113
155
|
[result]
|
data/lib/where_exists/version.rb
CHANGED
data/test/db/test.db
CHANGED
Binary file
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
ActiveRecord::Migration.create_table :tasks, :force => true do |t|
|
4
|
+
t.string :name
|
5
|
+
end
|
6
|
+
|
7
|
+
ActiveRecord::Migration.create_table :invoices_tasks, :force => true do |t|
|
8
|
+
t.integer :invoice_id
|
9
|
+
t.integer :task_id
|
10
|
+
end
|
11
|
+
|
12
|
+
ActiveRecord::Migration.create_table :invoices, :force => true do |t|
|
13
|
+
t.string :name
|
14
|
+
end
|
15
|
+
|
16
|
+
class Task < ActiveRecord::Base
|
17
|
+
has_and_belongs_to_many :connected_invoices, class_name: 'Invoice'
|
18
|
+
end
|
19
|
+
|
20
|
+
class Invoice < ActiveRecord::Base
|
21
|
+
has_and_belongs_to_many :tasks
|
22
|
+
has_and_belongs_to_many :unnamed_tasks, -> { where(name: nil) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Invoices -> LineItems <- Tasks <- Project
|
26
|
+
|
27
|
+
class HasAndBelongsToManyTest < Minitest::Test
|
28
|
+
def setup
|
29
|
+
ActiveRecord::Base.descendants.each(&:delete_all)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_with_standard_naming
|
33
|
+
task = Task.create!(name: 'task')
|
34
|
+
irrelevant_task = Task.create!(name: 'task_2')
|
35
|
+
invoice = Invoice.create!(name: 'invoice')
|
36
|
+
invoice_no_join = Invoice.create!(name: 'invoice_2')
|
37
|
+
|
38
|
+
invoice.tasks << task
|
39
|
+
|
40
|
+
|
41
|
+
result = Invoice.where_exists(:tasks, name: 'task')
|
42
|
+
|
43
|
+
assert_equal 1, result.length
|
44
|
+
assert_equal invoice.id, result.first.id
|
45
|
+
|
46
|
+
result = Invoice.where_exists(:tasks, name: 'task_2')
|
47
|
+
|
48
|
+
assert_equal 0, result.length
|
49
|
+
|
50
|
+
result = Invoice.where_not_exists(:tasks)
|
51
|
+
assert_equal 1, result.length
|
52
|
+
assert_equal invoice_no_join.id, result.first.id
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_with_custom_naming
|
56
|
+
task = Task.create!(name: 'task')
|
57
|
+
task_no_join = Task.create!(name: 'invoice')
|
58
|
+
invoice = Invoice.create!(name: 'invoice')
|
59
|
+
irrelevant_invoice = Invoice.create!(name: 'invoice_2')
|
60
|
+
|
61
|
+
task.connected_invoices << invoice
|
62
|
+
|
63
|
+
result = Task.where_exists(:connected_invoices, name: 'invoice')
|
64
|
+
|
65
|
+
assert_equal 1, result.length
|
66
|
+
assert_equal task.id, result.first.id
|
67
|
+
|
68
|
+
result = Task.where_exists(:connected_invoices, name: 'invoice_2')
|
69
|
+
|
70
|
+
assert_equal 0, result.length
|
71
|
+
|
72
|
+
result = Task.where_not_exists(:connected_invoices)
|
73
|
+
assert_equal 1, result.length
|
74
|
+
assert_equal task_no_join.id, result.first.id
|
75
|
+
|
76
|
+
result = Task.where_not_exists(:connected_invoices, name: 'invoice_2')
|
77
|
+
assert_equal 2, result.length
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_with_condition
|
81
|
+
task_1 = Task.create! name: nil
|
82
|
+
task_2 = Task.create! name: 'task 2'
|
83
|
+
|
84
|
+
invoice_1 = Invoice.create!(tasks: [task_1])
|
85
|
+
invoice_2 = Invoice.create!(tasks: [task_1, task_2])
|
86
|
+
invoice_3 = Invoice.create!(tasks: [task_2)
|
87
|
+
|
88
|
+
result_ids = Invoice.where_exists(:unnamed_tasks).pluck(:id)
|
89
|
+
|
90
|
+
assert_equal [invoice_1.id, invoice_2.id].sort, result_ids.sort
|
91
|
+
end
|
92
|
+
end
|
@@ -91,5 +91,10 @@ class HasManyThroughTest < Minitest::Test
|
|
91
91
|
|
92
92
|
assert_equal 1, result.length
|
93
93
|
assert_equal irrelevant_project.id, result.first.id
|
94
|
+
|
95
|
+
result = Project.where_not_exists(:invoices, "name = ?", 'relevant')
|
96
|
+
|
97
|
+
assert_equal 1, result.length
|
98
|
+
assert_equal irrelevant_project.id, result.first.id
|
94
99
|
end
|
95
100
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: where_exists
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eugene Zolotarev
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- test/belongs_to_test.rb
|
74
74
|
- test/db/test.db
|
75
75
|
- test/documentation_test.rb
|
76
|
+
- test/has_and_belongs_to_many.rb
|
76
77
|
- test/has_many_polymorphic_test.rb
|
77
78
|
- test/has_many_test.rb
|
78
79
|
- test/has_many_through_test.rb
|
@@ -107,6 +108,7 @@ test_files:
|
|
107
108
|
- test/documentation_test.rb
|
108
109
|
- test/test_helper.rb
|
109
110
|
- test/has_many_polymorphic_test.rb
|
111
|
+
- test/has_and_belongs_to_many.rb
|
110
112
|
- test/belongs_to_polymorphic_test.rb
|
111
113
|
- test/has_many_test.rb
|
112
114
|
- test/has_many_through_test.rb
|