search_redux 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 05db95b0f1118f55c5e23b538d535fd045c1f423
4
+ data.tar.gz: 37ecb95b3b84d3e6654561f917529c8f7455aed7
5
+ SHA512:
6
+ metadata.gz: f83575ea4ced7d460ab58edd6ab1a2651e586e48d717da44ad1af4a7af3b5048646cb436e2295f6a5017a2012773f29a59f49464d814e35ea62825142c40d578
7
+ data.tar.gz: bf3d3f9024b2e449e73125da20cd223df7478201008d6ed98691f4304285a9717f8b852c7b464bd93d57efc766e5018223c14d9d2c6df28da160071927ce6054
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,27 @@
1
+ # Full text search redux
2
+
3
+ The current version is just a code extract of a simple text search logic using Postgres [functionality](http://www.postgresql.org/docs/8.3/static/textsearch.html) and a simple fallback for other RDBMs (e.g. Mysql)
4
+
5
+ For now the usage is limited, it expects a `title` and a `content` column.
6
+
7
+ ## Installation
8
+
9
+ Include the gem in your Gemfile:
10
+
11
+ ```ruby
12
+ gem 'search_redux'
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```ruby
18
+ class MyModel
19
+ act_as_searchable
20
+ end
21
+
22
+ class MyController
23
+ def index
24
+ an_article = MyModel.text_search 'query phrase'
25
+ end
26
+ end
27
+ ```
@@ -0,0 +1,27 @@
1
+ require 'search_redux/version'
2
+ require 'search_redux/errors'
3
+ require 'search_redux/helpers'
4
+ require 'search_redux/glue'
5
+ require 'search_redux/searchable'
6
+ require 'search_redux/rdbms/mysql'
7
+ require 'search_redux/rdbms/postgres'
8
+
9
+ require 'search_redux/railtie'
10
+
11
+ module SearchRedux
12
+ extend Helpers
13
+
14
+ module ClassMethods
15
+ def act_as_searchable(options = {})
16
+ attr_accessor :searchable
17
+
18
+ @searchable = SearchRedux::Searchable.new options
19
+ end
20
+
21
+ def text_search(query)
22
+ raise(Errors::ActAsSearchableUnintialized, 'Use act_as_searchable') unless @searchable
23
+
24
+ @searchable.full_text_search(query, self)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ module SearchRedux
2
+ class Error < StandardError; end
3
+
4
+ module Errors
5
+ class ActAsSearchableUnintialized < SearchRedux::Error; end
6
+
7
+ class NoQuery < SearchRedux::Error; end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module SearchRedux
2
+ module Glue
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ module SearchRedux
2
+ module Helpers
3
+ def select_best_query_strategy(adapter, query)
4
+ case adapter
5
+ when /mysql.*/i
6
+ SearchRedux::Mysql.compatible_search(query)
7
+ when /postgres.*/i
8
+ SearchRedux::Postgres.compatible_search(query)
9
+ end
10
+ end
11
+
12
+ def db_adapter
13
+ ActiveRecord::Base::connection.adapter_name
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ module SearchRedux
2
+ require 'rails'
3
+
4
+ class Railtie < Rails::Railtie
5
+ initializer 'search_redux.insert_into_active_record' do |app|
6
+ SearchRedux::Railtie.insert
7
+ end
8
+
9
+ # rake_tasks { load 'tasks/search_redux.rake' }
10
+ end
11
+
12
+ class Railtie
13
+ def self.insert
14
+ if defined? ActiveRecord
15
+ # do the dew
16
+ ActiveRecord::Base.send(:include, SearchRedux::Glue)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ module SearchRedux
2
+ class Mysql
3
+ def self.compatible_search(query)
4
+ ->(obj) { obj.where("title like :q or content like :q", q: "%#{query}%") }
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,30 @@
1
+ module SearchRedux
2
+ class Postgres
3
+ class << self
4
+ attr_accessor :sanitized_query
5
+
6
+ def compatible_search(options)
7
+ query = options[:query]
8
+
9
+ rank_query = rank_sql options[:rank], query
10
+ search_query = search_sql options[:columns]
11
+
12
+ ->(obj) { obj.where(search_query, q: query).order(rank_query) }
13
+ end
14
+
15
+ def rank_sql(rank_column, query)
16
+ sanitized_query = ActionController::Base.helpers.sanitize(query)
17
+
18
+ "ts_rank(to_tsvector(#{rank_column}), plainto_tsquery('#{sanitized_query}')) desc"
19
+ end
20
+
21
+ def search_sql(columns)
22
+ template = ->(column_name) {
23
+ return "to_tsvector('english', #{column_name}) @@ plainto_tsquery(:q)"
24
+ }
25
+
26
+ columns.map { |c| template.call(c) }.join(' OR ')
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ module SearchRedux
2
+ extend Helpers
3
+
4
+ class Searchable
5
+ attr_accessor :columns
6
+ attr_accessor :rank
7
+ attr_reader :options
8
+
9
+ def self.default_options
10
+ @default_options ||= {
11
+ :columns => %w(title content),
12
+ :rank => 'title'
13
+ }
14
+ end
15
+
16
+ def initialize(options = {})
17
+ options = self.class.default_options.merge(options)
18
+
19
+ @options = options
20
+ end
21
+
22
+ def full_text_search(query, active_record_instance)
23
+ if query.present?
24
+ @options.merge! :query => query
25
+
26
+ adapter = SearchRedux.db_adapter
27
+ strategy = SearchRedux.select_best_query_strategy(adapter, @options)
28
+
29
+ strategy.call(active_record_instance)
30
+ else
31
+ active_record_instance.scoped
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module SearchRedux
2
+ VERSION = '0.0.4' unless defined? SearchRedux::VERSION
3
+ end
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
2
+ require 'search_redux/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'search_redux'
6
+ s.version = SearchRedux::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.summary = 'Add a text_search method to your models.'
9
+ s.description = 'Simple ActiveRecord full text search.'
10
+ s.author = 'Marian Posaceanu'
11
+ s.email = 'contact@marianposaceanu.com'
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ s.require_paths = ['lib']
15
+ s.homepage = 'https://github.com/dakull/search_redux'
16
+
17
+ s.required_ruby_version = '>= 1.9.2'
18
+
19
+ s.add_dependency('activerecord', '>= 3.0.0')
20
+ s.add_dependency('activemodel', '>= 3.0.0')
21
+ s.add_dependency('activesupport', '>= 3.0.0')
22
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: search_redux
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Marian Posaceanu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activemodel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 3.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 3.0.0
55
+ description: Simple ActiveRecord full text search.
56
+ email: contact@marianposaceanu.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - .gitignore
62
+ - Gemfile
63
+ - README.md
64
+ - lib/search_redux.rb
65
+ - lib/search_redux/errors.rb
66
+ - lib/search_redux/glue.rb
67
+ - lib/search_redux/helpers.rb
68
+ - lib/search_redux/railtie.rb
69
+ - lib/search_redux/rdbms/mysql.rb
70
+ - lib/search_redux/rdbms/postgres.rb
71
+ - lib/search_redux/searchable.rb
72
+ - lib/search_redux/version.rb
73
+ - search_redux.gemspec
74
+ homepage: https://github.com/dakull/search_redux
75
+ licenses: []
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 1.9.2
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.0.0
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Add a text_search method to your models.
97
+ test_files: []