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 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