rails-simple-search 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/rails-simple-search.rb +26 -146
  2. data/lib/sql_handler.rb +146 -0
  3. metadata +3 -1
@@ -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
- @model_class = (model_class.is_a?(Symbol) || model_class.is_a?(String))? model_class.to_s.camelize.constantize : model_class
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
- @joins = {}
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 conditions
49
- run_criteria
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
- @criteria.keys.each do |key|
212
- if @criteria[key].nil? || @criteria[key].blank?
213
- @criteria.delete(key)
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
@@ -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.6
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: