simple_search 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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.2
1
+ 0.1.0
@@ -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
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{simple_search}
8
- s.version = "0.0.2"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ernie Miller"]
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 1
7
8
  - 0
8
- - 2
9
- version: 0.0.2
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Ernie Miller