scoped_search 2.6.1 → 2.6.2
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.
- checksums.yaml +5 -13
- data/lib/scoped_search/query_builder.rb +24 -7
- data/lib/scoped_search/version.rb +1 -1
- data/spec/integration/relation_querying_spec.rb +51 -0
- metadata +20 -20
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MDc4ZmFjZTRlYmMyZDRhZjljYzg2NzFmYWM1OWJkNDllOGQwMmUzOQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 37c27d6c6a3311a013c5bcaa5558f3d91f7c4443
|
4
|
+
data.tar.gz: f0d713611729611a6d2f0f990982873dad65bb82
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ZjBhMmI2YmZlNGNlYTBmNzBmMmZjMjg0Y2NjN2YzZjgwOTA5NjJmMDhlYzg4
|
11
|
-
ODI0MmEyYTI0NGZiN2NjYzBiN2ZlNzA1ZGY1ZDM0Y2FkZDcyMzg=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NmU5N2UwN2FiOWE1MGI2NDNjNWZkMWEyNGI5YTk2MzIxM2Q5ZTc5YjIwOGQ5
|
14
|
-
N2UzMTg0ODlhMTljZDQ5NDAxNGZiNTMwMDhkODg5MmQ3Yzc3NzNhMGU1Y2I0
|
15
|
-
NTlmMDEwODgxMTk3ZWNiZjI5NjU5N2RjNzE3MzBjMDYwZDk0NzM=
|
6
|
+
metadata.gz: 5826b9fe779a5c48da50101a6dc7c52ba756bed745f99d463adeada1f23a1484e127d36ea122a9249f85050597133748655db51900d40160bf9c81a154975ae2
|
7
|
+
data.tar.gz: 6a0a37aeb76ca59e10c07c3e57ac51480dc34e7ef52586026d9db75741da70619fd327061b459ed527e206725b68e47fb0b4c5b012464f13aea8c48a1a053e90
|
@@ -240,16 +240,25 @@ module ScopedSearch
|
|
240
240
|
end
|
241
241
|
|
242
242
|
def has_many_through_join(field)
|
243
|
+
many_class = field.definition.klass
|
244
|
+
through = many_class.reflections[field.relation].options[:through]
|
245
|
+
#table names
|
243
246
|
endpoint_table_name = field.klass.table_name
|
244
|
-
|
245
|
-
middle_table_name =
|
247
|
+
many_table_name = many_class.table_name
|
248
|
+
middle_table_name = many_class.reflections[through].klass.table_name
|
249
|
+
#primary and foreign keys + optional condition for the many to middle join
|
250
|
+
pk1, fk1 = field.reflection_keys(many_class.reflections[through])
|
251
|
+
condition1 = field.reflection_conditions(field.klass.reflections[many_table_name.to_sym])
|
252
|
+
#primary and foreign keys + optional condition for the endpoint to middle join
|
253
|
+
pk2, fk2 = field.reflection_keys(field.klass.reflections[middle_table_name.to_sym])
|
254
|
+
condition2 = field.reflection_conditions(many_class.reflections[field.relation])
|
246
255
|
|
247
256
|
<<-SQL
|
248
|
-
#{
|
257
|
+
#{many_table_name}
|
249
258
|
INNER JOIN #{middle_table_name}
|
250
|
-
ON #{
|
259
|
+
ON #{many_table_name}.#{pk1} = #{middle_table_name}.#{fk1} #{condition1}
|
251
260
|
INNER JOIN #{endpoint_table_name}
|
252
|
-
ON #{middle_table_name}.#{
|
261
|
+
ON #{middle_table_name}.#{fk2} = #{endpoint_table_name}.#{pk2} #{condition2}
|
253
262
|
SQL
|
254
263
|
end
|
255
264
|
|
@@ -336,14 +345,22 @@ module ScopedSearch
|
|
336
345
|
return join_sql
|
337
346
|
end
|
338
347
|
|
339
|
-
def reflection_keys
|
348
|
+
def reflection_keys(reflection)
|
340
349
|
pk = reflection.klass.primary_key
|
341
350
|
fk = reflection.options[:foreign_key]
|
342
351
|
# activerecord prior to 3.1 doesn't respond to foreign_key method and hold the key name in the reflection primary key
|
343
|
-
fk
|
352
|
+
fk ||= reflection.respond_to?(:foreign_key) ? reflection.foreign_key : reflection.primary_key_name
|
344
353
|
[pk, fk]
|
345
354
|
end
|
346
355
|
|
356
|
+
def reflection_conditions(reflection)
|
357
|
+
return unless reflection
|
358
|
+
conditions = reflection.options[:conditions]
|
359
|
+
conditions ||= "#{reflection.options[:source]}_type = '#{reflection.klass}'" if reflection.options[:source]
|
360
|
+
conditions ||= "#{reflection.try(:foreign_type)} = '#{reflection.klass}'" if reflection.options[:polymorphic]
|
361
|
+
" AND #{conditions}" if conditions
|
362
|
+
end
|
363
|
+
|
347
364
|
def to_ext_method_sql(key, operator, value, &block)
|
348
365
|
raise ScopedSearch::QueryNotSupported, "'#{definition.klass}' doesn't respond to '#{ext_method}'" unless definition.klass.respond_to?(ext_method)
|
349
366
|
conditions = definition.klass.send(ext_method.to_sym,key, operator, value) rescue {}
|
@@ -274,5 +274,56 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
|
|
274
274
|
Koo.search_for('related=baz AND related="baz too!"').should have(1).items
|
275
275
|
end
|
276
276
|
end
|
277
|
+
|
278
|
+
context 'querying a :has_many => :through :polymorphic relation' do
|
279
|
+
|
280
|
+
before do
|
281
|
+
|
282
|
+
# Create some tables
|
283
|
+
ActiveRecord::Migration.create_table(:taggables) { |t| t.integer :taggable_id; t.string :taggable_type; t.integer :tag_id }
|
284
|
+
ActiveRecord::Migration.create_table(:dogs) { |t| t.string :related }
|
285
|
+
ActiveRecord::Migration.create_table(:tags) { |t| t.string :foo }
|
286
|
+
|
287
|
+
# The related classes
|
288
|
+
class Taggable < ActiveRecord::Base; belongs_to :tag; belongs_to :taggable, :polymorphic => true; end
|
289
|
+
class Tag < ActiveRecord::Base; has_many :taggables; end
|
290
|
+
|
291
|
+
# The class on which to call search_for
|
292
|
+
class Dog < ActiveRecord::Base
|
293
|
+
has_many :taggable, :as => :taggable
|
294
|
+
has_many :tags, :through => :taggable
|
295
|
+
|
296
|
+
scoped_search :in => :tags, :on => :foo
|
297
|
+
end
|
298
|
+
|
299
|
+
@tag_1 = Tag.create!(:foo => 'foo')
|
300
|
+
@tag_2 = Tag.create!(:foo => 'foo too')
|
301
|
+
@tag_3 = Tag.create!(:foo => 'foo three')
|
302
|
+
|
303
|
+
@taggable_1 = Dog.create(:related => 'baz')
|
304
|
+
@taggable_2 = Dog.create(:related => 'baz too!')
|
305
|
+
|
306
|
+
@bar_1 = Taggable.create!(:tag => @tag_1, :taggable => @taggable_1, :taggable_type => 'Dog' )
|
307
|
+
@bar_2 = Taggable.create!(:tag => @tag_1)
|
308
|
+
@bar_3 = Taggable.create!(:tag => @tag_2, :taggable => @taggable_1 , :taggable_type => 'Dog')
|
309
|
+
@bar_3 = Taggable.create!(:tag => @tag_2, :taggable => @taggable_2 , :taggable_type => 'Dog')
|
310
|
+
@bar_3 = Taggable.create!(:tag => @tag_2, :taggable => @taggable_2 , :taggable_type => 'Dog')
|
311
|
+
@bar_4 = Taggable.create!(:tag => @tag_3)
|
312
|
+
end
|
313
|
+
|
314
|
+
after do
|
315
|
+
ActiveRecord::Migration.drop_table(:dogs)
|
316
|
+
ActiveRecord::Migration.drop_table(:taggables)
|
317
|
+
ActiveRecord::Migration.drop_table(:tags)
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should find the two records that are related to a baz record" do
|
321
|
+
Dog.search_for('foo').should have(2).items
|
322
|
+
end
|
323
|
+
|
324
|
+
it "should find the two records that are related to a baz record" do
|
325
|
+
Dog.search_for('foo=foo AND foo="foo too"').should have(1).items
|
326
|
+
end
|
327
|
+
end
|
277
328
|
end
|
278
329
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scoped_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.6.
|
4
|
+
version: 2.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amos Benari
|
@@ -10,20 +10,20 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2014-02-10 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: 2.1.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
|
-
- -
|
26
|
+
- - '>='
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: 2.1.0
|
29
29
|
- !ruby/object:Gem::Dependency
|
@@ -44,27 +44,27 @@ dependencies:
|
|
44
44
|
name: rake
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- -
|
47
|
+
- - '>='
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: '0'
|
50
50
|
type: :development
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
|
-
- -
|
54
|
+
- - '>='
|
55
55
|
- !ruby/object:Gem::Version
|
56
56
|
version: '0'
|
57
|
-
description:
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
57
|
+
description: " Scoped search makes it easy to search your ActiveRecord-based models.\n
|
58
|
+
\ \n It will create a named scope :search_for that can be called with a query
|
59
|
+
string. It will build an SQL query using\n the provided query string and a definition
|
60
|
+
that specifies on what fields to search. Because the functionality is\n built
|
61
|
+
on named_scope, the result of the search_for call can be used like any other named_scope,
|
62
|
+
so it can be\n chained with another scope or combined with will_paginate.\n \n
|
63
|
+
\ Because it uses standard SQL, it does not require any setup, indexers or daemons.
|
64
|
+
This makes scoped_search\n suitable to quickly add basic search functionality
|
65
|
+
to your application with little hassle. On the other hand,\n it may not be the
|
66
|
+
best choice if it is going to be used on very large datasets or by a large user
|
67
|
+
base.\n"
|
68
68
|
email:
|
69
69
|
- abenari@redhat.com
|
70
70
|
- willem@railsdoctors.com
|
@@ -136,17 +136,17 @@ require_paths:
|
|
136
136
|
- lib
|
137
137
|
required_ruby_version: !ruby/object:Gem::Requirement
|
138
138
|
requirements:
|
139
|
-
- -
|
139
|
+
- - '>='
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
143
|
requirements:
|
144
|
-
- -
|
144
|
+
- - '>='
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '0'
|
147
147
|
requirements: []
|
148
148
|
rubyforge_project:
|
149
|
-
rubygems_version: 2.
|
149
|
+
rubygems_version: 2.0.3
|
150
150
|
signing_key:
|
151
151
|
specification_version: 4
|
152
152
|
summary: Easily search you ActiveRecord models with a simple query language using
|