searchlight 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +14 -6
- data/CHANGELOG.md +4 -0
- data/README.md +4 -2
- data/lib/searchlight/adapters/active_record.rb +25 -4
- data/lib/searchlight/search.rb +4 -0
- data/lib/searchlight/version.rb +1 -1
- data/spec/searchlight/adapters/active_record_spec.rb +39 -7
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MjNmMzE5OWE2YzM4N2ZjMDU4YWNmNGZmZTk5NzM2NGQxNWRjYzNjYw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
Y2IzNWVmNzUyOTU4NjYxYjU2YmRiNWIzZDBjZmE0YTgyMzZlMTgyNw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjE2ZTMxMDM4OTQ0NDlmNjk5MWY4ODBlMmJkNDAwZDMzZjg4Njc1NDJmZWIz
|
10
|
+
Y2UzNTIxMzg2M2E1Mzk4OGM1MzdhNmYwOGFlOGM1MDg1ZmU0MWJjNDRmYWY5
|
11
|
+
Y2IxOTM2YzU1OTRjZWU4MjhkM2FlZjQxZGU3YTU1YTcwMjc0MjI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MGQ0ZDg1YmMyZmJjYjcxNmY0ODU3MGNkNDY5YmY4NzkyOGJjMDExZThjNzk0
|
14
|
+
YjRlZDc0ODRiNTI4ZDgyNjFjNzEzOWU4ZTNjOGVlZjY5M2Y3YmI1NGYzM2My
|
15
|
+
ZGIwNTBlNzg4ZDM3ZWY4NTZmNDU0NjJiNWQ2ZTY3ODNiN2RkNmU=
|
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.1.0
|
6
|
+
|
7
|
+
ActiveRecord adapter ensures that searches return a relation, even if no options are given
|
8
|
+
|
5
9
|
## v1.0.0
|
6
10
|
|
7
11
|
- If no search target is given, search class attempts to guess based on its own name
|
data/README.md
CHANGED
@@ -14,7 +14,7 @@ The basic idea of Searchlight is to build a search by chaining method calls that
|
|
14
14
|
For example, if you have a Searchlight search class called `YetiSearch`, and you instantiate it like this:
|
15
15
|
|
16
16
|
```ruby
|
17
|
-
|
17
|
+
search = YetiSearch.new(active: true, name: 'Jimmy', location_in: %w[NY LA]) # or params[:search]
|
18
18
|
```
|
19
19
|
|
20
20
|
... calling `results` on the instance will build a search by chaining calls to `search_active`, `search_name`, and `search_location`.
|
@@ -108,7 +108,7 @@ For each search option, Searchlight defines two accessors: one for a value, and
|
|
108
108
|
For example, if your class `searches :awesomeness` and gets instantiated like:
|
109
109
|
|
110
110
|
```ruby
|
111
|
-
search = MySearchClass(awesomeness: 'Xtreme')
|
111
|
+
search = MySearchClass.new(awesomeness: 'Xtreme')
|
112
112
|
```
|
113
113
|
|
114
114
|
... your search methods can use:
|
@@ -292,6 +292,8 @@ For each of your search options, the module will have the simplest possible sear
|
|
292
292
|
|
293
293
|
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.
|
294
294
|
|
295
|
+
The adapter also ensures that searches return a relation, even if no options are given.
|
296
|
+
|
295
297
|
### ActionView
|
296
298
|
|
297
299
|
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`.
|
@@ -4,10 +4,8 @@ module Searchlight
|
|
4
4
|
|
5
5
|
def search_on(target)
|
6
6
|
super
|
7
|
-
if
|
8
|
-
|
9
|
-
extend Search
|
10
|
-
end
|
7
|
+
extend Search if is_active_record?(target)
|
8
|
+
convert_to_relation if is_active_record_class?(target)
|
11
9
|
end
|
12
10
|
|
13
11
|
module Search
|
@@ -32,6 +30,29 @@ module Searchlight
|
|
32
30
|
end
|
33
31
|
end
|
34
32
|
|
33
|
+
protected
|
34
|
+
|
35
|
+
def is_active_record?(target)
|
36
|
+
is_active_record_class?(target) || is_active_record_relation?(target)
|
37
|
+
end
|
38
|
+
|
39
|
+
def is_active_record_class?(target)
|
40
|
+
target.is_a?(Class) && target.ancestors.include?(::ActiveRecord::Base)
|
41
|
+
end
|
42
|
+
|
43
|
+
def is_active_record_relation?(target)
|
44
|
+
target.is_a?(::ActiveRecord::Relation)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Ensure that searches without options still return enumerable results
|
48
|
+
def convert_to_relation
|
49
|
+
self.search_target = (active_record_version >= 4) ? search_target.all : search_target.scoped
|
50
|
+
end
|
51
|
+
|
52
|
+
def active_record_version
|
53
|
+
::ActiveRecord::VERSION::MAJOR.to_i
|
54
|
+
end
|
55
|
+
|
35
56
|
end
|
36
57
|
end
|
37
58
|
end
|
data/lib/searchlight/search.rb
CHANGED
data/lib/searchlight/version.rb
CHANGED
@@ -7,15 +7,21 @@ describe 'Searchlight::Adapters::ActiveRecord', adapter: true do
|
|
7
7
|
require 'active_record'
|
8
8
|
end
|
9
9
|
|
10
|
-
let(:search_class) {
|
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
|
11
17
|
let(:search_instance) { search_class.new(elephants: 'yes, please') }
|
12
18
|
|
13
|
-
before :each do
|
14
|
-
search_class.searches :elephants
|
15
|
-
end
|
16
|
-
|
17
19
|
shared_examples "search classes with an ActiveRecord target" do
|
18
20
|
|
21
|
+
before :each do
|
22
|
+
search_class.searches :elephants
|
23
|
+
end
|
24
|
+
|
19
25
|
it "adds search methods to the search class" do
|
20
26
|
expect(search_class.new).to respond_to(:search_elephants)
|
21
27
|
end
|
@@ -26,7 +32,7 @@ describe 'Searchlight::Adapters::ActiveRecord', adapter: true do
|
|
26
32
|
|
27
33
|
it "defines search methods that call where on the search target" do
|
28
34
|
search_instance.results
|
29
|
-
expect(search_instance.search.called_methods).to
|
35
|
+
expect(search_instance.search.called_methods).to include(:where)
|
30
36
|
end
|
31
37
|
|
32
38
|
it "sets arguments properly in the defined method" do
|
@@ -40,11 +46,37 @@ describe 'Searchlight::Adapters::ActiveRecord', adapter: true do
|
|
40
46
|
|
41
47
|
let(:target) { MockActiveRecord }
|
42
48
|
|
49
|
+
describe "converting to an ActiveRecord::Relation" do
|
50
|
+
|
51
|
+
context "for ActiveRecord <= 3" do
|
52
|
+
|
53
|
+
let(:ar_version_faker) { lambda { |klass| klass.stub(:active_record_version).and_return(3) } }
|
54
|
+
|
55
|
+
it "calls 'scoped'" do
|
56
|
+
target.should_receive(:scoped)
|
57
|
+
search_class
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
context "for ActiveRecord >= 4" do
|
63
|
+
|
64
|
+
let(:ar_version_faker) { lambda { |klass| klass.stub(:active_record_version).and_return(4) } }
|
65
|
+
|
66
|
+
it "calls 'all'" do
|
67
|
+
target.should_receive(:all)
|
68
|
+
search_class
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
43
75
|
it_behaves_like "search classes with an ActiveRecord target"
|
44
76
|
|
45
77
|
end
|
46
78
|
|
47
|
-
context "when the search target is an ActiveRecord
|
79
|
+
context "when the search target is an ActiveRecord relation" do
|
48
80
|
|
49
81
|
let(:target) { MockActiveRecord.joins(:dudes_named_milford).tap { |r| r.called_methods.clear } }
|
50
82
|
|
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.1.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-05-
|
12
|
+
date: 2013-05-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: named
|
@@ -57,28 +57,28 @@ dependencies:
|
|
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: rails
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- - '>='
|
74
|
+
- - ! '>='
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '3'
|
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: '3'
|
84
84
|
- !ruby/object:Gem::Dependency
|
@@ -154,12 +154,12 @@ require_paths:
|
|
154
154
|
- lib
|
155
155
|
required_ruby_version: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
|
-
- - '>='
|
157
|
+
- - ! '>='
|
158
158
|
- !ruby/object:Gem::Version
|
159
159
|
version: '0'
|
160
160
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
161
|
requirements:
|
162
|
-
- - '>='
|
162
|
+
- - ! '>='
|
163
163
|
- !ruby/object:Gem::Version
|
164
164
|
version: '0'
|
165
165
|
requirements: []
|