searchtastic 0.5.0 → 0.6.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.
- data/Readme.md +16 -2
- data/lib/searchtastic.rb +45 -19
- data/lib/searchtastic/version.rb +1 -1
- data/searchtastic.gemspec +1 -1
- metadata +19 -3
data/Readme.md
CHANGED
@@ -21,7 +21,7 @@ Make a model searchable by providing an array of attributes to search on:
|
|
21
21
|
class User < ActiveRecord::Base
|
22
22
|
attr_accessible :name, :bio
|
23
23
|
has_one :club, class_name: Organization
|
24
|
-
searchable_by
|
24
|
+
searchable_by :name, :bio, :'club.name'
|
25
25
|
end
|
26
26
|
```
|
27
27
|
|
@@ -39,11 +39,25 @@ end
|
|
39
39
|
...
|
40
40
|
```
|
41
41
|
|
42
|
+
Note that this works for any ActiveRelation so this will work as well:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
...
|
46
|
+
def index
|
47
|
+
#@filter == "pete"
|
48
|
+
@users = @foo.users.search(@filter)
|
49
|
+
...
|
50
|
+
end
|
51
|
+
...
|
52
|
+
```
|
53
|
+
|
42
54
|
# To Do
|
43
55
|
|
44
|
-
* Search on Dates -- there's no good way to do this right now
|
45
56
|
* Search on combined fields, e.g. first_name + last_name
|
46
57
|
* Search on all accessible attributes shorthand
|
58
|
+
* Search on Date Ranges
|
59
|
+
* Search against has_many :through associations
|
60
|
+
* Search against HABTM associations
|
47
61
|
|
48
62
|
# Contributors
|
49
63
|
|
data/lib/searchtastic.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'searchtastic/version'
|
2
|
+
require 'chronic'
|
2
3
|
|
3
4
|
# This module is automatically included in all ActiveRecords
|
4
5
|
module Searchtastic
|
@@ -24,8 +25,10 @@ module Searchtastic
|
|
24
25
|
# @filtered_models = User.search(filter)
|
25
26
|
#
|
26
27
|
def search filter
|
27
|
-
if filter &&
|
28
|
-
|
28
|
+
if filter && is_searchable?
|
29
|
+
filter = [filter, Chronic.parse(filter).strftime("%Y-%m-%d")] rescue filter
|
30
|
+
handle_joins(self.fields, scoped.select("DISTINCT(`#{self.table_name}`.`id`), `#{self.table_name}`.*"))
|
31
|
+
.where(build_filter(filter, self.fields))
|
29
32
|
else
|
30
33
|
scoped
|
31
34
|
end
|
@@ -36,7 +39,7 @@ module Searchtastic
|
|
36
39
|
# User.search(@filter) if User.is_searchable?
|
37
40
|
#
|
38
41
|
def is_searchable?
|
39
|
-
self.fields.count
|
42
|
+
self.fields.count > 0
|
40
43
|
end
|
41
44
|
|
42
45
|
private
|
@@ -59,41 +62,64 @@ module Searchtastic
|
|
59
62
|
# Before adding the where clauses, we have to make sure the right tables are joined
|
60
63
|
# into the query. We use .includes() instead of .joins() so we can get an OUTER JOIN
|
61
64
|
#
|
62
|
-
def handle_joins fields
|
63
|
-
ret = scoped
|
64
|
-
fields.each do |
|
65
|
-
assoc,
|
66
|
-
ret = ret.
|
65
|
+
def handle_joins fields, select = nil
|
66
|
+
ret = select || scoped
|
67
|
+
fields.each do |qualified_field|
|
68
|
+
assoc, foreign_table, field = parse_field(qualified_field)
|
69
|
+
ret = ret.joins(join_string(assoc, foreign_table)) if assoc
|
67
70
|
end
|
68
71
|
ret
|
69
72
|
end
|
70
73
|
|
74
|
+
def join_string(assoc, foreign_table)
|
75
|
+
reflection = self.reflect_on_association(assoc.to_sym)
|
76
|
+
case reflection.macro
|
77
|
+
when :belongs_to
|
78
|
+
"LEFT OUTER JOIN `#{foreign_table}` on `#{foreign_table}`.`id` = `#{self.table_name}`.`#{assoc.singularize}_id`"
|
79
|
+
when :has_one
|
80
|
+
if reflection.options.has_key?(:through)
|
81
|
+
"LEFT OUTER JOIN `#{reflection.options[:through].pluralize}` on `#{reflection.options[:through].pluralize}`.`id` = `#{self.table_name}`.`#{reflection.options[:through]}_id` "+
|
82
|
+
"LEFT OUTER JOIN `#{foreign_table}` on `#{foreign_table}`.`id` = `#{reflection.options[:through].pluralize}`.`#{assoc.singularize}_id`"
|
83
|
+
else
|
84
|
+
"LEFT OUTER JOIN `#{foreign_table}` on `#{foreign_table}`.`id` = `#{self.table_name}`.`#{assoc.singularize}_id`"
|
85
|
+
end
|
86
|
+
when :has_many
|
87
|
+
"LEFT OUTER JOIN `#{foreign_table}` on `#{self.table_name}`.`id` = `#{foreign_table}`.`#{self.table_name.singularize}_id`"
|
88
|
+
#when :has_and_belongs_to_many
|
89
|
+
else
|
90
|
+
raise "Searching against HABTM associations is not supported"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
71
94
|
# Get table name from association name
|
72
95
|
#
|
73
96
|
# class User < ActiveRecord::Base
|
74
97
|
# belongs_to :company, class_name: Organization
|
75
|
-
# searchable_by
|
98
|
+
# searchable_by :name, :email, :'company.name'
|
76
99
|
# end
|
77
100
|
#
|
78
|
-
#
|
101
|
+
# parse_field('company.name') => ['companies', 'organizations', 'name']
|
79
102
|
#
|
80
|
-
def
|
81
|
-
if
|
82
|
-
assoc =
|
103
|
+
def parse_field(qualified_field)
|
104
|
+
if qualified_field.include? '.'
|
105
|
+
assoc, field = qualified_field.split('.')
|
83
106
|
if assoc != self.table_name
|
84
|
-
return assoc
|
107
|
+
return assoc, self.reflect_on_association(assoc.to_sym).table_name, field
|
85
108
|
end
|
86
109
|
end
|
87
110
|
|
88
|
-
return nil, self.table_name
|
111
|
+
return nil, self.table_name, field
|
89
112
|
|
90
113
|
end
|
91
114
|
|
92
115
|
# Build the filter for the .where() clause in the search method
|
93
116
|
#
|
94
|
-
def build_filter
|
95
|
-
|
96
|
-
|
117
|
+
def build_filter filters, fields
|
118
|
+
filters = [filters] unless filters.is_a? Array
|
119
|
+
where = [Array.new(filters.count, associations_to_tables(fields).map { |f| "#{f} LIKE ?" }.join(" || ")).join(" || ")]
|
120
|
+
filters.each do |filter|
|
121
|
+
fields.count.times { |n| where << "%#{filter}%" }
|
122
|
+
end
|
97
123
|
where
|
98
124
|
end
|
99
125
|
|
@@ -102,7 +128,7 @@ module Searchtastic
|
|
102
128
|
def associations_to_tables fields
|
103
129
|
fields.map do |field|
|
104
130
|
_, column = field.split('.')
|
105
|
-
"#{
|
131
|
+
"#{parse_field(field)[1]}.#{column}"
|
106
132
|
end
|
107
133
|
end
|
108
134
|
|
data/lib/searchtastic/version.rb
CHANGED
data/searchtastic.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.require_paths = ["config", "lib"]
|
18
18
|
|
19
19
|
#s.add_dependency 'activesupport', '~> 3.2'
|
20
|
-
|
20
|
+
s.add_dependency 'chronic', '~> 0.9'
|
21
21
|
|
22
22
|
s.add_development_dependency 'rake', '~> 0.9.2'
|
23
23
|
s.add_development_dependency 'rspec', '~> 2.10'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: searchtastic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: chronic
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.9'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.9'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: rake
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
128
|
version: '0'
|
113
129
|
requirements: []
|
114
130
|
rubyforge_project: searchtastic
|
115
|
-
rubygems_version: 1.8.
|
131
|
+
rubygems_version: 1.8.25
|
116
132
|
signing_key:
|
117
133
|
specification_version: 3
|
118
134
|
summary: Enables ActiveRecord Model Searching
|