searchlight 1.2.4 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -1
- data/README.md +8 -6
- data/gemfiles/Gemfile.rails-3.2.x +7 -0
- data/gemfiles/Gemfile.rails-4.0.x +8 -0
- data/lib/searchlight.rb +1 -0
- data/lib/searchlight/adapters/mongoid.rb +60 -0
- data/lib/searchlight/version.rb +1 -1
- data/searchlight.gemspec +0 -1
- data/spec/searchlight/adapters/action_view_spec.rb +5 -3
- data/spec/searchlight/adapters/mongoid_spec.rb +86 -0
- data/spec/spec_helper.rb +9 -4
- data/spec/support/mock_model.rb +0 -12
- data/spec/support/mock_models/active_record.rb +23 -0
- data/spec/support/mock_models/mongoid.rb +19 -0
- metadata +11 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5654905b697feb05239ed5b783d46e6a282eaa4
|
4
|
+
data.tar.gz: 7b9622f4a6d5d9f7cdcc2429941fc08f36e6c491
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64e8e55512aac81f5bed20ac97152a012211cdfdcb25906f62cb62b52e0a8970eb8111f991b85120f382e57771cea3f23e64edf4d4bcb0673b8983dc12a91f26
|
7
|
+
data.tar.gz: 491c812aa4973a4cfca1b2948f435a647ab1c59da69ea40414073bd93d780d4619afe5a5c10bebfee1a5509bf8915693abd7723b5e5080db29ef2c7bc5cde29b
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
Searchlight does its best to use [semantic versioning](http://semver.org).
|
4
4
|
|
5
|
+
## v1.3.0
|
6
|
+
|
7
|
+
New Mongoid adapter, thanks to [iliabylich](https://github.com/iliabylich).
|
8
|
+
|
5
9
|
## v1.2.4
|
6
10
|
|
7
11
|
- `options` method only returns those that map to search methods (not `attr_accessor` type values)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -10,6 +10,10 @@ Searchlight can work with any ORM or object that can build a query using chained
|
|
10
10
|
[![Coverage Status](https://coveralls.io/repos/nathanl/searchlight/badge.png?branch=master)](https://coveralls.io/r/nathanl/searchlight?branch=master)
|
11
11
|
[![Dependency Status](https://gemnasium.com/nathanl/searchlight.png)](https://gemnasium.com/nathanl/searchlight)
|
12
12
|
|
13
|
+
## Getting Started
|
14
|
+
|
15
|
+
An [introductory video](https://vimeo.com/69179161), [the demo app it uses](http://bookfinder-searchlight-demo.herokuapp.com) and [the code for that app](https://github.com/nathanl/bookfinder) are available to help you get started.
|
16
|
+
|
13
17
|
## Overview
|
14
18
|
|
15
19
|
The basic idea of Searchlight is to build a search by chaining method calls that you define. It calls **public** methods on the object you specify, based on the options you pass.
|
@@ -284,13 +288,13 @@ end
|
|
284
288
|
```
|
285
289
|
## Adapters
|
286
290
|
|
287
|
-
Currently, Searchlight has adapters for ActiveRecord and
|
291
|
+
Currently, Searchlight has adapters for ActiveRecord, ActionView, and Mongoid. We'd love to get pull requests for others. :)
|
288
292
|
|
289
|
-
### ActiveRecord
|
293
|
+
### ActiveRecord and Mongoid
|
290
294
|
|
291
|
-
When you call `search_on` in your Searchlight class, Searchlight checks whether the search target comes from ActiveRecord, and, if so, mixes a module into your class.
|
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.
|
292
296
|
|
293
|
-
For each of your search options, the module will have the simplest possible search method defined. For example, if your class `searches :name`, the module will have this method:
|
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:
|
294
298
|
|
295
299
|
```ruby
|
296
300
|
def search_name
|
@@ -300,8 +304,6 @@ For each of your search options, the module will have the simplest possible sear
|
|
300
304
|
|
301
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.
|
302
306
|
|
303
|
-
The adapter also ensures that searches return a relation, even if no options are given.
|
304
|
-
|
305
307
|
### ActionView
|
306
308
|
|
307
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`.
|
data/lib/searchlight.rb
CHANGED
@@ -8,4 +8,5 @@ end
|
|
8
8
|
require 'searchlight/dsl'
|
9
9
|
require 'searchlight/search'
|
10
10
|
require 'searchlight/adapters/active_record' if defined?(::ActiveRecord)
|
11
|
+
require 'searchlight/adapters/mongoid' if defined?(::Mongoid)
|
11
12
|
require 'searchlight/adapters/action_view' if defined?(::ActionView)
|
@@ -0,0 +1,60 @@
|
|
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)
|
data/lib/searchlight/version.rb
CHANGED
data/searchlight.gemspec
CHANGED
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency "rspec", "~> 2.13"
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
25
25
|
spec.add_development_dependency "rake"
|
26
|
-
spec.add_development_dependency "rails", ">= 3"
|
27
26
|
spec.add_development_dependency "capybara", "~> 2.0"
|
28
27
|
spec.add_development_dependency "simplecov", "~> 0.7"
|
29
28
|
end
|
@@ -2,14 +2,16 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe 'Searchlight::Adapters::ActionView', type: :feature, adapter: true do
|
4
4
|
|
5
|
+
let(:view) { ::ActionView::Base.new }
|
6
|
+
let(:search) { AccountSearch.new(paid_amount: 15) }
|
7
|
+
|
5
8
|
before :all do
|
6
9
|
require 'searchlight/adapters/action_view'
|
7
10
|
require 'action_view'
|
11
|
+
require 'active_model'
|
12
|
+
require 'active_support/core_ext'
|
8
13
|
end
|
9
14
|
|
10
|
-
let(:view) { ::ActionView::Base.new }
|
11
|
-
let(:search) { AccountSearch.new(paid_amount: 15) }
|
12
|
-
|
13
15
|
before :each do
|
14
16
|
view.stub(:protect_against_forgery?).and_return(false)
|
15
17
|
end
|
@@ -0,0 +1,86 @@
|
|
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
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
require 'capybara/rspec'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
if ENV["TRAVIS"]
|
3
|
+
require 'coveralls'
|
4
|
+
Coveralls.wear!
|
5
|
+
else
|
6
|
+
require 'simplecov'
|
7
|
+
SimpleCov.start { add_filter "/spec" }
|
8
|
+
end
|
6
9
|
require 'searchlight'
|
7
10
|
$LOAD_PATH << '.'
|
8
11
|
require 'support/mock_model'
|
12
|
+
require 'support/mock_models/active_record'
|
13
|
+
require 'support/mock_models/mongoid'
|
9
14
|
require 'support/account_search'
|
10
15
|
require 'support/spiffy_account_search'
|
11
16
|
|
data/spec/support/mock_model.rb
CHANGED
@@ -3,18 +3,6 @@ class MockModel
|
|
3
3
|
def self.method_missing(method, *args, &block)
|
4
4
|
MockRelation.new(method)
|
5
5
|
end
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
class MockActiveRecord < MockModel
|
10
|
-
|
11
|
-
def self.ancestors
|
12
|
-
super + [::ActiveRecord::Base]
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.is_a?(thing)
|
16
|
-
thing == ::ActiveRecord::Base ? true : super
|
17
|
-
end
|
18
6
|
|
19
7
|
end
|
20
8
|
|
@@ -0,0 +1,23 @@
|
|
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
|
@@ -0,0 +1,19 @@
|
|
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
|
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.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Long
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: named
|
@@ -67,20 +67,6 @@ dependencies:
|
|
67
67
|
- - '>='
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
|
-
- !ruby/object:Gem::Dependency
|
71
|
-
name: rails
|
72
|
-
requirement: !ruby/object:Gem::Requirement
|
73
|
-
requirements:
|
74
|
-
- - '>='
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
version: '3'
|
77
|
-
type: :development
|
78
|
-
prerelease: false
|
79
|
-
version_requirements: !ruby/object:Gem::Requirement
|
80
|
-
requirements:
|
81
|
-
- - '>='
|
82
|
-
- !ruby/object:Gem::Version
|
83
|
-
version: '3'
|
84
70
|
- !ruby/object:Gem::Dependency
|
85
71
|
name: capybara
|
86
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,20 +115,26 @@ files:
|
|
129
115
|
- README.md
|
130
116
|
- Rakefile
|
131
117
|
- TODO.md
|
118
|
+
- gemfiles/Gemfile.rails-3.2.x
|
119
|
+
- gemfiles/Gemfile.rails-4.0.x
|
132
120
|
- lib/searchlight.rb
|
133
121
|
- lib/searchlight/adapters/action_view.rb
|
134
122
|
- lib/searchlight/adapters/active_record.rb
|
123
|
+
- lib/searchlight/adapters/mongoid.rb
|
135
124
|
- lib/searchlight/dsl.rb
|
136
125
|
- lib/searchlight/search.rb
|
137
126
|
- lib/searchlight/version.rb
|
138
127
|
- searchlight.gemspec
|
139
128
|
- spec/searchlight/adapters/action_view_spec.rb
|
140
129
|
- spec/searchlight/adapters/active_record_spec.rb
|
130
|
+
- spec/searchlight/adapters/mongoid_spec.rb
|
141
131
|
- spec/searchlight/search_spec.rb
|
142
132
|
- spec/searchlight_spec.rb
|
143
133
|
- spec/spec_helper.rb
|
144
134
|
- spec/support/account_search.rb
|
145
135
|
- spec/support/mock_model.rb
|
136
|
+
- spec/support/mock_models/active_record.rb
|
137
|
+
- spec/support/mock_models/mongoid.rb
|
146
138
|
- spec/support/spiffy_account_search.rb
|
147
139
|
homepage: https://github.com/nathanl/searchlight
|
148
140
|
licenses:
|
@@ -172,9 +164,12 @@ summary: Searchlight helps you build searches from options via Ruby methods that
|
|
172
164
|
test_files:
|
173
165
|
- spec/searchlight/adapters/action_view_spec.rb
|
174
166
|
- spec/searchlight/adapters/active_record_spec.rb
|
167
|
+
- spec/searchlight/adapters/mongoid_spec.rb
|
175
168
|
- spec/searchlight/search_spec.rb
|
176
169
|
- spec/searchlight_spec.rb
|
177
170
|
- spec/spec_helper.rb
|
178
171
|
- spec/support/account_search.rb
|
179
172
|
- spec/support/mock_model.rb
|
173
|
+
- spec/support/mock_models/active_record.rb
|
174
|
+
- spec/support/mock_models/mongoid.rb
|
180
175
|
- spec/support/spiffy_account_search.rb
|