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 CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 65909cc6d8f99929aa4c76ba6a52e23dd8b85f59
4
- data.tar.gz: 8ed82b1eab66fe78fcfc2b7b1630a8cbd2e2dcf3
5
- SHA512:
6
- metadata.gz: fd26998a2330f3b034cdad89efe07ab3a52e0125db072da03533aa0038e091240baf0af3428ddc84de5b7e7e558b9a0c5fe6b095cf9a30acee503dbd359cb27e
7
- data.tar.gz: 62a9b2a4ae2e8e5d8b28b996199b500c210f63ef53805e1c5ce491b7273832a5aed11155ff86a83dc7c4f4d5f6d66aa8a88b1db7d524dd2ca24d622c769fa0ea
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
- yeti_search = YetiSearch(active: true, name: 'Jimmy', location_in: %w[NY LA]) # or params[:search]
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 target.is_a?(Class) && target.ancestors.include?(::ActiveRecord::Base) ||
8
- target.is_a?(::ActiveRecord::Relation)
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
@@ -41,6 +41,10 @@ module Searchlight
41
41
  raise e
42
42
  end
43
43
 
44
+ def self.search_target=(value)
45
+ @search_target = value
46
+ end
47
+
44
48
  def search_methods
45
49
  public_methods.map(&:to_s).select { |m| m.start_with?('search_') }
46
50
  end
@@ -1,3 +1,3 @@
1
1
  module Searchlight
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -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) { Named::Class.new('SearchClass', Searchlight::Search).tap { |klass| klass.search_on target } }
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 eq([:where])
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 class" do
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.0.0
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-17 00:00:00.000000000 Z
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: []