simple_search 0.0.2 → 0.1.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.rdoc +3 -1
- data/VERSION +1 -1
- data/lib/simple_search/search.rb +82 -3
- data/simple_search.gemspec +1 -1
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -57,7 +57,9 @@ Then in your view:
|
|
57
57
|
Remember, searches are idempotent so to appease the HTTP gods (and make it easy to bookmark
|
58
58
|
search results) they should be executed with GET.
|
59
59
|
|
60
|
-
That should get you started, for now.
|
60
|
+
That should get you started, for now. Read up on SimpleSearch::Search for more details, and keep in
|
61
|
+
mind that this gem was extracted from code designed to serve a specific purpose -- it has not spent
|
62
|
+
much time in the wild, so you may (will) find bugs. Please let me know about them.
|
61
63
|
|
62
64
|
== Copyright
|
63
65
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/lib/simple_search/search.rb
CHANGED
@@ -1,7 +1,78 @@
|
|
1
1
|
module SimpleSearch
|
2
|
+
# == How it works
|
3
|
+
#
|
4
|
+
# Okay, so +form_for+ is a really handy helper, right? Yes. But it expects that whatever
|
5
|
+
# object you are building a form... er, for, responds to methods that match the name of
|
6
|
+
# the first parameter. So, for instance ...
|
7
|
+
#
|
8
|
+
# f.text_field :headly_von_headdington
|
9
|
+
#
|
10
|
+
# ... expects that the object you passed to form_for responds to the +headly_von_headdington+
|
11
|
+
# method. SimpleSearch uses this to its advantage by auto-creating methods that will
|
12
|
+
# help it build a set of conditions to search on.
|
13
|
+
#
|
14
|
+
# So, when you instantiate an object of class SimpleSearch::Search, it takes a look at the
|
15
|
+
# model you want it to search, and goes about creating a bunch of methods you will find
|
16
|
+
# handy to have available in your form_for block, based on the persistent attributes of your
|
17
|
+
# model -- that is, the columns in the database table.
|
18
|
+
#
|
19
|
+
# The methods vary by the type of data to be searched. For example purposes, let's assume
|
20
|
+
# the attribute is question is named "gipe", and see what kinds of conditions SimpleSearch
|
21
|
+
# will create depending on its data type.
|
22
|
+
#
|
23
|
+
# == Strings
|
24
|
+
#
|
25
|
+
# * +gipe+ - Matches if the searched attribute contains this string. In SQL terms, this is a
|
26
|
+
# fragment that looks like <tt>gipe LIKE '%value%'</tt>
|
27
|
+
# * +gipe_starts_with+ - Matches if the attribute starts with this string. SQL:
|
28
|
+
# <tt>gipe LIKE 'value%'</tt>
|
29
|
+
# * +gipe_exact+ - Exact match. In SQL terms: <tt>gipe = 'value'</tt>
|
30
|
+
# * +gipe_not+, +gipe_not_starts_with+, +gipe_not_exact+ - Negation of the previous examples.
|
31
|
+
# Matches if the attribute doesn't contain, start with, or equal the value, respectively.
|
32
|
+
#
|
33
|
+
# == Numbers
|
34
|
+
#
|
35
|
+
# * +gipe+ - Matches if the searched attribute equals the supplied numeric value.
|
36
|
+
# * +gipe_not+ - Matches if the searched attribute doesn't equal the value.
|
37
|
+
# * +gipe_min+ - Matches if the searched attribute is greater than or equal to the value.
|
38
|
+
# * +gipe_max+ - Matches if the searched attribute is less than or equal to the value.
|
39
|
+
#
|
40
|
+
# == Dates/DateTimes
|
41
|
+
#
|
42
|
+
# * +gipe+ - Supplied value is can be a String, Date or DateTime. This method will always search on
|
43
|
+
# a range against a datetime column.
|
44
|
+
#
|
45
|
+
# If a string, it will be parsed to a Date or DateTime, depending on the type of column it is
|
46
|
+
# being compared against, and converted to a range from beginning_of_day to end_of_day in the
|
47
|
+
# current time zone, if a range is needed. If it contains the text " to " it will be treated
|
48
|
+
# as a specific date range. So "12/25/2009 to 12/31/2009" will return results from midnight on
|
49
|
+
# Christmas day to just before the ball drops at Times Square.
|
50
|
+
# * +gipe_from+, +gipe_to+ - Sets the start or endpoint of a date/time range explicitly, much
|
51
|
+
# as min/max do on numeric values. Keep in mind that range specifications are still locked to
|
52
|
+
# a day boundary, so +gipe_from+ will be beginning_of_day and +gipe_to+ will be end_of_day when
|
53
|
+
# searching against datetime columns.
|
54
|
+
#
|
55
|
+
# == Associations
|
56
|
+
#
|
57
|
+
# When you pass a list of associations to SimpleSearch::Search#new (in the +:search_associations+
|
58
|
+
# option) SimpleSearch will add methods for that association as well. These work as you might expect,
|
59
|
+
# so a <tt>:search_association => [:manufacturer, :owner, :users]</tt> on a model that +belongs_to+ a
|
60
|
+
# manufacturer and owner, and +has_many+ users will gain methods like users_first_name_starts_with and
|
61
|
+
# manufacturer_years_in_operation_min, depending on the attributes of the associated models.
|
2
62
|
class Search
|
3
63
|
attr_reader :options, :associations
|
4
|
-
|
64
|
+
|
65
|
+
# SimpleSearch always needs a +model+ parameter to know which ActiveRecord model
|
66
|
+
# it will be wrapping around and squeezing juicy attribute goodness from.
|
67
|
+
# +options+ are, oddly enough, optional. That being said, without at least a few
|
68
|
+
# search criteria specified, SimpleSearch isn't going to be doing much besides
|
69
|
+
# providing a poorly-optimized alternative to Model.all in its +search+ method.
|
70
|
+
#
|
71
|
+
# One special option is the <tt>:search_associations</tt> option. This is a list
|
72
|
+
# of one or more associations on the model (as referenced by +has_many+, +belongs_to+,
|
73
|
+
# etc) that you would like to autogenerate search methods for, as well.
|
74
|
+
#
|
75
|
+
# Wait, what? Scroll up and read "How it works" for more details.
|
5
76
|
def initialize(model, options = {})
|
6
77
|
@model = model
|
7
78
|
@associations = [*options.delete(:search_associations)].compact
|
@@ -14,6 +85,9 @@ module SimpleSearch
|
|
14
85
|
@options = options.reject{|k, v| !respond_to?(k)}.merge dates
|
15
86
|
end
|
16
87
|
|
88
|
+
# Returns the array of conditions that is passed to ActiveRecord's find or paginate
|
89
|
+
# method by this search. Useful for debugging or to do your own custom searches without
|
90
|
+
# using the +search+ or +count+ methods.
|
17
91
|
def conditions
|
18
92
|
conditions = []
|
19
93
|
parameters = []
|
@@ -35,6 +109,10 @@ module SimpleSearch
|
|
35
109
|
conditions.blank? ? [] : [conditions.join(" AND "), *parameters]
|
36
110
|
end
|
37
111
|
|
112
|
+
# Runs the current search against the database, returning all results, or paginated
|
113
|
+
# results, depending on whether a +:page+ parameter has been received (and, of course,
|
114
|
+
# whether your model responds to paginate). All other options are passed through to the
|
115
|
+
# paginate/find call.
|
38
116
|
def search(args = {})
|
39
117
|
args.merge!(
|
40
118
|
:conditions => self.conditions,
|
@@ -47,6 +125,8 @@ module SimpleSearch
|
|
47
125
|
end
|
48
126
|
end
|
49
127
|
|
128
|
+
# Get the count of records matched by the current search. All arguments are passed to
|
129
|
+
# ActiveRecord's count method.
|
50
130
|
def count(args = {})
|
51
131
|
args.merge!(
|
52
132
|
:conditions => self.conditions,
|
@@ -217,7 +297,6 @@ module SimpleSearch
|
|
217
297
|
date_str = options[meth]
|
218
298
|
return nil if date_str.blank?
|
219
299
|
from, to = date_str.split(/\s+to\s+/)
|
220
|
-
Rails.logger.info "from = #{from}, to = #{to}"
|
221
300
|
to ||= from
|
222
301
|
from = cast_to_date_or_time(model, n, from, :from).to_s(:db) rescue nil
|
223
302
|
to = cast_to_date_or_time(model, n, to, :to).to_s(:db) rescue nil
|
@@ -275,7 +354,7 @@ module SimpleSearch
|
|
275
354
|
if endpoint == :to
|
276
355
|
date_or_time = date_or_time.end_of_day.in_time_zone
|
277
356
|
else
|
278
|
-
date_or_time.beginning_of_day.in_time_zone
|
357
|
+
date_or_time = date_or_time.beginning_of_day.in_time_zone
|
279
358
|
end
|
280
359
|
end
|
281
360
|
date_or_time
|
data/simple_search.gemspec
CHANGED