searchlight 1.3.1 → 2.0.0

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: 4ca4e4a2693cd9315c4734f63f2e3cdbb560d8f9
4
- data.tar.gz: 5182116d73d4fd2da4d2ef187f7be4df210cab7f
3
+ metadata.gz: d87d47fdacfae5b1d8d87d2c34b6443610fb4f88
4
+ data.tar.gz: 639cb63efe19379336e0fbcd65b8d66f0d265f2a
5
5
  SHA512:
6
- metadata.gz: b1b65c23ac4951fde9cd7810ee92fb4374838efc3df42cbd4861439098516557bccd500d08a3f1d135dcf562a78114438cfff3a82af296df6ce13fd73e4b4216
7
- data.tar.gz: 0963fe2edc3ced89da8c97132425bbe1152a38445ebe168537d20a1af21bed960faaf38f3709b740327727d951de3e764621409242aac9eadd00e27494cd5b2f
6
+ metadata.gz: 9785b92c697fb59b0ae3aebd88af3f1913c04df0ff99aed3b73923b13d2d313d9923f98b217a7646be742c163ab892d61ce3eb8cff77960da21a132979a1717d
7
+ data.tar.gz: 5438b35af95bcf804ff0898f8989f0d804f7bb1b46f9f74642e59d3a98c5a27ac70c681a988b8ffca545aa9253a9339b3f3efca9fe29e7beaca868b70b0d73df
data/.travis.yml CHANGED
@@ -1,10 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - jruby-19mode # JRuby in 1.9 mode
5
- - rbx-19mode # JRuby in 1.9 mode
6
4
  - 2.0.0
7
- gemfile:
8
- - gemfiles/Gemfile.rails-3.2.x
9
- - gemfiles/Gemfile.rails-4.0.x
10
- env: JRUBY_OPTS="-Xcext.enabled=true"
5
+ - 2.1.1
data/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
2
2
 
