rails-simple-search 1.1.8 → 1.1.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25a52a9d4df55218b58ed0bfd14fd26b83d1073a9e7cf595ad43d6614e6b1bb8
4
- data.tar.gz: 304a1ac4d8784efa69d5ecaa5f6f16b891b26ab45e01a686684b40a0beac64f8
3
+ metadata.gz: 7bbf2eecbbb512c647a434d6f6d1f928652cfeafa00c8c52226a88c1ec6bc23c
4
+ data.tar.gz: 8b32419b7e0daa8baa581dfd96e04b08513960bbc1a628bda321c12493de6a08
5
5
  SHA512:
6
- metadata.gz: 4f6efabcecb4eaaddfe0380a56456c9351fdcab77406156e213238a4df1c9cb3e38ca850b91677e3ecba80e4bb245096d293759f02b622055e138f1a1d8319e4
7
- data.tar.gz: 879154bc961b75adf9374a199b8403232c5db5601326aa42f49ebfaa119a1e96eafad63b3827bf5f5bc52f74e9dc4b8747c43b09f77fe5e026c6714d0fc94e7b
6
+ metadata.gz: 9032b02b2027ee62b51680ed8310ccf7579a8eef33494f6536dfc91f414f853bff2496ee53fb875dccfd52f84e60dacea7d3221eba27d51bc5ceafc73873be63
7
+ data.tar.gz: 796835f0e60438a36e52783eac52e0fdecf9e4ff3fd9789aa53f95396cdae797d1567c9477dea2fb3e773893950bc8aea54b3ed1f7f0c54b4c164deab0c1c28f
data/README.md ADDED
@@ -0,0 +1,129 @@
1
+ ## What is rails-simple-search?
2
+ rails-simple-search is a Ruby gem. It can help Ruby on Rails developers **quickly**
3
+ implement searching/filtering function against database. If you're not looking
4
+ for a full-text searching solution, this plugin will most probably **satisfy all**
5
+ your searching requirement.
6
+
7
+ ## Why?
8
+ From time to time, I need to build pages to show a list of narrowed down records
9
+ from a database table by giving some searching criteria on some columns of the
10
+ table and/or of some referencing tables. Before I implemented this plugin, I usually
11
+ do the searching in the following way:
12
+
13
+ 1. Use <%= form_tag %> to build a form in the view
14
+ 2. Get the searching criteria from the params hash individually in the controller
15
+ and put them into instance variables to be used in view
16
+ 3. Build the SQL WHERE clause and sometimes the JOIN clause according to the
17
+ values from the form
18
+ 4. Run the find(:all, :conditions => [xxxxxxxx], :joins => "xxxxxxxx") with the
19
+ WHERE and JOIN clauses
20
+
21
+ After having used this pattern a few times, I realized I could DRY it to make
22
+ future coding of this kind of searching **much simpler**. That's where the
23
+ rails-simple-search plugin comes in.
24
+
25
+ ## Installation
26
+ 1. Put the following line into the Gemfile of your project
27
+ ```
28
+ gem 'rails-simple-search'
29
+ ```
30
+
31
+ 2. Install the gems in Gemfile
32
+ ```
33
+ $ bundle install
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ Let's suppose we have models of User, Address, Post and Comment. User model has_one
39
+ address, has_many posts, and has_many comments; Post model has_many comments; Comment
40
+ model belongs_to an author(of model User). We'd like to search for users according
41
+ to any combination of the following criteria:
42
+
43
+ * part of the user's email addrsss
44
+ * part of the first name or last name
45
+ * range of the user's birth date
46
+ * part of the city name of the user's address
47
+ * state of the user's address
48
+ * part of the name of any authors who commented the user's any posts
49
+
50
+ The following is how we implement this searching function with rails-simple-search:
51
+
52
+ 1. Include gem into Gemfile
53
+ ```
54
+ gem 'rails-simple-search'
55
+ ```
56
+
57
+ 2. Code in model (app/model/search.rb):
58
+ ```
59
+ class Search < RailsSimpleSearch::Base
60
+ end
61
+ ```
62
+
63
+ 3. Code in controller:
64
+ ```
65
+ @search = Search.new(User, params[:search])
66
+ @users = @search.run.order('email')
67
+ ```
68
+
69
+ 4. Code in views:
70
+ ```
71
+ <% form_for @search, url => "/xxxxxx", data: {turbo: false} do |f| %>
72
+
73
+ <%=f.label :email %>
74
+ <%=f.text_field :email %>
75
+
76
+ <%=f.label "first name or last name" %>
77
+ <%=f.text_field "first_name_or_last_name" %>
78
+
79
+ <%=f.label :from_birth_date %>
80
+ <%=f.text_field :birth_date_greater_than_equal_to %>
81
+
82
+ <%=f.label :to_birth_date %>
83
+ <%=f.text_field :birth_date_less_than_equal_to %>
84
+
85
+ <%=f.label :state%>
86
+ <%=f.select "address.state_id", [['AL', 1], ...] %> <!-- address is an association of model User -->
87
+
88
+ <%=f.label :city %>
89
+ <%=f.text_field "address.city" %> <!-- address is an association of model User -->
90
+
91
+ <%=f.label "name of any one who commented to my posts" %>
92
+ <%=f.text_field "posts.comments.author.first_name_or_posts.comments.author.last_name" %>
93
+ <!-- the associations could go even deeper, isn't it POWERFUL? -->
94
+
95
+ <%=f.submit %>
96
+ <% end %>
97
+
98
+ <% @users.each do |user| %>
99
+ <%= # show the attributes of user %>
100
+ <% end %>
101
+ ```
102
+
103
+ 5. Add route for the post to url "/xxxxxx" (config/route.rb)
104
+ ```
105
+ post "/xxxxxx" => "yyyyyyy#zzzzzz"
106
+ ```
107
+
108
+ ## Demo projects
109
+ There are 2 demo projects for this gem, one for [Rails 5](https://github.com/yzhanginwa/demo_app_for_rails_simple_search)
110
+ and one for [Rails 7](https://github.com/yzhanginwa/rails_simple_search_demo). You are encouraged to clone them to your local and
111
+ get a feel of the power of rails-simple-search.
112
+
113
+ ## Version history
114
+ For rails 2.x.x applications, you might want to use the version 0.9.0.
115
+
116
+ From version 0.9.1 to 0.9.7, Rails 3 is supported.
117
+
118
+ From version 0.9.8 on, this gem started to support Rails 4. Version 0.9.8 is tested under Rails 4.1.1, and version 0.9.9 fixed an issue under
119
+ Rails 4.2.
120
+
121
+ From version 1.1.0 on, we started to support the "or" relation, e.g., we can use field like "first_name_or_last_name".
122
+
123
+ From version 1.1.3 on, we started to support Rails 5.
124
+
125
+ For Rails 7, please use version 1.1.9.
126
+
127
+ ## License
128
+
129
+ Copyright &copy; 2012 [Ethan Zhang], released under the MIT license
@@ -1,9 +1,10 @@
1
1
  require_relative 'sql_handler'
2
2
 
3
3
  module RailsSimpleSearch
4
- DEFAULT_CONFIG = { :exact_match => [],
5
- :or_separator => '_or_'
6
- }
4
+ DEFAULT_CONFIG = {
5
+ exact_match: [],
6
+ or_separator: '_or_'
7
+ }
7
8
 
8
9
  module FixModelName
9
10
  def model_name
@@ -16,16 +17,16 @@ module RailsSimpleSearch
16
17
 
17
18
  def self.inherited(subclass)
18
19
  class << subclass
19
- # in rails 3, the call to "form_for" invokes the model_name
20
- def model_name
21
- ActiveModel::Name.new(self)
22
- end
20
+ # in rails 3, the call to "form_for" invokes the model_name
21
+ def model_name
22
+ ActiveModel::Name.new(self)
23
+ end
23
24
  end
24
-
25
+
25
26
  # to fix an issues in rails 4.2
26
27
  subclass.send(:include, RailsSimpleSearch::FixModelName)
27
28
  end
28
-
29
+
29
30
  def self.pre_process(model_name, &procedure)
30
31
  model_name.each { |internal_model_name| pre_process(internal_model_name, &procedure) } if model_name.is_a?(Array)
31
32
  @pre_processors ||= {}
@@ -37,7 +38,7 @@ module RailsSimpleSearch
37
38
  @pre_processors[model_name]
38
39
  end
39
40
 
40
- def initialize(model_class, criteria={}, config={})
41
+ def initialize(model_class, criteria = {}, config = {})
41
42
  @criteria = sanitize_criteria(criteria)
42
43
  @config = DEFAULT_CONFIG.merge(config)
43
44
  @config[:exact_match] = [@config[:exact_match]] unless @config[:exact_match].respond_to?(:map!)
@@ -49,21 +50,19 @@ module RailsSimpleSearch
49
50
  end
50
51
 
51
52
  def load_database_handler(model_class)
52
- if model_class.ancestors.include?(ActiveRecord::Base)
53
- RailsSimpleSearch::Base.send(:include, RailsSimpleSearch::SqlHandler)
54
- else
55
- raise("RailsSimpleSearch only supports ActiveRecord for now")
56
- end
53
+ raise("RailsSimpleSearch only supports ActiveRecord for now") unless model_class.ancestors.include?(ActiveRecord::Base)
54
+
55
+ RailsSimpleSearch::Base.send(:include, RailsSimpleSearch::SqlHandler)
57
56
  end
58
-
57
+
59
58
  def count
60
59
  @count || 0
61
60
  end
62
61
 
63
- def add_conditions(h={})
64
- @criteria.merge!(h.stringify_keys)
62
+ def add_conditions(hash = {})
63
+ @criteria.merge!(hash.stringify_keys)
65
64
  end
66
-
65
+
67
66
  def remove_criteria(key)
68
67
  key.each { |internal_key| remove_criteria(internal_key) } if key.is_a?(Array)
69
68
  @criteria.delete(key.to_s)
@@ -73,43 +72,33 @@ module RailsSimpleSearch
73
72
  @criteria[key.to_s] = value
74
73
  end
75
74
 
76
- private
75
+ private
77
76
 
78
77
  def method_missing(method, *args)
79
78
  method_str = method.to_s
80
79
  if method_str =~ /^([^=]+)=$/
81
- @criteria[$1.to_s] = args[0]
82
- else
80
+ @criteria[::Regexp.last_match(1).to_s] = args[0]
81
+ else
83
82
  @criteria[method_str]
84
83
  end
85
84
  end
86
85
 
87
86
  def parse_field_name(name)
88
- result = {}
89
87
  if name =~ /^(.*)?((_(greater|less)_than)(_equal_to)?)$/
90
- result[:field_name] = $1
91
- if $4 == 'greater'
92
- result[:operator] = ">"
93
- else
94
- result[:operator] = "<"
95
- end
96
- if $5
97
- result[:operator] << "="
98
- end
88
+ field_name = ::Regexp.last_match(1)
89
+ operator = (::Regexp.last_match(4) == 'greater' ? '>' : '<')
90
+ operator << '=' if ::Regexp.last_match(5)
99
91
  else
100
- result[:field_name] = name
92
+ field_name = name
101
93
  end
102
- result
94
+
95
+ [field_name, operator]
103
96
  end
104
-
97
+
105
98
  def sanitize_criteria(criteria)
106
- criteria = criteria || {}
99
+ criteria ||= {}
107
100
  c = {}
108
- criteria.each do |key, value|
109
- unless value.blank?
110
- c[key] = value
111
- end
112
- end
101
+ criteria.each { |key, value| c[key] = value unless value.blank? }
113
102
  c.stringify_keys
114
103
  end
115
104
  end
data/lib/sql_handler.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  module RailsSimpleSearch
2
- module SqlHandler
3
-
2
+ module SqlHandler
4
3
  def init
5
4
  @table_name = @model_class.table_name
6
5
  @joins = {}
@@ -24,23 +23,23 @@ module RailsSimpleSearch
24
23
  if column.respond_to?(:text?)
25
24
  column.text?
26
25
  elsif column.respond_to?(:type)
27
- column.type == :string
26
+ column.type == :string || column.type == :text
28
27
  else
29
- raise "encountered new version of Rails"
28
+ raise 'encountered new version of Rails'
30
29
  end
31
30
  end
32
-
31
+
33
32
  def make_joins
34
33
  @joins_str = ''
35
34
  joins = @joins.values
36
- joins.sort! {|a,b| a[0] <=> b[0]}
35
+ joins.sort! { |a, b| a[0] <=> b[0] }
37
36
  joins.each do |j|
38
37
  table = j[1]
39
38
  constrain = j[2]
40
- @joins_str << " inner join #{table} on #{constrain}"
39
+ @joins_str << " inner join #{table} on #{constrain}"
41
40
  end
42
41
  end
43
-
42
+
44
43
  def run_criteria
45
44
  @condition_group = ConditionGroup.new
46
45
  @condition_group.set_relation(:and)
@@ -52,14 +51,11 @@ module RailsSimpleSearch
52
51
  make_joins
53
52
  end
54
53
 
55
- def insert_condition(base_class, attribute, field, value)
56
- name_hash = parse_field_name(field)
57
- field = name_hash[:field_name]
58
- operator = name_hash[:operator]
59
-
54
+ def insert_condition(base_class, field, value)
55
+ field, operator = parse_field_name(field)
60
56
  table = base_class.table_name
61
57
  key = "#{table}.#{field}"
62
-
58
+
63
59
  column = base_class.columns_hash[field.to_s]
64
60
  return nil unless column
65
61
 
@@ -69,7 +65,7 @@ module RailsSimpleSearch
69
65
  verb = 'in'
70
66
  elsif operator
71
67
  verb = operator
72
- elsif text_column?(column) && ! @config[:exact_match].include?((@table_name == table)? field : key)
68
+ elsif text_column?(column) && ! @config[:exact_match].include?((@table_name == table) ? field : key)
73
69
  verb = 'like'
74
70
  value = "%#{value}%"
75
71
  else
@@ -78,29 +74,28 @@ module RailsSimpleSearch
78
74
 
79
75
  ConditionGroup.new(ConditionItem.new(key, verb, value))
80
76
  end
81
-
77
+
82
78
  def insert_join(base_class, asso_ref)
83
79
  base_table = base_class.table_name
84
80
  asso_table = asso_ref.klass.table_name
85
-
81
+
86
82
  @join_count ||= 0
87
- unless base_table == asso_table
88
- if @joins[asso_table].nil?
89
- @join_count += 1
90
- if asso_ref.belongs_to?
91
- @joins[asso_table] =[@join_count, asso_table, "#{base_table}.#{asso_ref.foreign_key} = #{asso_table}.#{asso_ref.klass.primary_key}"]
92
- else
93
- join_cond = "#{base_table}.#{base_class.primary_key} = #{asso_table}.#{asso_ref.foreign_key}"
94
- join_cond = "#{asso_table}.#{asso_ref.type} = '#{base_class.name}' and #{join_cond}" if asso_ref.type
95
- @joins[asso_table] = [@join_count, asso_table, join_cond]
96
- end
97
- end
83
+ return if base_table == asso_table
84
+ return unless @joins[asso_table].nil?
85
+
86
+ @join_count += 1
87
+ if asso_ref.belongs_to?
88
+ @joins[asso_table] =[@join_count, asso_table, "#{base_table}.#{asso_ref.foreign_key} = #{asso_table}.#{asso_ref.klass.primary_key}"]
89
+ else
90
+ join_cond = "#{base_table}.#{base_class.primary_key} = #{asso_table}.#{asso_ref.foreign_key}"
91
+ join_cond = "#{asso_table}.#{asso_ref.type} = '#{base_class.name}' and #{join_cond}" if asso_ref.type
92
+ @joins[asso_table] = [@join_count, asso_table, join_cond]
98
93
  end
99
94
  end
100
-
95
+
101
96
  def parse_attribute(attribute, value)
102
97
  attributes = attribute.split(@config[:or_separator])
103
- if(attributes.size > 1)
98
+ if attributes.size > 1
104
99
  cg = ConditionGroup.new
105
100
  cg.set_relation(:or)
106
101
  attributes.each do |a|
@@ -110,25 +105,22 @@ module RailsSimpleSearch
110
105
  end
111
106
 
112
107
  unless attribute =~ /\./
113
- field = attribute
114
- condition = insert_condition(@model_class, attribute, field, value)
108
+ condition = insert_condition(@model_class, attribute, value)
115
109
  return condition
116
- end
110
+ end
117
111
 
118
112
  association_fields = attribute.split(/\./)
119
113
  field = association_fields.pop
120
114
 
121
115
  base_class = @model_class
122
- while (association_fields.size > 0)
116
+ until association_fields.empty?
123
117
  association_fields[0] = base_class.reflect_on_association(association_fields[0].to_sym)
124
118
  insert_join(base_class, association_fields[0])
125
119
  base_class = association_fields.shift.klass
126
120
  end
127
121
 
128
- condition = insert_condition(base_class, attribute, field, value)
129
- return condition
122
+ insert_condition(base_class, field, value)
130
123
  end
131
-
132
124
  end
133
125
 
134
126
  class ConditionItem
@@ -142,7 +134,7 @@ module RailsSimpleSearch
142
134
  end
143
135
 
144
136
  class ConditionGroup
145
- def initialize(item=nil)
137
+ def initialize(item = nil)
146
138
  if item
147
139
  @condition_item = item
148
140
  else
@@ -150,17 +142,15 @@ module RailsSimpleSearch
150
142
  end
151
143
  end
152
144
 
153
- def add(cg)
154
- if leaf?
155
- raise "It's not allowed to add child into leaf node"
156
- end
157
- @children << cg if cg
145
+ def add(condition_group)
146
+ raise "It's not allowed to add child into leaf node" if leaf?
147
+
148
+ @children << condition_group if condition_group
158
149
  end
159
150
 
160
151
  def set_relation(and_or)
161
- if leaf?
162
- raise "It's not needed to set relation for leaf node"
163
- end
152
+ raise "It's not needed to set relation for leaf node" if leaf?
153
+
164
154
  @relation = and_or
165
155
  end
166
156
 
@@ -169,7 +159,7 @@ module RailsSimpleSearch
169
159
  end
170
160
 
171
161
  def empty?
172
- (@children && @children.empty?) ? true : false
162
+ @children && @children.empty? ? true : false
173
163
  end
174
164
 
175
165
  def to_ar_condition
@@ -177,17 +167,14 @@ module RailsSimpleSearch
177
167
  if leaf?
178
168
  i = @condition_item
179
169
  condition << "#{i.field} #{i.verb}"
180
- if i.verb == 'in'
181
- condition[0] << " (?)"
182
- else
183
- condition[0] << " ?"
184
- end
170
+ condition[0] << (i.verb == 'in' ? ' (?)' : ' ?')
185
171
  condition << i.value
186
172
  else
187
- tmp = @children.map(&:to_ar_condition)
188
- condition << "(" + tmp.map(&:first).join(" #{@relation} ") + ")"
189
- tmp.each do |t|
190
- (1..(t.length-1)).each do |index|
173
+ tmp_conditions = @children.map(&:to_ar_condition)
174
+ tmp_condition_str = tmp_conditions.map(&:first).join(" #{@relation} ")
175
+ condition << "(#{tmp_condition_str})"
176
+ tmp_conditions.each do |t|
177
+ (1..(t.length - 1)).each do |index|
191
178
  condition << t[index]
192
179
  end
193
180
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-simple-search
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.8
4
+ version: 1.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yi Zhang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-24 00:00:00.000000000 Z
11
+ date: 2023-12-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: rails-simple-search is a light and easy to use gem. It could help developers
14
14
  quickly build a search page.
@@ -17,7 +17,7 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
- - README.rdoc
20
+ - README.md
21
21
  - lib/rails-simple-search.rb
22
22
  - lib/sql_handler.rb
23
23
  homepage: http://github.com/yzhanginwa/rails-simple-search
data/README.rdoc DELETED
@@ -1,95 +0,0 @@
1
- =rails-simple-search
2
-
3
- rails-simple-search is a Ruby gem. It helps you quickly implement searching/filtering function for your web site. This plugin has paginating feature built in. If you're not looking for a full-text searching solution, this plugin will most probably satisfy all your searching requirement.
4
-
5
- From time to time, I need to build pages to show a list of narrowed down records from a database table by giving some searching criteria on some columns of the table and/or of some referencing tables. Before I implemented this plugin, I usually do the searching in the following way:
6
-
7
- 1. Use <%= form_tag %> to build a form in the view
8
- 2. Get the searching criteria from the params hash individually in the controller and put them into instance variable to be used in view
9
- 3. Build the SQL WHERE clause and sometimes the JOIN clause according to the values from the form
10
- 4. Run the find(:all, :conditions => [xxxxxx], :joins => "yyyyyy") with the WHERE and JOIN clauses
11
-
12
- After having used this pattern a few times, I realized I could DRY it to make future coding of this kind of searching much simpler. That's where the rails-simple-search plugin comes in.
13
-
14
- Now implementing the searching/filter page is a lot easier for me. You're see how easy it is by taking a look at the following example. I may give more examples in the future when I have some spare time.
15
-
16
-
17
- == Example
18
-
19
- Let's suppose we have models of User, Address, Post and Comment. User model has_one address and has_many posts; Post model has_many comments. We'd like to search for users according to any combination of the following criteria:
20
-
21
- * part of the user's email addrsss
22
- * range of the user's birth date
23
- * state of the user's address
24
- * part of the name of any authors who commented the user's any posts
25
-
26
- The following is how we implement this searching function with rails-simple-search:
27
-
28
- 1. Include gem into Gemfile
29
-
30
- gem 'rails-simple-search'
31
-
32
- 2. Code in model (app/model/search.rb):
33
-
34
- class Search < RailsSimpleSearch::Base
35
- end
36
-
37
- 3. Code in controller:
38
-
39
- @search = Search.new(User, params[:search])
40
- @users = @search.run.paginate(page: params[:page], per_page: 20).order('email')
41
-
42
- 4. Code in views:
43
-
44
- <% form_for @search, url => "/xxxxxx", data: {turbo: false} do |f| %>
45
-
46
- <%=f.label :email %>
47
- <%=f.text_field :email %>
48
-
49
- <%=f.label "first name or last name" %>
50
- <%=f.text_field "first_name_or_last_name" %>
51
-
52
- <%=f.label :from_birth_date %>
53
- <%=f.text_field :birth_date_greater_than_equal_to %>
54
-
55
- <%=f.label :to_age %>
56
- <%=f.text_field :birth_date_less_than_equal_to %>
57
-
58
- <%=f.label :state%>
59
- <%=f.select "address.state_id", [['AL', 1], ...] %> <!-- address is an association of model User -->
60
-
61
- <%=f.label :post%>
62
- <%=f.text_field "posts.comments.author" %> <!-- the associations could go even deeper, isn't it POWERFUL? -->
63
-
64
- <%=f.submit %>
65
- <% end %>
66
-
67
- <% @users.each do |user| %>
68
- <%= # show the attributes of user %>
69
- <% end %>
70
-
71
- 5. Add route for the post to url "/xxxxxx" (config/route.rb)
72
- post "/xxxxxx" => "yyyyyyy#zzzzzz"
73
-
74
- == Note
75
-
76
- For rails 2.x.x applications, you might want to use the version 0.9.0.
77
-
78
- From version 0.9.1 to 0.9.7, Rails 3 is supported.
79
-
80
- From version 0.9.8 on, this gem started to support Rails 4. Version 0.9.8 is tested under Rails 4.1.1, and version 0.9.9 fixed an issue under
81
- Rails 4.2.
82
-
83
- From version 1.1.0 on, we started to support the "or" relation, e.g., we can use field like "first_name_or_last_name".
84
-
85
- From version 1.1.3 on, we started to support Rails 5.
86
-
87
- For Rails 7, please use version 1.1.7.
88
-
89
- There is a real demo application which you can download and run immediately: https://github.com/yzhanginwa/demo_app_for_rails_simple_search
90
-
91
- For Rails 7 demo, please see here: https://github.com/yzhanginwa/rails_simple_search_demo
92
-
93
- == License
94
-
95
- Copyright (c) 2012 [Yi Zhang], released under the MIT license