searchlight 1.2.4 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ebb954502f32317df1fe4fb490178e3c868a541c
4
- data.tar.gz: b0d0283e388c84a917c1c0d627752ce0b625a10c
3
+ metadata.gz: a5654905b697feb05239ed5b783d46e6a282eaa4
4
+ data.tar.gz: 7b9622f4a6d5d9f7cdcc2429941fc08f36e6c491
5
5
  SHA512:
6
- metadata.gz: 001d3bfe0e77b84ae6d256892310d18c63cb54ea416c2d3b7b794d5374c228d17423e32d3c82abdb59da8db6886b3a449c591b863a4ac9d578e9d34431d7b8ea
7
- data.tar.gz: 72c116a81eb742c6d7ecf97c982d8ec99731c1321aee96d0246491c11c3725d8ab747d8eb36ca44b93c14751e24a4b275a465a28c6b77e7f254c28864c714b8a
6
+ metadata.gz: 64e8e55512aac81f5bed20ac97152a012211cdfdcb25906f62cb62b52e0a8970eb8111f991b85120f382e57771cea3f23e64edf4d4bcb0673b8983dc12a91f26
7
+ data.tar.gz: 491c812aa4973a4cfca1b2948f435a647ab1c59da69ea40414073bd93d780d4619afe5a5c10bebfee1a5509bf8915693abd7723b5e5080db29ef2c7bc5cde29b
data/.gitignore CHANGED
@@ -18,3 +18,4 @@ spec/reports
18
18
  test/tmp
19
19
  test/version_tmp
20
20
  tmp
21
+ gemfiles/*.lock
data/.travis.yml CHANGED
@@ -4,3 +4,7 @@ rvm:
4
4
  - jruby-19mode # JRuby in 1.9 mode
5
5
  - rbx-19mode # JRuby in 1.9 mode
6
6
  - 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"
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
@@ -2,4 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in searchlight.gemspec
4
4
  gemspec
5
- gem 'coveralls', require: false
5
+
6
+ gem 'rspec', '~> 2.13'
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 ActionView. We'd love to get pull requests for others. :)
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`.
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => ".."
4
+
5
+ gem "rails", "~> 3.2.13"
6
+ gem 'mongoid', "~> 3.1.4"
7
+ gem 'coveralls', require: false
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => '..'
4
+
5
+ gem "rails", "~> 4.0.0"
6
+ gem "mongoid"
7
+ gem 'bson_ext'
8
+ gem 'coveralls', require: false
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)
@@ -1,3 +1,3 @@
1
1
  module Searchlight
2
- VERSION = "1.2.4"
2
+ VERSION = "1.3.0"
3
3
  end
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
- require 'simplecov'
3
- SimpleCov.start
4
- require 'coveralls'
5
- Coveralls.wear!
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
 
@@ -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.2.4
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-06-24 00:00:00.000000000 Z
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