scoped_search 3.0.1 → 3.1.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.
- checksums.yaml +4 -4
- data/.travis.yml +22 -20
- data/CHANGELOG.rdoc +10 -1
- data/CONTRIBUTING.rdoc +2 -1
- data/{Gemfile.activerecord3 → Gemfile.activerecord32} +1 -1
- data/Gemfile.activerecord42 +16 -0
- data/lib/scoped_search/auto_complete_builder.rb +1 -1
- data/lib/scoped_search/definition.rb +23 -36
- data/lib/scoped_search/query_builder.rb +23 -21
- data/lib/scoped_search/version.rb +1 -1
- data/scoped_search.gemspec +1 -1
- data/spec/integration/api_spec.rb +2 -9
- data/spec/integration/key_value_querying_spec.rb +1 -6
- data/spec/integration/relation_querying_spec.rb +8 -11
- data/spec/lib/database.rb +6 -2
- data/spec/unit/definition_spec.rb +8 -26
- data/spec/unit/query_builder_spec.rb +2 -2
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8f3158e1d95aa30c3129d1f93fd908c7a52c8d4
|
4
|
+
data.tar.gz: db5a65eeebd58513c499ea3b6bbfb3a8723702d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34c8500136d8d3baf89313d09a9cfeb817798790ce27d16009745ed6af40dbc9ec47f3c2532dab44945c266cb491973179506b5e0a2950d02db5f64c337716f0
|
7
|
+
data.tar.gz: bf5ea94257096ead71261964695ba7fed482cbca7c5b5acfd5afed3653884312e5fda2d9c8d11262f3c7f7b710c78ce9c75b060b3ba5391bfa182eefd738fcf4
|
data/.travis.yml
CHANGED
@@ -1,30 +1,32 @@
|
|
1
|
-
|
2
1
|
language: ruby
|
3
2
|
cache: bundler
|
4
|
-
|
5
3
|
sudo: false
|
6
4
|
|
5
|
+
install:
|
6
|
+
- bundle install
|
7
|
+
before_script:
|
8
|
+
- psql -c 'create database scoped_search_test;' -U postgres
|
9
|
+
- mysql -e 'create database scoped_search_test;'
|
10
|
+
script:
|
11
|
+
- bundle exec rake
|
12
|
+
|
7
13
|
rvm:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
- "1.9"
|
15
|
+
- "2.0"
|
16
|
+
- "2.1"
|
17
|
+
- "2.2"
|
18
|
+
- ruby-head
|
19
|
+
- jruby-19mode
|
20
|
+
- jruby-head
|
14
21
|
|
15
22
|
gemfile:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
before_script:
|
21
|
-
- psql -c 'create database scoped_search_test;' -U postgres
|
22
|
-
- mysql -e 'create database scoped_search_test;'
|
23
|
-
|
24
|
-
script: bundle exec rake
|
23
|
+
- Gemfile.activerecord32
|
24
|
+
- Gemfile.activerecord40
|
25
|
+
- Gemfile.activerecord41
|
26
|
+
- Gemfile.activerecord42
|
25
27
|
|
26
28
|
matrix:
|
27
|
-
include:
|
28
29
|
allow_failures:
|
29
|
-
|
30
|
-
|
30
|
+
- rvm: ruby-head
|
31
|
+
- rvm: jruby-head
|
32
|
+
- rvm: jruby-19mode
|
data/CHANGELOG.rdoc
CHANGED
@@ -8,7 +8,16 @@ Please add an entry to the "Unreleased changes" section in your pull requests.
|
|
8
8
|
|
9
9
|
*Nothing yet*
|
10
10
|
|
11
|
-
=== Version 3.0
|
11
|
+
=== Version 3.1.0
|
12
|
+
|
13
|
+
- Add support for ActiveRecord 4.2.
|
14
|
+
- Bump AtiveRecord requirement to 3.2.
|
15
|
+
|
16
|
+
=== Version 3.0.1
|
17
|
+
|
18
|
+
- Security fix in parsing dates.
|
19
|
+
|
20
|
+
=== Version 3.0.0
|
12
21
|
|
13
22
|
- Add support for ActiveRecord 4.1
|
14
23
|
- Drop support for Ruby 1.8
|
data/CONTRIBUTING.rdoc
CHANGED
@@ -6,10 +6,11 @@ Scoped search is an open source project, and hence we are open for contributions
|
|
6
6
|
|
7
7
|
When reporting an issue, make sure to include the following information so we can pinpoint the problem faster:
|
8
8
|
|
9
|
-
- What query did you use?
|
9
|
+
- What search query did you use?
|
10
10
|
- What is the search definition used on your models?
|
11
11
|
- What do the tables involved in your search definition look like? Please include the type of the fields.
|
12
12
|
- A sample of records. Which one did you expect to be included in the result
|
13
|
+
- What was the SQL that scoped_search ended up generating?
|
13
14
|
|
14
15
|
Finally, please include the following information about your environment.
|
15
16
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
gem 'activerecord', '~> 4.2.0'
|
5
|
+
|
6
|
+
platforms :jruby do
|
7
|
+
gem 'activerecord-jdbcsqlite3-adapter'
|
8
|
+
gem 'activerecord-jdbcmysql-adapter'
|
9
|
+
gem 'activerecord-jdbcpostgresql-adapter'
|
10
|
+
end
|
11
|
+
|
12
|
+
platforms :ruby do
|
13
|
+
gem 'sqlite3'
|
14
|
+
gem 'mysql2', '~> 0.3.11'
|
15
|
+
gem 'pg'
|
16
|
+
end
|
@@ -246,7 +246,7 @@ module ScopedSearch
|
|
246
246
|
|
247
247
|
if field.key_klass != field.klass
|
248
248
|
key = field.key_klass.to_s.gsub(/.*::/,'').underscore.to_sym
|
249
|
-
fk = field.klass
|
249
|
+
fk = definition.reflection_by_name(field.klass, key).association_foreign_key.to_sym
|
250
250
|
query = query.where(fk => key_klass.id)
|
251
251
|
end
|
252
252
|
|
@@ -59,9 +59,7 @@ module ScopedSearch
|
|
59
59
|
# The ActiveRecord-based class that belongs to this field.
|
60
60
|
def klass
|
61
61
|
@klass ||= if relation
|
62
|
-
|
63
|
-
raise ScopedSearch::QueryNotSupported, "relation '#{relation}' not one of #{definition.klass.reflections.keys.join(', ')} " if related.nil?
|
64
|
-
related.klass
|
62
|
+
definition.reflection_by_name(definition.klass, relation).klass
|
65
63
|
else
|
66
64
|
definition.klass
|
67
65
|
end
|
@@ -70,9 +68,9 @@ module ScopedSearch
|
|
70
68
|
# The ActiveRecord-based class that belongs the key field in a key-value pair.
|
71
69
|
def key_klass
|
72
70
|
@key_klass ||= if key_relation
|
73
|
-
definition.klass
|
71
|
+
definition.reflection_by_name(definition.klass, key_relation).klass
|
74
72
|
elsif relation
|
75
|
-
definition.klass
|
73
|
+
definition.reflection_by_name(definition.klass, relation).klass
|
76
74
|
else
|
77
75
|
definition.klass
|
78
76
|
end
|
@@ -87,7 +85,7 @@ module ScopedSearch
|
|
87
85
|
if "#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}".to_f < 4.1
|
88
86
|
raise ActiveRecord::UnknownAttributeError, "#{klass.inspect} doesn't have column #{field.inspect}."
|
89
87
|
else
|
90
|
-
raise ActiveRecord::UnknownAttributeError.new(
|
88
|
+
raise ActiveRecord::UnknownAttributeError.new(klass, field)
|
91
89
|
end
|
92
90
|
end
|
93
91
|
end
|
@@ -198,7 +196,7 @@ module ScopedSearch
|
|
198
196
|
return ['= ', '> ', '< ', '<= ', '>= ','!= ', '^ ', '!^ '] if field.numerical?
|
199
197
|
return ['= ', '!= ', '~ ', '!~ ', '^ ', '!^ '] if field.textual?
|
200
198
|
return ['= ', '> ', '< '] if field.temporal?
|
201
|
-
raise ScopedSearch::QueryNotSupported, "
|
199
|
+
raise ScopedSearch::QueryNotSupported, "Unsupported type '#{field.type.inspect}')' for field '#{name}'. This can be a result of a search definition problem."
|
202
200
|
end
|
203
201
|
|
204
202
|
NUMERICAL_REGXP = /^\-?\d+(\.\d+)?$/
|
@@ -240,40 +238,29 @@ module ScopedSearch
|
|
240
238
|
Field.new(self, options)
|
241
239
|
end
|
242
240
|
|
241
|
+
# Returns a reflection for a given klass and name
|
242
|
+
def reflection_by_name(klass, name)
|
243
|
+
return if name.nil?
|
244
|
+
klass.reflections[name.to_sym] || klass.reflections[name.to_s]
|
245
|
+
end
|
246
|
+
|
243
247
|
protected
|
244
248
|
|
245
249
|
# Registers the search_for named scope within the class that is used for searching.
|
246
250
|
def register_named_scope! # :nodoc
|
247
251
|
definition = self
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
when 4
|
261
|
-
@klass.scope(:search_for, lambda { |*args|
|
262
|
-
find_options = ScopedSearch::QueryBuilder.build_query(definition, args[0], args[1])
|
263
|
-
search_scope = @klass
|
264
|
-
search_scope = search_scope.where(find_options[:conditions]) if find_options[:conditions]
|
265
|
-
search_scope = search_scope.includes(find_options[:include]) if find_options[:include]
|
266
|
-
search_scope = search_scope.references(find_options[:include]) if find_options[:include]
|
267
|
-
search_scope = search_scope.joins(find_options[:joins]) if find_options[:joins]
|
268
|
-
search_scope = search_scope.reorder(find_options[:order]) if find_options[:order]
|
269
|
-
search_scope
|
270
|
-
})
|
271
|
-
else
|
272
|
-
raise "This ActiveRecord version is currently not supported!"
|
273
|
-
end
|
274
|
-
else
|
275
|
-
raise "Currently, only ActiveRecord 3 or newer is supported!"
|
276
|
-
end
|
252
|
+
@klass.scope(:search_for, proc { |query, options|
|
253
|
+
search_scope = ActiveRecord::VERSION::MAJOR == 3 ? @klass.scoped : @klass
|
254
|
+
|
255
|
+
find_options = ScopedSearch::QueryBuilder.build_query(definition, query || '', options || {})
|
256
|
+
search_scope = search_scope.where(find_options[:conditions]) if find_options[:conditions]
|
257
|
+
search_scope = search_scope.includes(find_options[:include]) if find_options[:include]
|
258
|
+
search_scope = search_scope.joins(find_options[:joins]) if find_options[:joins]
|
259
|
+
search_scope = search_scope.reorder(find_options[:order]) if find_options[:order]
|
260
|
+
search_scope = search_scope.references(find_options[:include]) if find_options[:include] && ActiveRecord::VERSION::MAJOR >= 4
|
261
|
+
|
262
|
+
search_scope
|
263
|
+
})
|
277
264
|
end
|
278
265
|
|
279
266
|
# Registers the complete_for method within the class that is used for searching.
|
@@ -14,17 +14,14 @@ module ScopedSearch
|
|
14
14
|
# This method will parse the query string and build an SQL query using the search
|
15
15
|
# query. It will return an empty hash if the search query is empty, in which case
|
16
16
|
# the scope call will simply return all records.
|
17
|
-
def self.build_query(definition,
|
18
|
-
query = args[0] ||=''
|
19
|
-
options = args[1] || {}
|
20
|
-
|
17
|
+
def self.build_query(definition, query, options = {})
|
21
18
|
query_builder_class = self.class_for(definition)
|
22
19
|
if query.kind_of?(ScopedSearch::QueryLanguage::AST::Node)
|
23
20
|
return query_builder_class.new(definition, query, options[:profile]).build_find_params(options)
|
24
21
|
elsif query.kind_of?(String)
|
25
22
|
return query_builder_class.new(definition, ScopedSearch::QueryLanguage::Compiler.parse(query), options[:profile]).build_find_params(options)
|
26
23
|
else
|
27
|
-
raise "Unsupported query object: #{query.inspect}!"
|
24
|
+
raise ArgumentError, "Unsupported query object: #{query.inspect}!"
|
28
25
|
end
|
29
26
|
end
|
30
27
|
|
@@ -213,26 +210,31 @@ module ScopedSearch
|
|
213
210
|
if [:like, :unlike].include?(operator)
|
214
211
|
yield(:parameter, (value !~ /^\%|\*/ && value !~ /\%|\*$/) ? "%#{value}%" : value.tr_s('%*', '%'))
|
215
212
|
return "#{field.to_sql(operator, &block)} #{self.sql_operator(operator, field)} ?"
|
213
|
+
|
216
214
|
elsif [:in, :notin].include?(operator)
|
217
215
|
value.split(',').collect { |v| yield(:parameter, field.set? ? translate_value(field, v) : v.strip) }
|
218
216
|
value = value.split(',').collect { "?" }.join(",")
|
219
217
|
return "#{field.to_sql(operator, &block)} #{self.sql_operator(operator, field)} (#{value})"
|
218
|
+
|
220
219
|
elsif field.temporal?
|
221
220
|
return datetime_test(field, operator, value, &block)
|
221
|
+
|
222
222
|
elsif field.set?
|
223
223
|
return set_test(field, operator, value, &block)
|
224
|
-
|
224
|
+
|
225
|
+
elsif field.relation && definition.reflection_by_name(field.definition.klass, field.relation).macro == :has_many
|
225
226
|
value = value.to_i if field.offset
|
226
227
|
yield(:parameter, value)
|
227
228
|
connection = field.definition.klass.connection
|
228
229
|
primary_key = "#{connection.quote_table_name(field.definition.klass.table_name)}.#{connection.quote_column_name(field.definition.klass.primary_key)}"
|
229
|
-
if field.definition.klass
|
230
|
+
if definition.reflection_by_name(field.definition.klass, field.relation).options.has_key?(:through)
|
230
231
|
join = has_many_through_join(field)
|
231
232
|
return "#{primary_key} IN (SELECT #{primary_key} FROM #{join} WHERE #{field.to_sql(operator, &block)} #{self.sql_operator(operator, field)} ? )"
|
232
233
|
else
|
233
|
-
foreign_key = connection.quote_column_name(field.reflection_keys(field.definition.klass
|
234
|
+
foreign_key = connection.quote_column_name(field.reflection_keys(definition.reflection_by_name(field.definition.klass, field.relation))[1])
|
234
235
|
return "#{primary_key} IN (SELECT #{foreign_key} FROM #{connection.quote_table_name(field.klass.table_name)} WHERE #{field.to_sql(operator, &block)} #{self.sql_operator(operator, field)} ? )"
|
235
236
|
end
|
237
|
+
|
236
238
|
else
|
237
239
|
value = value.to_i if field.offset
|
238
240
|
yield(:parameter, value)
|
@@ -242,21 +244,21 @@ module ScopedSearch
|
|
242
244
|
|
243
245
|
def has_many_through_join(field)
|
244
246
|
many_class = field.definition.klass
|
245
|
-
through = many_class
|
247
|
+
through = definition.reflection_by_name(many_class, field.relation).options[:through]
|
246
248
|
connection = many_class.connection
|
247
249
|
|
248
250
|
# table names
|
249
251
|
endpoint_table_name = field.klass.table_name
|
250
252
|
many_table_name = many_class.table_name
|
251
|
-
middle_table_name = many_class
|
253
|
+
middle_table_name = definition.reflection_by_name(many_class, through).klass.table_name
|
252
254
|
|
253
255
|
# primary and foreign keys + optional condition for the many to middle join
|
254
|
-
pk1, fk1 = field.reflection_keys(many_class
|
255
|
-
condition1 = field.reflection_conditions(field.klass
|
256
|
+
pk1, fk1 = field.reflection_keys(definition.reflection_by_name(many_class, through))
|
257
|
+
condition1 = field.reflection_conditions(definition.reflection_by_name(field.klass, many_table_name))
|
256
258
|
|
257
259
|
# primary and foreign keys + optional condition for the endpoint to middle join
|
258
|
-
pk2, fk2 = field.reflection_keys(field.klass
|
259
|
-
condition2 = field.reflection_conditions(many_class
|
260
|
+
pk2, fk2 = field.reflection_keys(definition.reflection_by_name(field.klass, middle_table_name))
|
261
|
+
condition2 = field.reflection_conditions(definition.reflection_by_name(many_class, field.relation))
|
260
262
|
|
261
263
|
<<-SQL
|
262
264
|
#{connection.quote_table_name(many_table_name)}
|
@@ -307,20 +309,20 @@ module ScopedSearch
|
|
307
309
|
# +----------+ +---------+ +--------+
|
308
310
|
# uniq name for the joins are needed in case that there is more than one condition
|
309
311
|
# on different keys in the same query.
|
310
|
-
def construct_join_sql(key_relation, num
|
312
|
+
def construct_join_sql(key_relation, num)
|
311
313
|
join_sql = ""
|
312
314
|
connection = klass.connection
|
313
315
|
key = key_relation.to_s.singularize.to_sym
|
314
316
|
|
315
|
-
key_table = klass
|
317
|
+
key_table = definition.reflection_by_name(klass, key).table_name
|
316
318
|
value_table = klass.table_name.to_s
|
317
319
|
|
318
|
-
value_table_fk_key, key_table_pk = reflection_keys(klass
|
320
|
+
value_table_fk_key, key_table_pk = reflection_keys(definition.reflection_by_name(klass, key))
|
319
321
|
|
320
|
-
main_reflection = definition.klass
|
322
|
+
main_reflection = definition.reflection_by_name(definition.klass, relation)
|
321
323
|
if main_reflection
|
322
324
|
main_table = definition.klass.table_name
|
323
|
-
main_table_pk, value_table_fk_main = reflection_keys(definition.klass
|
325
|
+
main_table_pk, value_table_fk_main = reflection_keys(definition.reflection_by_name(definition.klass, relation))
|
324
326
|
|
325
327
|
join_sql = "\n INNER JOIN #{connection.quote_table_name(value_table)} #{value_table}_#{num} ON (#{main_table}.#{main_table_pk} = #{value_table}_#{num}.#{value_table_fk_main})"
|
326
328
|
value_table = " #{value_table}_#{num}"
|
@@ -339,12 +341,12 @@ module ScopedSearch
|
|
339
341
|
# +----------+ +---------+
|
340
342
|
# uniq name for the joins are needed in case that there is more than one condition
|
341
343
|
# on different keys in the same query.
|
342
|
-
def construct_simple_join_sql(
|
344
|
+
def construct_simple_join_sql(num)
|
343
345
|
connection = klass.connection
|
344
346
|
key_value_table = klass.table_name
|
345
347
|
|
346
348
|
main_table = definition.klass.table_name
|
347
|
-
main_table_pk, value_table_fk_main = reflection_keys(definition.klass
|
349
|
+
main_table_pk, value_table_fk_main = reflection_keys(definition.reflection_by_name(definition.klass, relation))
|
348
350
|
|
349
351
|
join_sql = "\n INNER JOIN #{connection.quote_table_name(key_value_table)} #{key_value_table}_#{num} ON (#{connection.quote_table_name(main_table)}.#{connection.quote_column_name(main_table_pk)} = #{key_value_table}_#{num}.#{connection.quote_column_name(value_table_fk_main)})"
|
350
352
|
return join_sql
|
data/scoped_search.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |gem|
|
|
29
29
|
gem.require_paths = ["lib"]
|
30
30
|
|
31
31
|
gem.required_ruby_version = '>= 1.9.3'
|
32
|
-
gem.add_runtime_dependency('activerecord', '>= 3.
|
32
|
+
gem.add_runtime_dependency('activerecord', '>= 3.2.0')
|
33
33
|
gem.add_development_dependency('rspec', '~> 3.0')
|
34
34
|
gem.add_development_dependency('rake')
|
35
35
|
|
@@ -44,15 +44,8 @@ describe ScopedSearch, "API" do
|
|
44
44
|
@class.should respond_to(:search_for)
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
@class.search_for('query').class.should eql(ActiveRecord::Relation)
|
50
|
-
end
|
51
|
-
|
52
|
-
elsif ActiveRecord::VERSION::MAJOR == 4
|
53
|
-
it "should return a ActiveRecord::Relation instance" do
|
54
|
-
@class.search_for('query').class.superclass.should eql(ActiveRecord::Relation)
|
55
|
-
end
|
47
|
+
it "should return a ActiveRecord::Relation instance" do
|
48
|
+
@class.search_for('query').should be_a(ActiveRecord::Relation)
|
56
49
|
end
|
57
50
|
end
|
58
51
|
end
|
@@ -96,13 +96,8 @@ require "spec_helper"
|
|
96
96
|
end
|
97
97
|
|
98
98
|
it "should find all bars with a fact name color and fact value gold of descendant class" do
|
99
|
-
|
100
|
-
MyItem.search_for('facts.color = gold').first.name.should eql('barbary')
|
101
|
-
end
|
99
|
+
MyItem.search_for('facts.color = gold').first.name.should eql('barbary')
|
102
100
|
end
|
103
|
-
|
104
101
|
end
|
105
|
-
|
106
102
|
end
|
107
103
|
end
|
108
|
-
|
@@ -222,9 +222,9 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
|
|
222
222
|
end
|
223
223
|
|
224
224
|
after do
|
225
|
-
|
226
|
-
|
227
|
-
ActiveRecord::Migration.drop_table(:
|
225
|
+
ScopedSearch::RSpec::Database.drop_model(Joo)
|
226
|
+
ScopedSearch::RSpec::Database.drop_model(Dar)
|
227
|
+
ActiveRecord::Migration.drop_table(:dars_joos) if ActiveRecord::Migration.table_exists?(:dars_joos)
|
228
228
|
end
|
229
229
|
|
230
230
|
it "should find all records with at least one associated bar record containing 'bar'" do
|
@@ -336,15 +336,12 @@ ScopedSearch::RSpec::Database.test_databases.each do |db|
|
|
336
336
|
ActiveRecord::Migration.drop_table(:zoos)
|
337
337
|
end
|
338
338
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
Zoo.search_for('baz').length.should == 3
|
343
|
-
end
|
339
|
+
it "should find the three records that are related to a baz record" do
|
340
|
+
Zoo.search_for('baz').length.should == 3
|
341
|
+
end
|
344
342
|
|
345
|
-
|
346
|
-
|
347
|
-
end
|
343
|
+
it "should find no records that are related to a baz record" do
|
344
|
+
Zoo.search_for('related=baz AND related="baz too!"').length.should == 0
|
348
345
|
end
|
349
346
|
end
|
350
347
|
|
data/spec/lib/database.rb
CHANGED
@@ -20,7 +20,7 @@ module ScopedSearch::RSpec::Database
|
|
20
20
|
|
21
21
|
@database_connections ||= YAML.load(File.read(file))
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def self.test_databases
|
25
25
|
database_names = test_databases_configuration.keys.sort
|
26
26
|
if ENV['EXCLUDE_DATABASE'].present?
|
@@ -59,6 +59,10 @@ module ScopedSearch::RSpec::Database
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def self.drop_model(klass)
|
62
|
+
klass.constants.grep(/\AHABTM_/).each do |habtm_class|
|
63
|
+
ActiveRecord::Migration.drop_table(klass.const_get(habtm_class).table_name)
|
64
|
+
klass.send(:remove_const, habtm_class)
|
65
|
+
end
|
62
66
|
ActiveRecord::Migration.drop_table(klass.table_name)
|
63
67
|
end
|
64
|
-
end
|
68
|
+
end
|
@@ -25,33 +25,15 @@ describe ScopedSearch::Definition do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
describe '#initialize' do
|
28
|
+
it "should create the named scope when" do
|
29
|
+
@klass.should_receive(:scope).with(:search_for, instance_of(Proc))
|
30
|
+
ScopedSearch::Definition.new(@klass)
|
31
|
+
end
|
28
32
|
|
29
|
-
if
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
ScopedSearch::Definition.new(@klass)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should not create the named scope if it already exists" do
|
37
|
-
@klass.stub(:search_for)
|
38
|
-
@klass.should_not_receive(:named_scope)
|
39
|
-
ScopedSearch::Definition.new(@klass)
|
40
|
-
end
|
41
|
-
|
42
|
-
elsif ActiveRecord::VERSION::MAJOR == 3
|
43
|
-
|
44
|
-
it "should create the named scope when" do
|
45
|
-
@klass.should_receive(:scope).with(:search_for, instance_of(Proc))
|
46
|
-
ScopedSearch::Definition.new(@klass)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should not create the named scope if it already exists" do
|
50
|
-
@klass.stub(:search_for)
|
51
|
-
@klass.should_not_receive(:scope)
|
52
|
-
ScopedSearch::Definition.new(@klass)
|
53
|
-
end
|
54
|
-
|
33
|
+
it "should not create the named scope if it already exists" do
|
34
|
+
@klass.stub(:search_for)
|
35
|
+
@klass.should_not_receive(:scope)
|
36
|
+
ScopedSearch::Definition.new(@klass)
|
55
37
|
end
|
56
38
|
end
|
57
39
|
end
|
@@ -10,8 +10,8 @@ describe ScopedSearch::QueryBuilder do
|
|
10
10
|
@definition.stub(:profile=).and_return(true)
|
11
11
|
end
|
12
12
|
|
13
|
-
it "should
|
14
|
-
ScopedSearch::QueryBuilder.build_query(@definition, nil).should
|
13
|
+
it "should raise an ArgumentError if the query is not set" do
|
14
|
+
lambda { ScopedSearch::QueryBuilder.build_query(@definition, nil) }.should raise_error(ArgumentError)
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should return empty conditions if the query is blank" do
|
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: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amos Benari
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2015-01-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -18,14 +18,14 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 3.
|
21
|
+
version: 3.2.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
|
-
version: 3.
|
28
|
+
version: 3.2.0
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: rspec
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,9 +82,10 @@ files:
|
|
82
82
|
- CHANGELOG.rdoc
|
83
83
|
- CONTRIBUTING.rdoc
|
84
84
|
- Gemfile
|
85
|
-
- Gemfile.
|
85
|
+
- Gemfile.activerecord32
|
86
86
|
- Gemfile.activerecord40
|
87
87
|
- Gemfile.activerecord41
|
88
|
+
- Gemfile.activerecord42
|
88
89
|
- LICENSE
|
89
90
|
- README.rdoc
|
90
91
|
- Rakefile
|