seeker 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4e54247641dde163562c6f30672589e81ec77e60
4
+ data.tar.gz: ff0b0de84416467abeb06ff8319448cee81a2528
5
+ SHA512:
6
+ metadata.gz: ec497af4007218b339a5f787299a0c652e3c5c830dd6b0907b5e1ad11168db5ff094ac5e9551795658784799c022876f83c47c74fe38f152bdac86e0ea6abdf1
7
+ data.tar.gz: 994fc23535869b905d5736ef16e94a2eeee670234ece7215be98d8b3b71fa9e3cca479463b4c34b9e9a53fde63c41f308512051cdc7c7fe5bab0c8d566dcac95
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in seeker.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Szymon Przybył
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Szymon Przybył
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # Seeker
2
+
3
+ This Ruby on Rails gem provides an elegant way to separate search logic out of models.
4
+
5
+ Right now it supports only [sunspot](https://github.com/sunspot/sunspot).
6
+
7
+ ## Installation
8
+
9
+ gem 'seeker'
10
+
11
+ ## Usage
12
+
13
+ Given you have Product model:
14
+
15
+ class Product < ActiveRecord::Base
16
+ end
17
+
18
+ Create corresponding searcher:
19
+
20
+ # app/searchers/product_searcher.rb
21
+ class ProductSearcher < Seeker::Base
22
+ attr_accessor :name, :max_price
23
+
24
+ searchable do
25
+ text :name
26
+ integer :price
27
+ end
28
+
29
+ def search(query)
30
+ query.fulltext(:name, @name) if @name.present?
31
+ query.with(:price).less_than_or_equal_to(@max_price) if @max_price.present?
32
+ end
33
+ end
34
+
35
+ Use it in your controller:
36
+
37
+ class ProductsController < ApplicationController
38
+ def index
39
+ @searcher = ProductSearcher.new params[:product]
40
+ end
41
+ end
42
+
43
+ And use it in your view with form helper, just like model:
44
+
45
+ # app/views/products/index.html.slim
46
+ = form_for @searcher do |f|
47
+ = f.label :name
48
+ = f.text_field :name
49
+
50
+ = f.label :max_price
51
+ = f.number_field :max_price
52
+
53
+ = f.submit
54
+
55
+ h1 Search results
56
+ ul
57
+ = @searcher.results.each do |product|
58
+ li #{product.name} - #{product.price}
59
+
60
+
61
+ ## TODO
62
+
63
+ * add tests
64
+ * add support for ThinkingSphinx
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/seeker.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'seeker/version'
2
+ require 'seeker/railtie'
3
+ require 'seeker/base'
4
+
5
+ module Seeker
6
+ end
@@ -0,0 +1,43 @@
1
+ class Seeker::Base
2
+ def initialize(params={})
3
+ params.each do |attr, value|
4
+ self.public_send("#{attr}=", value)
5
+ end if params
6
+
7
+ super()
8
+ end
9
+
10
+ def self.model_name
11
+ @_model_name ||= begin
12
+ model = eval self.name.sub(/Searcher$/, '')
13
+ ActiveModel::Name.new(model)
14
+ end
15
+ end
16
+
17
+ def self.model
18
+ model_name.constantize
19
+ end
20
+
21
+ def self.searchable(&block)
22
+ self.model.searchable &block
23
+ end
24
+
25
+ # Searcher needs to implement it
26
+ def search(query, options = {}); end
27
+
28
+ def options
29
+ {}
30
+ end
31
+
32
+ def results
33
+ self.class.model.search(options, &method(:search)).results
34
+ end
35
+
36
+ def to_key
37
+ nil
38
+ end
39
+
40
+ def searcher?
41
+ true
42
+ end
43
+ end
@@ -0,0 +1,22 @@
1
+ module Seeker::FormHelper
2
+ def apply_form_for_options!(object_or_array, options) #:nodoc:
3
+ object = object_or_array.is_a?(Array) ? object_or_array.last : object_or_array
4
+ object = convert_to_model(object)
5
+
6
+ as = options[:as]
7
+ # added searcher
8
+ action, method = if object.respond_to?(:searcher?)
9
+ [:search, :get]
10
+ else
11
+ object.respond_to?(:persisted?) && object.persisted? ? [:edit, :put] : [:new, :post]
12
+ end
13
+
14
+ options[:html].reverse_merge!(
15
+ :class => as ? "#{action}_#{as}" : dom_class(object, action),
16
+ :id => as ? "#{action}_#{as}" : [options[:namespace], dom_id(object, action)].compact.join("_").presence,
17
+ :method => method
18
+ )
19
+
20
+ options[:url] ||= polymorphic_path(object_or_array, :format => options.delete(:format))
21
+ end
22
+ end
@@ -0,0 +1,10 @@
1
+ require 'seeker/form_helper'
2
+ require 'seeker/route_helper'
3
+
4
+ module Seeker
5
+ class Railtie < Rails::Railtie
6
+ initializer 'seeker.form_helper' do
7
+ ActionView::Base.send :include, FormHelper
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ module ActionDispatch::Routing::PolymorphicRoutes
2
+ def polymorphic_url(record_or_hash_or_array, options = {})
3
+ if record_or_hash_or_array.kind_of?(Array)
4
+ record_or_hash_or_array = record_or_hash_or_array.compact
5
+ if record_or_hash_or_array.first.is_a?(ActionDispatch::Routing::RoutesProxy)
6
+ proxy = record_or_hash_or_array.shift
7
+ end
8
+ record_or_hash_or_array = record_or_hash_or_array[0] if record_or_hash_or_array.size == 1
9
+ end
10
+
11
+ record = extract_record(record_or_hash_or_array)
12
+ record = convert_to_model(record)
13
+
14
+ args = Array === record_or_hash_or_array ?
15
+ record_or_hash_or_array.dup :
16
+ [ record_or_hash_or_array ]
17
+
18
+ inflection = if options[:action] && options[:action].to_s == "new"
19
+ args.pop
20
+ :singular
21
+ # added searcher
22
+ elsif (record.respond_to?(:persisted?) && !record.persisted? || record.respond_to?(:searcher?))
23
+ args.pop
24
+ :plural
25
+ elsif record.is_a?(Class)
26
+ args.pop
27
+ :plural
28
+ else
29
+ :singular
30
+ end
31
+
32
+ args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
33
+ named_route = build_named_route_call(record_or_hash_or_array, inflection, options)
34
+
35
+ url_options = options.except(:action, :routing_type)
36
+ unless url_options.empty?
37
+ args.last.kind_of?(Hash) ? args.last.merge!(url_options) : args << url_options
38
+ end
39
+
40
+ args.collect! { |a| convert_to_model(a) }
41
+
42
+ (proxy || self).send(named_route, *args)
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module Seeker
2
+ VERSION = "0.0.1"
3
+ end
data/seeker.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'seeker/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "seeker"
8
+ spec.version = Seeker::VERSION
9
+ spec.authors = ["Szymon Przybył"]
10
+ spec.email = ["szymon@estender.net"]
11
+ spec.description = %q{This Ruby on Rails gem provides an elegant way to separate search logic out of models.}
12
+ spec.summary = %q{It separates search indecies setup and search rules to searchers. They also may be used in form helpers just like models.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: seeker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Szymon Przybył
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: This Ruby on Rails gem provides an elegant way to separate search logic
42
+ out of models.
43
+ email:
44
+ - szymon@estender.net
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - .gitignore
50
+ - Gemfile
51
+ - LICENSE
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - lib/seeker.rb
56
+ - lib/seeker/base.rb
57
+ - lib/seeker/form_helper.rb
58
+ - lib/seeker/railtie.rb
59
+ - lib/seeker/route_helper.rb
60
+ - lib/seeker/version.rb
61
+ - seeker.gemspec
62
+ homepage: ''
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.0.3
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: It separates search indecies setup and search rules to searchers. They also
86
+ may be used in form helpers just like models.
87
+ test_files: []