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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b896dc7f4e36987c9fee2d3f99624944241c5778
4
- data.tar.gz: 3b63cf040cc3eccc90b22ffb167815cbc6c26762
3
+ metadata.gz: '09bda87b615e0962be005bda294cc0227e1d76ce'
4
+ data.tar.gz: 4cb809c77b97dfaad246f1a90be28e75cc2bb5a2
5
5
  SHA512:
6
- metadata.gz: f41ff3048e44820bd889403986a48ad90f95e1b3c97b0cfcd43a5797b2c5fdf706b8c6ac21ff3c9655489610a1ec38675001fd10ad5452237b0d46862f02660b
7
- data.tar.gz: 744a933a1fcc1fc3bd5251fc1b686c3009d4b7894996a64bef294947d18ed283552b00a225213d3181ae9e8768f976fede2a26aec03c05e6910a35407c7d9003
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
- raise ArgumentError.new("where_exists: not supported association – #{association.macros.inspect}")
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
- result = result.instance_exec(&association_scope)
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
- result = result.where_exists(next_association.name, *where_parameters)
107
- else
108
- if where_parameters != []
109
- result = result.where(*where_parameters)
110
- end
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]
@@ -1,3 +1,3 @@
1
1
  module WhereExists
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.1"
3
3
  end
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.0
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