3
3
  Searchlight does its best to use [semantic versioning](http://semver.org).
4
4
 
5
+ ## v2.0.0
6
+
7
+ Now with fewer features! :D
8
+
9
+ ### No more ORM adapters
10
+
11
+ ORM "adapters", which were never actually necessary, have been removed. They required lots of hackery, added test dependencies, and sometimes introduced [weird bugs](https://github.com/nathanl/searchlight/pull/15). All that just so that if you said your class `searches :first_name, :last_name`, we could save you from typing simple search methods like:
12
+
13
+ ```ruby
14
+ def search_first_name
15
+ search.where(first_name: first_name)
16
+ end
17
+ ```
18
+
19
+ You can easily save yourself this effort with something like:
20
+
21
+ ```ruby
22
+ %w[name address pant_size].each do |attr|
23
+ define_method("search_#{attr}") do
24
+ search.where(:"#{attr}" => attr)
25
+ end
26
+ end
27
+ ```
28
+
29
+ ...and you'll get much saner backtraces if anything goes wrong.
30
+
31
+ **ActiveRecord users**: note that with this change, you'll need to update your `search_on` calls to return an `ActiveRecord::Relation` so that, if no options are passed, you don't return the model class itself. Eg, instead of `search_on User`, do `search_on User.all` for Rails > 4 or `search_on User.scoped` for Rails < 4.
32
+
33
+ With this change, Searchlight no longer has any ties to any ORM, but can still work with any of them that use method chaining. Hooray!
34
+
5
35
  ## v1.3.1
6
36
 
7
37
  Add license to gemspec, thanks to notice from Benjamin Fleischer - see [his blog post](http://www.benjaminfleischer.com/2013/07/12/make-the-world-a-better-place-put-a-license-in-your-gemspec/)
data/Gemfile CHANGED
@@ -2,5 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in searchlight.gemspec
4
4
  gemspec
5
-
6
- gem 'rspec', '~> 2.13'
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Searchlight
2
2
 
3
- Searchlight helps you build searches from options via Ruby methods that you write.
3
+ Searchlight is a low-magic way to build database searches using an ORM.
4
4
 
5
- Searchlight can work with any ORM or object that can build a query using chained methods (eg, ActiveRecord's `.where(...).where(...).limit(...)`). It comes with modules for integrating with ActiveRecord and ActionView, but can easily be used in any Ruby program.
5
+ Searchlight can work with **any** ORM or object that can build a query using **chained method calls** (eg, ActiveRecord's `.where(...).where(...).limit(...)`, or similar chains with [Sequel](https://rubygems.org/gems/sequel), [Mongoid](https://rubygems.org/gems/mongoid), etc).
6
6
 
7
7
  [![Gem Version](https://badge.fury.io/rb/searchlight.png)](https://rubygems.org/gems/searchlight)
8
8
  [![Code Climate](https://codeclimate.com/github/nathanl/searchlight.png)](https://codeclimate.com/github/nathanl/searchlight)
@@ -21,10 +21,12 @@ The basic idea of Searchlight is to build a search by chaining method calls that
21
21
  For example, if you have a Searchlight search class called `YetiSearch`, and you instantiate it like this:
22
22
 
23
23
  ```ruby
24
- search = YetiSearch.new(active: true, name: 'Jimmy', location_in: %w[NY LA]) # or params[:search]
24
+ search = YetiSearch.new(
25
+ active: true, name: 'Jimmy', location_in: %w[NY LA] # or params[:search]
26
+ )
25
27
  ```
26
28
 
27
- ... calling `results` on the instance will build a search by chaining calls to `search_active`, `search_name`, and `search_location`.
29
+ ... calling `results` on the instance will build a search by chaining calls to `search_active`, `search_name`, and `search_location_in`.
28
30
 
29
31
  The `results` method will then return the return value of the last search method. If you're using ActiveRecord, this would be an `ActiveRecord::Relation`, and you can then call `each` to loop through the results, `to_sql` to get the generated query, etc.
30
32
 
@@ -38,7 +40,9 @@ A search class has three main parts: a target, options, and methods. For example
38
40
  class PersonSearch < Searchlight::Search
39
41
 
40
42
  # The search target; in this case, an ActiveRecord model.
41
- search_on Person
43
+ # This is the starting point for any chaining we do, and it's what
44
+ # will be returned if no search options are passed.
45
+ search_on Person.all
42
46
 
43
47
  # The options the search understands. Supply any combination of them to an instance.
44
48
  searches :first_name, :last_name
@@ -120,7 +124,7 @@ search = MySearchClass.new(awesomeness: 'Xtreme')
120
124
 
121
125
  ... your search methods can use:
122
126
 
123
- - `awesomeness` to retrive the given value, `'Xtreme'`
127
+ - `awesomeness` to retrieve the given value, `'Xtreme'`
124
128
  - `awesomeness?` to get a boolean version: `true`
125
129
 
126
130
  The boolean conversion is form-friendly, so that `0`, `'0'`, and `'false'` are considered `false`.
@@ -181,7 +185,7 @@ You can define defaults for boolean attributes if you treat them as "yes/no/eith
181
185
  ```ruby
182
186
  class AnimalSearch < Searchlight::Search
183
187
 
184
- search_on Animal
188
+ search_on Animal.all
185
189
 
186
190
  searches :is_fictional
187
191
 
@@ -214,7 +218,7 @@ You can subclass an existing search class and support all the same options with
214
218
 
215
219
  ```ruby
216
220
  class VillageSearch < CitySearch
217
- search_on Village
221
+ search_on Village.all
218
222
  end
219
223
  ```
220
224
 
@@ -286,27 +290,9 @@ class OrdersController < ApplicationController
286
290
  end
287
291
  end
288
292
  ```
289
- ## Adapters
293
+ ## ActionView Adapter
290
294
 
291
- Currently, Searchlight has adapters for ActiveRecord, ActionView, and Mongoid. We'd love to get pull requests for others. :)
292
-
293
- ### ActiveRecord and Mongoid
294
-
295
- When you call `search_on` in your Searchlight class, Searchlight checks whether the search target comes from ActiveRecord or Mongoid, and, if so, mixes a module into your class.
296
-
297
- For each of your search options, the module will have the simplest possible search method defined. For example, if your class `searches :name`, the ActiveRecord module will have this method:
298
-
299
- ```ruby
300
- def search_name
301
- search.where(name: name)
302
- end
303
- ```
304
-
305
- Since that method is in a parent module, you can easily override it by defining your own method. You can also call `super` in the method you define.
306
-
307
- ### ActionView
308
-
309
- Similarly, Searchlight adds ActionView-friendly methods to your classes if it sees that `ActionView` is a defined constant. See the code for details, but the upshot is that you can use a search with `form_for`.
295
+ Searchlight's ActionView adapter adds ActionView-friendly methods to your classes if it sees that `ActionView` is a defined constant. See the code for details, but the upshot is that you can use a search with `form_for`.
310
296
 
311
297
  ## Compatibility
312
298
 
@@ -337,4 +323,4 @@ Or install it yourself as:
337
323
  ## Shout Outs
338
324
 
339
325
  - The excellent [Mr. Adam Hunter](https://github.com/adamhunter), co-creator of Searchlight.
340
- - [TMA](http://tma1.com) for supporting the development of Searchlight.
326
+ - [TMA](http://tma1.com) for supporting the initial development of Searchlight.
data/lib/searchlight.rb CHANGED
@@ -7,6 +7,4 @@ end
7
7
 
8
8
  require 'searchlight/dsl'
9
9
  require 'searchlight/search'
10
- require 'searchlight/adapters/active_record' if defined?(::ActiveRecord)
11
- require 'searchlight/adapters/mongoid' if defined?(::Mongoid)
12
10
  require 'searchlight/adapters/action_view' if defined?(::ActionView)
@@ -5,7 +5,7 @@ module Searchlight
5
5
  module ClassMethods
6
6
 
7
7
  def model_name
8
- ActiveModel::Name.new(self, nil, 'search')
8
+ ::ActiveModel::Name.new(self, nil, 'search')
9
9
  end
10
10
 
11
11
  end
@@ -1,3 +1,3 @@
1
1
  module Searchlight
2
- VERSION = "1.3.1"
2
+ VERSION = "2.0.0"
3
3
  end
data/searchlight.gemspec CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.version = Searchlight::VERSION
10
10
  spec.authors = ["Nathan Long", "Adam Hunter"]
11
11
  spec.email = ["nathanmlong@gmail.com", "adamhunter@me.com"]
12
- spec.description = %q{Searchlight helps you build searches from options via Ruby methods that you write. Searchlight can work with any ORM or object that allows chaining search methods. It comes with modules for integrating with ActiveRecord and ActionView, but can easily be used in any Ruby program.}
13
- spec.summary = %q{Searchlight helps you build searches from options via Ruby methods that you write.}
12
+ spec.summary = %q{Searchlight is a low-magic way to build database searches using an ORM.}
13
+ spec.description = %q{Searchlight is a low-magic way to build database searches using an ORM. It's compatible with ActiveRecord, Sequel, Mongoid, and any other ORM that can build queries by chaining method calls.}
14
14
  spec.homepage = "https://github.com/nathanl/searchlight"
15
15
  spec.license = "MIT"
16
16
 
@@ -21,9 +21,16 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_dependency "named", "~> 1.0"
23
23
 
24
- spec.add_development_dependency "rspec", "~> 2.13"
24
+ spec.add_development_dependency "rspec", "~> 2.14"
25
25
  spec.add_development_dependency "bundler", "~> 1.3"
26
26
  spec.add_development_dependency "rake"
27
27
  spec.add_development_dependency "capybara", "~> 2.0"
28
28
  spec.add_development_dependency "simplecov", "~> 0.7"
29
+
30
+ # To test integration with actionview and activerecord
31
+ spec.add_development_dependency "actionview", "~> 4.1"
32
+ spec.add_development_dependency "activemodel", "~> 4.1"
33
+
34
+ # For coverage testing on Travis
35
+ spec.add_development_dependency "coveralls", "~> 0.7"
29
36
  end
data/spec/spec_helper.rb CHANGED
@@ -9,8 +9,6 @@ end
9
9
  require 'searchlight'
10
10
  $LOAD_PATH << '.'
11
11
  require 'support/mock_model'
12
- require 'support/mock_models/active_record'
13
- require 'support/mock_models/mongoid'
14
12
  require 'support/account_search'
15
13
  require 'support/spiffy_account_search'
16
14
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchlight
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Long
@@ -9,96 +9,137 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-30 00:00:00.000000000 Z
12
+ date: 2014-04-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: named
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ~>
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: '1.0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ~>
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rspec
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ~>
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '2.13'
34
+ version: '2.14'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ~>
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '2.13'
41
+ version: '2.14'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: bundler
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ~>
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
48
  version: '1.3'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ~>
53
+ - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '1.3'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rake
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - '>='
60
+ - - ">="
61
61
  - !ruby/object:Gem::Version
62
62
  version: '0'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - '>='
67
+ - - ">="
68
68
  - !ruby/object:Gem::Version
69
69
  version: '0'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: capybara
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - ~>
74
+ - - "~>"
75
75
  - !ruby/object:Gem::Version
76
76
  version: '2.0'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - ~>
81
+ - - "~>"
82
82
  - !ruby/object:Gem::Version
83
83
  version: '2.0'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: simplecov
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - ~>
88
+ - - "~>"
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0.7'
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - ~>
95
+ - - "~>"
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0.7'
98
- description: Searchlight helps you build searches from options via Ruby methods that
99
- you write. Searchlight can work with any ORM or object that allows chaining search
100
- methods. It comes with modules for integrating with ActiveRecord and ActionView,
101
- but can easily be used in any Ruby program.
98
+ - !ruby/object:Gem::Dependency
99
+ name: actionview
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '4.1'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '4.1'
112
+ - !ruby/object:Gem::Dependency
113
+ name: activemodel
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '4.1'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '4.1'
126
+ - !ruby/object:Gem::Dependency
127
+ name: coveralls
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: '0.7'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '0.7'
140
+ description: Searchlight is a low-magic way to build database searches using an ORM.
141
+ It's compatible with ActiveRecord, Sequel, Mongoid, and any other ORM that can build
142
+ queries by chaining method calls.
102
143
  email:
103
144
  - nathanmlong@gmail.com
104
145
  - adamhunter@me.com
@@ -106,9 +147,9 @@ executables: []
106
147
  extensions: []
107
148
  extra_rdoc_files: []
108
149
  files:
109
- - .gitignore
110
- - .rspec
111
- - .travis.yml
150
+ - ".gitignore"
151
+ - ".rspec"
152
+ - ".travis.yml"
112
153
  - CHANGELOG.md
113
154
  - Gemfile
114
155
  - LICENSE.txt
@@ -119,22 +160,16 @@ files:
119
160
  - gemfiles/Gemfile.rails-4.0.x
120
161
  - lib/searchlight.rb
121
162
  - lib/searchlight/adapters/action_view.rb
122
- - lib/searchlight/adapters/active_record.rb
123
- - lib/searchlight/adapters/mongoid.rb
124
163
  - lib/searchlight/dsl.rb
125
164
  - lib/searchlight/search.rb
126
165
  - lib/searchlight/version.rb
127
166
  - searchlight.gemspec
128
167
  - spec/searchlight/adapters/action_view_spec.rb
129
- - spec/searchlight/adapters/active_record_spec.rb
130
- - spec/searchlight/adapters/mongoid_spec.rb
131
168
  - spec/searchlight/search_spec.rb
132
169
  - spec/searchlight_spec.rb
133
170
  - spec/spec_helper.rb
134
171
  - spec/support/account_search.rb
135
172
  - spec/support/mock_model.rb
136
- - spec/support/mock_models/active_record.rb
137
- - spec/support/mock_models/mongoid.rb
138
173
  - spec/support/spiffy_account_search.rb
139
174
  homepage: https://github.com/nathanl/searchlight
140
175
  licenses:
@@ -146,30 +181,25 @@ require_paths:
146
181
  - lib
147
182
  required_ruby_version: !ruby/object:Gem::Requirement
148
183
  requirements:
149
- - - '>='
184
+ - - ">="
150
185
  - !ruby/object:Gem::Version
151
186
  version: '0'
152
187
  required_rubygems_version: !ruby/object:Gem::Requirement
153
188
  requirements:
154
- - - '>='
189
+ - - ">="
155
190
  - !ruby/object:Gem::Version
156
191
  version: '0'
157
192
  requirements: []
158
193
  rubyforge_project:
159
- rubygems_version: 2.0.3
194
+ rubygems_version: 2.2.0
160
195
  signing_key:
161
196
  specification_version: 4
162
- summary: Searchlight helps you build searches from options via Ruby methods that you
163
- write.
197
+ summary: Searchlight is a low-magic way to build database searches using an ORM.
164
198
  test_files:
165
199
  - spec/searchlight/adapters/action_view_spec.rb
166
- - spec/searchlight/adapters/active_record_spec.rb
167
- - spec/searchlight/adapters/mongoid_spec.rb
168
200
  - spec/searchlight/search_spec.rb
169
201
  - spec/searchlight_spec.rb
170
202
  - spec/spec_helper.rb
171
203
  - spec/support/account_search.rb
172
204
  - spec/support/mock_model.rb
173
- - spec/support/mock_models/active_record.rb
174
- - spec/support/mock_models/mongoid.rb
175
205
  - spec/support/spiffy_account_search.rb
@@ -1,96 +0,0 @@
1
- module Searchlight
2
- module Adapters
3
- module ActiveRecord
4
-
5
- def search_on(target)
6
- super
7
- extend Search if is_active_record?(target)
8
- convert_to_relation if is_active_record_class?(target)
9
- end
10
-
11
- module Search
12
- def searches(*attribute_names)
13
- super
14
-
15
- # Ensure this class only adds one search module to the ancestors chain
16
- if @ar_searches_module.nil?
17
- @ar_searches_module = Named::Module.new("SearchlightActiveRecordSearches(#{self})")
18
- include @ar_searches_module
19
- end
20
-
21
- eval_string = attribute_names.map { |attribute_name|
22
- model_class = model_class_for(search_target)
23
- if model_has_db_attribute?(attribute_name.to_s)
24
-
25
- <<-UNICORN_BILE
26
- def search_#{attribute_name}
27
- search.where('#{attribute_name}' => public_send("#{attribute_name}"))
28
- end
29
- UNICORN_BILE
30
- else
31
- <<-MERMAID_TEARS
32
- def search_#{attribute_name}
33
- raise Searchlight::Adapters::ActiveRecord::UndefinedColumn,
34
- "Class `#{model_class}` has no column `#{attribute_name}`; please define `search_#{attribute_name}` on `\#{self.class}` to clarify what you intend to search for"
35
- end
36
- MERMAID_TEARS
37
- end
38
-
39
- }.join
40
-
41
- @ar_searches_module.module_eval(eval_string, __FILE__, __LINE__)
42
- end
43
-
44
- # The idea here is to provide a means to allow users to bypass the check if it causes problems (e.g. during
45
- # `rake assets:precompile` if the DB has yet to be created). To bypass this, a user could monkey patch as
46
- # follows:
47
- #
48
- # module Searchlight::Adapters::ActiveRecord::Search
49
- # def model_has_db_attribute?(attribute_name)
50
- # model_class_for(search_target).columns_hash.keys.include?(attribute_name)
51
- # rescue StandardError
52
- # true
53
- # end
54
- # end
55
- #
56
- # Alternatively, they could monkey-patch Searchlight::Adapters::ActiveRecord::Search::model_has_db_attribute
57
- # to simply always return true, though they would then not get the benefit of the improved error messaging.
58
- #
59
- def model_has_db_attribute?(attribute_name)
60
- model_class_for(search_target).columns_hash.keys.include?(attribute_name)
61
- end
62
- end
63
-
64
- protected
65
-
66
- def is_active_record?(target)
67
- is_active_record_class?(target) || is_active_record_relation?(target)
68
- end
69
-
70
- def is_active_record_class?(target)
71
- target.is_a?(Class) && target.ancestors.include?(::ActiveRecord::Base)
72
- end
73
-
74
- def is_active_record_relation?(target)
75
- target.is_a?(::ActiveRecord::Relation)
76
- end
77
-
78
- # Ensure that searches without options still return enumerable results
79
- def convert_to_relation
80
- self.search_target = (active_record_version >= 4) ? search_target.all : search_target.scoped
81
- end
82
-
83
- def model_class_for(target)
84
- is_active_record_class?(target) ? target : target.engine
85
- end
86
-
87
- def active_record_version
88
- ::ActiveRecord::VERSION::MAJOR.to_i
89
- end
90
-
91
- UndefinedColumn = Class.new(StandardError)
92
- end
93
- end
94
- end
95
-
96
- Searchlight::Search.extend(Searchlight::Adapters::ActiveRecord)
@@ -1,60 +0,0 @@
1
- module Searchlight
2
- module Adapters
3
- module Mongoid
4
-
5
- def search_on(target)
6
- super
7
- extend Search if mongoid?(target)
8
- end
9
-
10
- module Search
11
-
12
- def searches(*attributes_names)
13
- super
14
-
15
- attributes_names.map do |attribute_name|
16
- method_name = "search_#{attribute_name}"
17
- if field?(attribute_name)
18
- define_method method_name do
19
- search.where(attribute_name.to_s => public_send(attribute_name))
20
- end
21
- else
22
- define_method method_name do
23
- raise Searchlight::Adapters::Mongoid::UndefinedColumn,
24
- "Class `#{self.class.model_class}` has no field `#{attribute_name}`; please define `search_#{attribute_name}` on `#{self.class}` to clarify what you intend to search for"
25
- end
26
- end
27
- end
28
- end
29
-
30
- def field?(attributes_name)
31
- model_class.fields.has_key? attributes_name.to_s
32
- end
33
-
34
- def model_class
35
- search_target.is_a?(::Mongoid::Criteria) ? search_target.klass : search_target
36
- end
37
-
38
- end
39
-
40
- protected
41
-
42
- def mongoid?(target)
43
- mongoid_document?(target) || mongoid_criteria?(target)
44
- end
45
-
46
- def mongoid_document?(target)
47
- defined?(::Mongoid::Document) && target.include?(::Mongoid::Document)
48
- end
49
-
50
- def mongoid_criteria?(target)
51
- defined?(::Mongoid::Criteria) && target.is_a?(::Mongoid::Criteria)
52
- end
53
-
54
- UndefinedColumn = Class.new(StandardError)
55
-
56
- end
57
- end
58
- end
59
-
60
- Searchlight::Search.extend(Searchlight::Adapters::Mongoid)
@@ -1,107 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Searchlight::Adapters::ActiveRecord', adapter: true do
4
-
5
- before :all do
6
- require 'searchlight/adapters/active_record'
7
- require 'active_record'
8
- end
9
-
10
- let(:search_class) {
11
- Named::Class.new('SearchClass', Searchlight::Search).tap { |klass|
12
- klass.instance_eval(&ar_version_faker)
13
- klass.search_on target
14
- }
15
- }
16
- let(:ar_version_faker) { lambda {|klass| nil } } # no-op
17
- let(:search_instance) { search_class.new(elephants: 'yes, please') }
18
-
19
- shared_examples "search classes with an ActiveRecord target" do
20
-
21
- context "when the base model has a column matching the search term" do
22
-
23
- before :each do
24
- MockActiveRecord.stub(:columns_hash).and_return({'elephants' => 'column info...'})
25
- search_class.searches :elephants
26
- end
27
-
28
- it "adds search methods to the search class" do
29
- expect(search_class.new).to respond_to(:search_elephants)
30
- end
31
-
32
- it "defines search methods that call `where` on the search target" do
33
- search_instance.results
34
- expect(search_instance.search.called_methods).to include(:where)
35
- end
36
-
37
- it "sets arguments properly in the defined method" do
38
- search_instance.search.should_receive(:where).with('elephants' => 'yes, please')
39
- search_instance.search_elephants
40
- end
41
-
42
- end
43
-
44
- context "when the base model has no column matching the search term" do
45
-
46
- before :each do
47
- MockActiveRecord.stub(:columns_hash).and_return({})
48
- search_class.searches :elephants
49
- end
50
-
51
- it "adds search methods to the search class" do
52
- expect(search_class.new).to respond_to(:search_elephants)
53
- end
54
-
55
- it "defines search methods to raise an exception" do
56
- expect { search_instance.results }.to raise_error(
57
- Searchlight::Adapters::ActiveRecord::UndefinedColumn
58
- )
59
- end
60
-
61
- end
62
-
63
- end
64
-
65
- context "when the search target is an ActiveRecord class" do
66
-
67
- let(:target) { MockActiveRecord }
68
-
69
- describe "converting to an ActiveRecord::Relation" do
70
-
71
- context "for ActiveRecord <= 3" do
72
-
73
- let(:ar_version_faker) { lambda { |klass| klass.stub(:active_record_version).and_return(3) } }
74
-
75
- it "calls 'scoped'" do
76
- target.should_receive(:scoped)
77
- search_class
78
- end
79
-
80
- end
81
-
82
- context "for ActiveRecord >= 4" do
83
-
84
- let(:ar_version_faker) { lambda { |klass| klass.stub(:active_record_version).and_return(4) } }
85
-
86
- it "calls 'all'" do
87
- target.should_receive(:all)
88
- search_class
89
- end
90
-
91
- end
92
-
93
- end
94
-
95
- it_behaves_like "search classes with an ActiveRecord target"
96
-
97
- end
98
-
99
- context "when the search target is an ActiveRecord relation" do
100
-
101
- let(:target) { MockActiveRecord.joins(:dudes_named_milford).tap { |r| r.called_methods.clear } }
102
-
103
- it_behaves_like "search classes with an ActiveRecord target"
104
-
105
- end
106
-
107
- end
@@ -1,86 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Searchlight::Adapters::Mongoid', adapter: true do
4
-
5
- before :all do
6
- require 'mongoid'
7
- require 'searchlight/adapters/mongoid'
8
- end
9
-
10
- after :all do
11
- Object.send(:remove_const, :Mongoid)
12
- end
13
-
14
- let(:search_class) {
15
- Named::Class.new('SearchClass', Searchlight::Search).tap { |klass| klass.search_on target }
16
- }
17
-
18
- let(:search_instance) { search_class.new(elephants: 'yes, please') }
19
-
20
- shared_examples "search classes with an Mongoid target" do
21
-
22
- context "when the base model has a field matching the search term" do
23
-
24
- before do
25
- MockMongoid.stub(:fields).and_return('elephants' => 'column info...')
26
- search_class.searches :elephants
27
- end
28
-
29
- it "adds search methods to the search class" do
30
- expect(search_class.new).to respond_to(:search_elephants)
31
- end
32
-
33
- it "defines search methods that call `where` on the search target" do
34
- search_instance.results
35
- expect(search_instance.search.called_methods).to include(:where)
36
- end
37
-
38
- it "sets arguments properly in the defined method" do
39
- search_instance.search.should_receive(:where).with('elephants' => 'yes, please')
40
- search_instance.search_elephants
41
- end
42
-
43
- end
44
-
45
- context "when the base model has no field matching the search term" do
46
-
47
- before do
48
- MockMongoid.stub(fields: {})
49
- search_class.searches :elephants
50
- end
51
-
52
- it "adds search methods to the search class" do
53
- expect(search_class.new).to respond_to(:search_elephants)
54
- end
55
-
56
- it "defines search methods to raise an exception" do
57
- expect { search_instance.results }.to raise_error(
58
- Searchlight::Adapters::Mongoid::UndefinedColumn
59
- )
60
- end
61
-
62
- end
63
-
64
- end
65
-
66
- context "when the search target is a class with Mongoid::Document module" do
67
-
68
- let(:target) { MockMongoid }
69
-
70
- it_behaves_like "search classes with an Mongoid target"
71
-
72
- end
73
-
74
- context "when the search target is Mongoid::Criteria class" do
75
-
76
- let(:target) { MockMongoidCriteria.new([]) }
77
-
78
- before do
79
- target.stub(klass: MockMongoid)
80
- end
81
-
82
- it_behaves_like "search classes with an Mongoid target"
83
-
84
- end
85
-
86
- end
@@ -1,23 +0,0 @@
1
- class MockActiveRecord < MockModel
2
-
3
- def self.ancestors
4
- super + [::ActiveRecord::Base]
5
- end
6
-
7
- def self.is_a?(thing)
8
- thing == ::ActiveRecord::Base ? true : super
9
- end
10
-
11
- end
12
-
13
- class MockActiveRecordRelation < MockRelation
14
-
15
- def is_a?(thing)
16
- thing == ::ActiveRecord::Relation ? true : super
17
- end
18
-
19
- def engine
20
- MockActiveRecord
21
- end
22
-
23
- end
@@ -1,19 +0,0 @@
1
- class MockMongoid < MockModel
2
-
3
- def self.include?(thing)
4
- thing == ::Mongoid::Document ? true : super
5
- end
6
-
7
- end
8
-
9
- class MockMongoidCriteria < MockRelation
10
-
11
- def is_a?(thing)
12
- thing == ::Mongoid::Criteria ? true : super
13
- end
14
-
15
- def self.include?(thing)
16
- thing == ::Mongoid::Document ? false : super
17
- end
18
-
19
- end