rails-simple-search 0.9.6 → 0.9.7
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/lib/rails-simple-search.rb +26 -146
- data/lib/sql_handler.rb +146 -0
- metadata +3 -1
data/lib/rails-simple-search.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'sql_handler'
|
2
|
+
|
1
3
|
module RailsSimpleSearch
|
2
4
|
DEFAULT_CONFIG = { :exact_match => [],
|
3
5
|
:paginate => true,
|
@@ -17,12 +19,20 @@ module RailsSimpleSearch
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def initialize(model_class, criteria={}, config={})
|
20
|
-
@
|
21
|
-
@table_name = @model_class.table_name
|
22
|
-
@criteria = criteria.nil? ? {} : criteria
|
23
|
-
sanitize_criteria
|
22
|
+
@criteria = sanitize_criteria(criteria)
|
24
23
|
@config = DEFAULT_CONFIG.merge(config)
|
25
|
-
|
24
|
+
|
25
|
+
@model_class = (model_class.is_a?(Symbol) || model_class.is_a?(String))? model_class.to_s.camelize.constantize : model_class
|
26
|
+
load_database_handler(@model_class)
|
27
|
+
init
|
28
|
+
end
|
29
|
+
|
30
|
+
def load_database_handler(model_class)
|
31
|
+
if model_class.ancestors.include?(ActiveRecord::Base)
|
32
|
+
RailsSimpleSearch::Base.send(:include, RailsSimpleSearch::SqlHandler)
|
33
|
+
else
|
34
|
+
raise("RailsSimpleSearch only supports ActiveRecord for now")
|
35
|
+
end
|
26
36
|
end
|
27
37
|
|
28
38
|
def count
|
@@ -37,50 +47,16 @@ module RailsSimpleSearch
|
|
37
47
|
(1..pages).to_a
|
38
48
|
end
|
39
49
|
|
40
|
-
def add_conditions(h={})
|
41
|
-
@criteria.merge!(h)
|
42
|
-
end
|
43
|
-
|
44
50
|
def order=(str)
|
45
51
|
@order = str
|
46
52
|
end
|
47
53
|
|
48
|
-
def
|
49
|
-
|
50
|
-
@conditions
|
51
|
-
end
|
52
|
-
|
53
|
-
def joins
|
54
|
-
run_criteria
|
55
|
-
@joins_str
|
56
|
-
end
|
57
|
-
|
58
|
-
def run
|
59
|
-
run_criteria
|
60
|
-
if @config[:paginate]
|
61
|
-
@count = @model_class.count({:select => "distinct #{@model_class.table_name}.#{@model_class.primary_key}",
|
62
|
-
:conditions => @conditions,
|
63
|
-
:joins => @joins_str }
|
64
|
-
)
|
65
|
-
offset = [((@page || 0) - 1) * @config[:per_page], 0].max
|
66
|
-
limit = @config[:per_page]
|
67
|
-
else
|
68
|
-
offset = @config[:offset]
|
69
|
-
limit = @config[:limit]
|
70
|
-
end
|
71
|
-
|
72
|
-
execute_hash = {:select => "distinct #{@model_class.table_name}.*",
|
73
|
-
:conditions => @conditions,
|
74
|
-
:joins => @joins_str,
|
75
|
-
:offset => offset,
|
76
|
-
:limit => limit
|
77
|
-
}
|
78
|
-
execute_hash[:order] = @order if @order
|
79
|
-
@model_class.all(execute_hash)
|
54
|
+
def add_conditions(h={})
|
55
|
+
@criteria.merge!(h)
|
80
56
|
end
|
81
|
-
|
82
|
-
private
|
83
57
|
|
58
|
+
private
|
59
|
+
|
84
60
|
def method_missing(method, *args)
|
85
61
|
method_str = method.to_s
|
86
62
|
if method_str =~ /^([^=]+)=$/
|
@@ -89,31 +65,6 @@ module RailsSimpleSearch
|
|
89
65
|
@criteria[method_str]
|
90
66
|
end
|
91
67
|
end
|
92
|
-
|
93
|
-
def make_joins
|
94
|
-
@joins_str = ''
|
95
|
-
joins = @joins.values
|
96
|
-
joins.sort! {|a,b| a[0] <=> b[0]}
|
97
|
-
joins.each do |j|
|
98
|
-
table = j[1]
|
99
|
-
constrain = j[2]
|
100
|
-
@joins_str << " inner join #{table} on #{constrain}"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def run_criteria
|
105
|
-
return unless @conditions.nil?
|
106
|
-
@criteria.each do |key, value|
|
107
|
-
if @config[:page_name].to_s == key.to_s
|
108
|
-
@page = value.to_i
|
109
|
-
@criteria[key] = @page
|
110
|
-
else
|
111
|
-
parse_attribute(key, value)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
make_joins
|
116
|
-
end
|
117
68
|
|
118
69
|
def parse_field_name(name)
|
119
70
|
result = {}
|
@@ -132,87 +83,16 @@ module RailsSimpleSearch
|
|
132
83
|
end
|
133
84
|
result
|
134
85
|
end
|
135
|
-
|
136
|
-
|
137
|
-
def insert_condition(base_class, attribute, field, value)
|
138
|
-
name_hash = parse_field_name(field)
|
139
|
-
field = name_hash[:field_name]
|
140
|
-
operator = name_hash[:operator]
|
141
|
-
|
142
|
-
table = base_class.table_name
|
143
|
-
key = "#{table}.#{field}"
|
144
|
-
|
145
|
-
@conditions ||= []
|
146
|
-
column = base_class.columns_hash[field.to_s]
|
147
|
-
|
148
|
-
if !column.text? && value.is_a?(String)
|
149
|
-
value = column.type_cast(value)
|
150
|
-
@criteria[attribute] = value
|
151
|
-
end
|
152
|
-
|
153
|
-
if value.nil?
|
154
|
-
verb = 'is'
|
155
|
-
elsif operator
|
156
|
-
verb = operator
|
157
|
-
elsif column.text? && ! @config[:exact_match].include?((@table_name == table)? field : key)
|
158
|
-
verb = 'like'
|
159
|
-
value = "%#{value}%"
|
160
|
-
else
|
161
|
-
verb = '='
|
162
|
-
end
|
163
|
-
|
164
|
-
if @conditions.size < 1
|
165
|
-
@conditions[0] = "#{key} #{verb} ?"
|
166
|
-
@conditions[1] = value
|
167
|
-
else
|
168
|
-
@conditions[0] += " and #{key} #{verb} ?"
|
169
|
-
@conditions << value
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def insert_join(base_class, asso_ref)
|
174
|
-
base_table = base_class.table_name
|
175
|
-
asso_table = asso_ref.klass.table_name
|
176
|
-
|
177
|
-
@join_count ||= 0
|
178
|
-
unless base_table == asso_table
|
179
|
-
if @joins[asso_table].nil?
|
180
|
-
@join_count += 1
|
181
|
-
if asso_ref.belongs_to?
|
182
|
-
@joins[asso_table] =[@join_count, asso_table, "#{base_table}.#{asso_ref.foreign_key} = #{asso_table}.#{asso_ref.klass.primary_key}"]
|
183
|
-
else
|
184
|
-
@joins[asso_table] = [@join_count, asso_table, "#{base_table}.#{base_class.primary_key} = #{asso_table}.#{asso_ref.foreign_key}"]
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def parse_attribute(attribute, value)
|
191
|
-
unless attribute =~ /\./
|
192
|
-
field = attribute
|
193
|
-
insert_condition(@model_class, attribute, field, value)
|
194
|
-
return
|
195
|
-
end
|
196
|
-
|
197
|
-
association_fields = attribute.split(/\./)
|
198
|
-
field = association_fields.pop
|
199
|
-
|
200
|
-
base_class = @model_class
|
201
|
-
while (association_fields.size > 0)
|
202
|
-
association_fields[0] = base_class.reflect_on_association(association_fields[0].to_sym)
|
203
|
-
insert_join(base_class, association_fields[0])
|
204
|
-
base_class = association_fields.shift.klass
|
205
|
-
end
|
206
|
-
|
207
|
-
insert_condition(base_class, attribute, field, value)
|
208
|
-
end
|
209
86
|
|
210
|
-
def sanitize_criteria
|
211
|
-
|
212
|
-
|
213
|
-
|
87
|
+
def sanitize_criteria(criteria)
|
88
|
+
criteria = criteria || {}
|
89
|
+
c = {}
|
90
|
+
criteria.each do |key, value|
|
91
|
+
unless value.blank?
|
92
|
+
c[key] = value
|
214
93
|
end
|
215
94
|
end
|
95
|
+
c
|
216
96
|
end
|
217
97
|
end
|
218
98
|
end
|
data/lib/sql_handler.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
module RailsSimpleSearch
|
2
|
+
module SqlHandler
|
3
|
+
|
4
|
+
def init
|
5
|
+
@table_name = @model_class.table_name
|
6
|
+
@joins = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def conditions
|
10
|
+
run_criteria
|
11
|
+
@conditions
|
12
|
+
end
|
13
|
+
|
14
|
+
def joins
|
15
|
+
run_criteria
|
16
|
+
@joins_str
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
run_criteria
|
21
|
+
if @config[:paginate]
|
22
|
+
@count = @model_class.count({:select => "distinct #{@model_class.table_name}.#{@model_class.primary_key}",
|
23
|
+
:conditions => @conditions,
|
24
|
+
:joins => @joins_str }
|
25
|
+
)
|
26
|
+
offset = [((@page || 0) - 1) * @config[:per_page], 0].max
|
27
|
+
limit = @config[:per_page]
|
28
|
+
else
|
29
|
+
offset = @config[:offset]
|
30
|
+
limit = @config[:limit]
|
31
|
+
end
|
32
|
+
|
33
|
+
execute_hash = {:select => "distinct #{@model_class.table_name}.*",
|
34
|
+
:conditions => @conditions,
|
35
|
+
:joins => @joins_str,
|
36
|
+
:offset => offset,
|
37
|
+
:limit => limit
|
38
|
+
}
|
39
|
+
execute_hash[:order] = @order if @order
|
40
|
+
@model_class.all(execute_hash)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def make_joins
|
46
|
+
@joins_str = ''
|
47
|
+
joins = @joins.values
|
48
|
+
joins.sort! {|a,b| a[0] <=> b[0]}
|
49
|
+
joins.each do |j|
|
50
|
+
table = j[1]
|
51
|
+
constrain = j[2]
|
52
|
+
@joins_str << " inner join #{table} on #{constrain}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def run_criteria
|
57
|
+
return unless @conditions.nil?
|
58
|
+
@criteria.each do |key, value|
|
59
|
+
if @config[:page_name].to_s == key.to_s
|
60
|
+
@page = value.to_i
|
61
|
+
@criteria[key] = @page
|
62
|
+
else
|
63
|
+
parse_attribute(key, value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
make_joins
|
68
|
+
end
|
69
|
+
|
70
|
+
def insert_condition(base_class, attribute, field, value)
|
71
|
+
name_hash = parse_field_name(field)
|
72
|
+
field = name_hash[:field_name]
|
73
|
+
operator = name_hash[:operator]
|
74
|
+
|
75
|
+
table = base_class.table_name
|
76
|
+
key = "#{table}.#{field}"
|
77
|
+
|
78
|
+
@conditions ||= []
|
79
|
+
column = base_class.columns_hash[field.to_s]
|
80
|
+
|
81
|
+
if !column.text? && value.is_a?(String)
|
82
|
+
value = column.type_cast(value)
|
83
|
+
@criteria[attribute] = value
|
84
|
+
end
|
85
|
+
|
86
|
+
if value.nil?
|
87
|
+
verb = 'is'
|
88
|
+
elsif operator
|
89
|
+
verb = operator
|
90
|
+
elsif column.text? && ! @config[:exact_match].include?((@table_name == table)? field : key)
|
91
|
+
verb = 'like'
|
92
|
+
value = "%#{value}%"
|
93
|
+
else
|
94
|
+
verb = '='
|
95
|
+
end
|
96
|
+
|
97
|
+
if @conditions.size < 1
|
98
|
+
@conditions[0] = "#{key} #{verb} ?"
|
99
|
+
@conditions[1] = value
|
100
|
+
else
|
101
|
+
@conditions[0] += " and #{key} #{verb} ?"
|
102
|
+
@conditions << value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def insert_join(base_class, asso_ref)
|
107
|
+
base_table = base_class.table_name
|
108
|
+
asso_table = asso_ref.klass.table_name
|
109
|
+
|
110
|
+
@join_count ||= 0
|
111
|
+
unless base_table == asso_table
|
112
|
+
if @joins[asso_table].nil?
|
113
|
+
@join_count += 1
|
114
|
+
if asso_ref.belongs_to?
|
115
|
+
@joins[asso_table] =[@join_count, asso_table, "#{base_table}.#{asso_ref.foreign_key} = #{asso_table}.#{asso_ref.klass.primary_key}"]
|
116
|
+
else
|
117
|
+
join_cond = "#{base_table}.#{base_class.primary_key} = #{asso_table}.#{asso_ref.foreign_key}"
|
118
|
+
join_cond = "#{asso_table}.#{asso_ref.type} = '#{base_class.name}' and #{join_cond}" if asso_ref.type
|
119
|
+
@joins[asso_table] = [@join_count, asso_table, join_cond]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def parse_attribute(attribute, value)
|
126
|
+
unless attribute =~ /\./
|
127
|
+
field = attribute
|
128
|
+
insert_condition(@model_class, attribute, field, value)
|
129
|
+
return
|
130
|
+
end
|
131
|
+
|
132
|
+
association_fields = attribute.split(/\./)
|
133
|
+
field = association_fields.pop
|
134
|
+
|
135
|
+
base_class = @model_class
|
136
|
+
while (association_fields.size > 0)
|
137
|
+
association_fields[0] = base_class.reflect_on_association(association_fields[0].to_sym)
|
138
|
+
insert_join(base_class, association_fields[0])
|
139
|
+
base_class = association_fields.shift.klass
|
140
|
+
end
|
141
|
+
|
142
|
+
insert_condition(base_class, attribute, field, value)
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-simple-search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -20,6 +20,7 @@ extra_rdoc_files: []
|
|
20
20
|
files:
|
21
21
|
- README.rdoc
|
22
22
|
- lib/rails-simple-search.rb
|
23
|
+
- lib/sql_handler.rb
|
23
24
|
homepage: http://github.com/yzhanginwa/rails-simple-search
|
24
25
|
licenses: []
|
25
26
|
post_install_message:
|
@@ -45,3 +46,4 @@ signing_key:
|
|
45
46
|
specification_version: 3
|
46
47
|
summary: A very simple and light get to quick build search function in rails
|
47
48
|
test_files: []
|
49
|
+
has_rdoc:
|