meta_search_hub 1.1.3

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 821034765c75b62d54b080df44649b5a77a217c6bafd2e5340d8916b9f28ab90
4
+ data.tar.gz: 5fe057116b6ee5822044ee81564ea3149613a5ab86118c6c602816eb67abe18c
5
+ SHA512:
6
+ metadata.gz: 605de62eb9f30f3a8050529fd23ddc587f128a36b1ca74c4f6f410ba1a413eb8043e025bc86c37df9715b738f6387e323690c7008feebb7cc7d07079727960cd
7
+ data.tar.gz: d6d66fd012cd79c0fae03d768d5def43d18a7f7f0b885dbbb202561b8664bbecbbdf505ef4ac0d439fea04ad80fab5b106cb1d034406dfdf335592fff4e638f1
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitmodules ADDED
@@ -0,0 +1,6 @@
1
+ [submodule "vendor/arel"]
2
+ path = vendor/arel
3
+ url = git://github.com/rails/arel.git
4
+ [submodule "vendor/rails"]
5
+ path = vendor/rails
6
+ url = git://github.com/rails/rails.git
data/CHANGELOG ADDED
@@ -0,0 +1,109 @@
1
+ Changes since 1.0.4 (2011-04-08):
2
+ * Add :join_type option to Builder to allow for using InnerJoin if desired
3
+ (Stephen Pike)
4
+ * Fix a memory leak in development mode (Bonias)
5
+
6
+ Changes since 1.0.3 (2011-03-14):
7
+ * Be sure not to override form_for options if super returns a non-true value,
8
+ fixes a compatibility issue when using client_side_validation
9
+
10
+ Changes since 1.0.1 (2011-01-18):
11
+ * Include all non-boolean types in is_present and is_blank, to match
12
+ documentation
13
+ * Avoid setting alias to collection_check_boxes and check_boxes against
14
+ the base. Fixes issues with SimpleForm compatibility.
15
+ * Delegate page method to relation, for Kaminari support.
16
+ * Don't check for existence of attributes if the table doesn't exist yet.
17
+
18
+ Changes since 1.0.0 (2011-01-17):
19
+ * Update polymorphic join support to play nicely with MetaWhere
20
+
21
+ Changes since 0.9.11 (2011-01-06):
22
+ * Doc updates only.
23
+
24
+ Changes since 0.9.10 (2010-11-18):
25
+ * Skip attempts to sort if someone passes an empty string to meta_sort
26
+ * Allow conditions on search_methods, (attr|assoc)_(un)?searchable using :if.
27
+ Option should be an object that responds to call and accepts the
28
+ MetaSearch::Builder instance as a parameter. Unused options passed to the
29
+ Model.search method will be available for your conditions to act on.
30
+ * Access attribute setters if a param is supplied - @search.attr_name(val)
31
+ behaves like @search.attr_name = val
32
+
33
+ Changes since 0.9.9 (2010-11-15):
34
+ * Fix bug introduced by new polymorphic belongs_to association code in
35
+ honoring :url param to form_for
36
+ * Support localization of predicate text in labels
37
+ * Fix bug when accessing localizations for named search methods
38
+
39
+ Changes since 0.9.8 (2010-10-20):
40
+ * ARel 2.x and Rails 3.0.2 compatability
41
+ * sort_link uses search_key from builder. Search_key defaults to "search"
42
+ * sort_link will localize attribute names.
43
+ * You can now create two scopes on your model named sort_by_something_asc
44
+ and sort_by_something_desc, and sort_link will then allow you to specify
45
+ :something as a parameter, then use your scope to perform custom sorting.
46
+
47
+ Changes since 0.9.7 (2010-10-12):
48
+ * Play nicely regardless of MetaWhere/MetaSearch load order.
49
+ * Big fix - stop altering the supplied hash in Builder#build.
50
+
51
+ Changes since 0.9.6 (2010-09-29):
52
+ * Support _or_-separated conditions. I'm not crazy about 'em, but it's
53
+ an oft-requested feature.
54
+ * Support search on polymorphic belongs_to associations. Uses the same
55
+ syntax users of Searchlogic are familiar with, association_classname_type.
56
+ For example: commentable_article_type_contains
57
+ * Join using left outer joins instead of inner joins. This lets you do
58
+ some interesting things like search for all articles with no comments via
59
+ comments_id_is_null.
60
+ * No longer define method on the metaclass - stick to standard method_missing
61
+ for both correctness and performance.
62
+
63
+ Changes since 0.9.5 (2010-09-28):
64
+ * Fix issue with formatters supplied as strings
65
+
66
+ Changes since 0.9.4 (2010-09-18):
67
+ * Rename check_boxes and collection_check_boxes to checks and
68
+ collection_checks. Alias to the old names if not already taken. This
69
+ is to avoid conflicts with SimpleForm.
70
+
71
+ Changes since 0.9.3 (2010-09-08):
72
+ * Minor documentation fixes.
73
+ * Add sort_link helper to FormBuilder, to spare keystrokes if sort_links
74
+ are being added inside the context of the form_for of the search.
75
+
76
+ Changes since 0.9.2 (2010-08-25):
77
+ * Update dependencies for Rails 3 final.
78
+
79
+ Changes since 0.9.1 (2010-08-24):
80
+ * Fix time column casts to account for current time zone.
81
+
82
+ Changes since 0.9.0 (2010-08-24):
83
+ * Fix the missing "2" in the Rails 3.0.0.rc2 dependency. Sorry!
84
+
85
+ Changes since 0.5.4 (2010-07-28):
86
+ * Fix equals Where against boolean columns
87
+ * Add is_true/is_false for booleans, is_present/is_blank for other types
88
+ * Add is_null/is_not_null for all types
89
+ * Remove deprecated metasearch_exclude_attr and friends
90
+ * delegate #size and #length to relation
91
+
92
+ Changes since 0.5.3 (2010-07-26):
93
+ * Add is_true/is_false for boolean columns
94
+ * Add is_present and is_blank for string/numeric columns
95
+ * Add is_null and is_not_null for all columns
96
+ * Fix behavior of equals when used with boolean columns.
97
+
98
+ Changes since 0.5.2 (2010-07-22):
99
+ * Handle nested/namespaced form_for better. Formerly, you could use
100
+ "form_for @search" in a view, but not "form_for [:admin, @search]"
101
+
102
+ Changes since 0.5.1 (2010-07-20):
103
+ * Fix fallback for failed cast via to_time or to_date
104
+ * add :cast option for custom Wheres, allowing a where to override
105
+ the default cast of the incoming parameters.
106
+
107
+ Changes since 0.5.0 (2010-06-08):
108
+ * Fix searching against relations derived from a has_many :through
109
+ association
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source :rubygems
2
+
3
+ # Don't do a "gemspec" here. Seriously. It jacks up Jeweler.
4
+
5
+ gem "activerecord", "~> 3.1"
6
+ gem "activesupport", "~> 3.1"
7
+ gem "polyamorous", "~> 0.5.0"
8
+ gem "actionpack", "~> 3.1"
9
+
10
+ group :development do
11
+ gem "shoulda", "~> 2.11"
12
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Ernie Miller
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,438 @@
1
+ = MetaSearch
2
+
3
+ MetaSearch is extensible searching for your form_for enjoyment. It “wraps” one of your ActiveRecord models, providing methods that allow you to build up search conditions against that model, and has a few extra form helpers to simplify sorting and supplying multiple parameters to your condition methods as well.
4
+
5
+ == NOTE
6
+
7
+ The successor to MetaSearch is {Ransack}[http://github.com/ernie/ransack]. It's got features
8
+ that MetaSearch doesn't, along with some API changes. I haven't had the time to dedicate to
9
+ making it bulletproof yet, so I'm releasing a 1.1.x branch of MetaSearch to help with migrations
10
+ to Rails 3.1.
11
+
12
+ This is intended to be a stopgap measure.
13
+
14
+ t's important to note that the long-term migration path for your apps should be toward
15
+ Ransack, which is written in a more sane manner that will make supporting new versions
16
+ of Rails much easier going forward.
17
+
18
+ == Getting Started
19
+
20
+ In your Gemfile:
21
+
22
+ gem "meta_search" # Last officially released gem
23
+ # gem "meta_search", :git => "git://github.com/ernie/meta_search.git" # Track git repo
24
+
25
+ or, to install as a plugin:
26
+
27
+ rails plugin install git://github.com/ernie/meta_search.git
28
+
29
+ In your controller:
30
+
31
+ def index
32
+ @search = Article.search(params[:search])
33
+ @articles = @search.all # load all matching records
34
+ # @articles = @search.relation # Retrieve the relation, to lazy-load in view
35
+ # @articles = @search.paginate(:page => params[:page]) # Who doesn't love will_paginate?
36
+ end
37
+
38
+ In your view:
39
+
40
+ <%= form_for @search, :url => articles_path, :html => {:method => :get} do |f| %>
41
+ <%= f.label :title_contains %>
42
+ <%= f.text_field :title_contains %><br />
43
+ <%= f.label :comments_created_at_greater_than, 'With comments after' %>
44
+ <%= f.datetime_select :comments_created_at_greater_than, :include_blank => true %><br />
45
+ <!-- etc... -->
46
+ <%= f.submit %>
47
+ <% end %>
48
+
49
+ Options for the search method are documented at MetaSearch::Searches::ActiveRecord.
50
+
51
+ == "Wheres", and what they're good for
52
+
53
+ Wheres are how MetaSearch does its magic. Wheres have a name (and possible aliases) which are
54
+ appended to your model and association attributes. When you instantiate a MetaSearch::Builder
55
+ against a model (manually or by calling your model's +search+ method) the builder responds to
56
+ methods named for your model's attributes and associations, suffixed by the name of the Where.
57
+
58
+ These are the default Wheres, broken down by the types of ActiveRecord columns they can search
59
+ against:
60
+
61
+ === All data types
62
+
63
+ * _equals_ (alias: _eq_) - Just as it sounds.
64
+ * _does_not_equal_ (aliases: _ne_, _noteq_) - The opposite of equals, oddly enough.
65
+ * _in_ - Takes an array, matches on equality with any of the items in the array.
66
+ * _not_in_ (aliases: _ni_, _notin_) - Like above, but negated.
67
+ * _is_null_ - The column has an SQL NULL value.
68
+ * _is_not_null_ - The column contains anything but NULL.
69
+
70
+ === Strings
71
+
72
+ * _contains_ (aliases: _like_, _matches_) - Substring match.
73
+ * _does_not_contain_ (aliases: _nlike_, _nmatches_) - Negative substring match.
74
+ * _starts_with_ (alias: _sw_) - Match strings beginning with the entered term.
75
+ * _does_not_start_with_ (alias: _dnsw_) - The opposite of above.
76
+ * _ends_with_ (alias: _ew_) - Match strings ending with the entered term.
77
+ * _does_not_end_with_ (alias: _dnew_) - Negative of above.
78
+
79
+ === Numbers, dates, and times
80
+
81
+ * _greater_than_ (alias: _gt_) - Greater than.
82
+ * _greater_than_or_equal_to_ (aliases: _gte_, _gteq_) - Greater than or equal to.
83
+ * _less_than_ (alias: _lt_) - Less than.
84
+ * _less_than_or_equal_to_ (aliases: _lte_, _lteq_) - Less than or equal to.
85
+
86
+ === Booleans
87
+
88
+ * _is_true_ - Is true. Useful for a checkbox like "only show admin users".
89
+ * _is_false_ - The complement of _is_true_.
90
+
91
+ === Non-boolean data types
92
+
93
+ * _is_present_ - As with _is_true_, useful with a checkbox. Not NULL or the empty string.
94
+ * _is_blank_ - Returns records with a value of NULL or the empty string in the column.
95
+
96
+ So, given a model like this...
97
+
98
+ class Article < ActiveRecord::Base
99
+ belongs_to :author
100
+ has_many :comments
101
+ has_many :moderations, :through => :comments
102
+ end
103
+
104
+ ...you might end up with attributes like <tt>title_contains</tt>,
105
+ <tt>comments_title_starts_with</tt>, <tt>moderations_value_less_than</tt>,
106
+ <tt>author_name_equals</tt>, and so on.
107
+
108
+ Additionally, all of the above predicate types also have an _any and _all version, which
109
+ expects an array of the corresponding parameter type, and requires any or all of the
110
+ parameters to be a match, respectively. So:
111
+
112
+ Article.search :author_name_starts_with_any => ['Jim', 'Bob', 'Fred']
113
+
114
+ will match articles authored by Jimmy, Bobby, or Freddy, but not Winifred.
115
+
116
+ == Advanced usage
117
+
118
+ === Narrowing the scope of a search
119
+
120
+ While the most common use case is to simply call Model.search(params[:search]), there
121
+ may be times where you want to scope your search more tightly. For instance, only allowing
122
+ users to search their own projects (assuming a current_user method returning the current user):
123
+
124
+ @search = current_user.projects.search(params[:search])
125
+
126
+ Or, you can build up any relation you like and call the search method on that object:
127
+
128
+ @projects_with_awesome_users_search =
129
+ Project.joins(:user).where(:users => {:awesome => true}).search(params[:search])
130
+
131
+ === ORed conditions
132
+
133
+ If you'd like to match on one of several possible columns, you can do this:
134
+
135
+ <%= f.text_field :title_or_description_contains %>
136
+ <%= f.text_field :title_or_author_name_starts_with %>
137
+
138
+ Caveats:
139
+
140
+ * Only one match type is supported. You <b>can't</b> do
141
+ <tt>title_matches_or_description_starts_with</tt> for instance.
142
+ * If you're matching across associations, remember that the associated table will be
143
+ INNER JOINed, therefore limiting results to those that at least have a corresponding
144
+ record in the associated table.
145
+
146
+ === Compound conditions (any/all)
147
+
148
+ All Where types automatically get an "any" and "all" variant. This has the same name and
149
+ aliases as the original, but is suffixed with _any and _all, for an "OR" or "AND" search,
150
+ respectively. So, if you want to provide the user with 5 different search boxes to enter
151
+ possible article titles:
152
+
153
+ <%= f.multiparameter_field :title_contains_any,
154
+ *5.times.inject([]) {|a, b| a << {:field_type => :text_field}} +
155
+ [:size => 10] %>
156
+
157
+ === Multi-level associations
158
+
159
+ MetaSearch will allow you to traverse your associations in one form, generating the
160
+ necessary joins along the way. If you have the following models...
161
+
162
+ class Company < ActiveRecord::Base
163
+ has_many :developers
164
+ end
165
+
166
+ class Developer < ActiveRecord::Base
167
+ belongs_to :company
168
+ has_many :notes
169
+ end
170
+
171
+ ...you can do this in your form to search your companies by developers with certain notes:
172
+
173
+ <%= f.text_field :developers_notes_note_contains %>
174
+
175
+ You can travel forward and back through the associations, so this would also work (though
176
+ be entirely pointless in this case):
177
+
178
+ <%= f.text_field :developers_notes_developer_company_name_contains %>
179
+
180
+ However, to prevent abuse, this is limited to associations of a total "depth" of 5 levels.
181
+ This means that while starting from a Company model, as above, you could do
182
+ Company -> :developers -> :notes -> :developer -> :company, which has gotten you right
183
+ back where you started, but "travels" through 5 models total.
184
+
185
+ In the case of polymorphic belongs_to associations, things work a bit differently. Let's say
186
+ you have the following models:
187
+
188
+ class Article < ActiveRecord::Base
189
+ has_many :comments, :as => :commentable
190
+ end
191
+
192
+ class Post < ActiveRecord::Base
193
+ has_many :comments, :as => :commentable
194
+ end
195
+
196
+ class Comment < ActiveRecord::Base
197
+ belongs_to :commentable, :polymorphic => true
198
+ validates_presence_of :body
199
+ end
200
+
201
+ Your first instinct might be to set up a text field for :commentable_body_contains, but
202
+ you can't do this. MetaSearch would have no way to know which class lies on the other side
203
+ of the polymorphic association, so it wouldn't be able to join the correct tables.
204
+
205
+ Instead, you'll follow a convention Searchlogic users are already familiar with, using the
206
+ name of the polymorphic association, then the underscored class name (AwesomeClass becomes
207
+ awesome_class), then the delimiter "type", to tell MetaSearch anything that follows is an
208
+ attribute name. For example:
209
+
210
+ <%= f.text_field :commentable_article_type_body_contains %>
211
+
212
+ If you'd like to match on multiple types of polymorphic associations, you can join them
213
+ with \_or_, just like any other conditions:
214
+
215
+ <%= f.text_field :commentable_article_type_body_or_commentable_post_type_body_contains %>
216
+
217
+ It's not pretty, but it works. Alternately, consider creating a custom search method as
218
+ described below to save yourself some typing if you're creating a lot of these types of
219
+ search fields.
220
+
221
+ === Adding a new Where
222
+
223
+ If none of the built-in search criteria work for you, you can add new Wheres. To do so,
224
+ create an initializer (<tt>/config/initializers/meta_search.rb</tt>, for instance) and add lines
225
+ like:
226
+
227
+ MetaSearch::Where.add :between, :btw,
228
+ :predicate => :in,
229
+ :types => [:integer, :float, :decimal, :date, :datetime, :timestamp, :time],
230
+ :formatter => Proc.new {|param| Range.new(param.first, param.last)},
231
+ :validator => Proc.new {|param|
232
+ param.is_a?(Array) && !(param[0].blank? || param[1].blank?)
233
+ }
234
+
235
+ See MetaSearch::Where for info on the supported options.
236
+
237
+ === Accessing custom search methods (and named scopes!)
238
+
239
+ MetaSearch can be given access to any class method on your model to extend its search capabilities.
240
+ The only rule is that the method must return an ActiveRecord::Relation so that MetaSearch can
241
+ continue to extend the search with other attributes. Conveniently, scopes (formerly "named scopes")
242
+ do this already.
243
+
244
+ Consider the following model:
245
+
246
+ class Company < ActiveRecord::Base
247
+ has_many :slackers, :class_name => "Developer", :conditions => {:slacker => true}
248
+ scope :backwards_name, lambda {|name| where(:name => name.reverse)}
249
+ scope :with_slackers_by_name_and_salary_range,
250
+ lambda {|name, low, high|
251
+ joins(:slackers).where(:developers => {:name => name, :salary => low..high})
252
+ }
253
+ end
254
+
255
+ To allow MetaSearch access to a model method, including a named scope, just use
256
+ <tt>search_methods</tt> in the model:
257
+
258
+ search_methods :backwards_name
259
+
260
+ This will allow you to add a text field named :backwards_name to your search form, and
261
+ it will behave as you might expect.
262
+
263
+ In the case of the second scope, we have multiple parameters to pass in, of different
264
+ types. We can pass the following to <tt>search_methods</tt>:
265
+
266
+ search_methods :with_slackers_by_name_and_salary_range,
267
+ :splat_param => true, :type => [:string, :integer, :integer]
268
+
269
+ MetaSearch needs us to tell it that we don't want to keep the array supplied to it as-is, but
270
+ "splat" it when passing it to the model method. Regarding <tt>:types</tt>: In this case,
271
+ ActiveRecord would have been smart enough to handle the typecasting for us, but I wanted to
272
+ demonstrate how we can tell MetaSearch that a given parameter is of a specific database "column type." This is just a hint MetaSearch uses in the same way it does when casting "Where" params based
273
+ on the DB column being searched. It's also important so that things like dates get handled
274
+ properly by FormBuilder.
275
+
276
+ === multiparameter_field
277
+
278
+ The example Where above adds support for a "between" search, which requires an array with
279
+ two parameters. These can be passed using Rails multiparameter attributes. To make life easier,
280
+ MetaSearch adds a helper for this:
281
+
282
+ <%= f.multiparameter_field :moderations_value_between,
283
+ {:field_type => :text_field}, {:field_type => :text_field}, :size => 5 %>
284
+
285
+ <tt>multiparameter_field</tt> works pretty much like the other FormBuilder helpers, but it
286
+ lets you sandwich a list of fields, each in hash format, between the attribute and the usual
287
+ options hash. See MetaSearch::Helpers::FormBuilder for more info.
288
+
289
+ === checks and collection_checks
290
+
291
+ If you need to get an array into your where, and you don't care about parameter order,
292
+ you might choose to use a select or collection_select with multiple selection enabled,
293
+ but everyone hates multiple selection boxes. MetaSearch adds a couple of additional
294
+ helpers, +checks+ and +collection_checks+ to handle multiple selections in a
295
+ more visually appealing manner. They can be called with or without a block. Without a
296
+ block, you get an array of MetaSearch::Check objects to do with as you please.
297
+
298
+ With a block, each check is yielded to your template, like so:
299
+
300
+ <h4>How many heads?</h4>
301
+ <ul>
302
+ <% f.checks :number_of_heads_in,
303
+ [['One', 1], ['Two', 2], ['Three', 3]], :class => 'checkboxy' do |check| %>
304
+ <li>
305
+ <%= check.box %>
306
+ <%= check.label %>
307
+ </li>
308
+ <% end %>
309
+ </ul>
310
+
311
+ Again, full documentation is in MetaSearch::Helpers::FormBuilder.
312
+
313
+ === Sorting columns
314
+
315
+ If you'd like to sort by a specific column in your results (the attributes of the base model)
316
+ or an association column then supply the <tt>meta_sort</tt> parameter in your form.
317
+ The parameter takes the form <tt>column.direction</tt> where +column+ is the column name or
318
+ underscore-separated association_column combination, and +direction+ is one of "asc" or "desc"
319
+ for ascending or descending, respectively.
320
+
321
+ Normally, you won't supply this parameter yourself, but instead will use the helper method
322
+ <tt>sort_link</tt> in your views, like so:
323
+
324
+ <%= sort_link @search, :title %>
325
+
326
+ Or, if in the context of a form_for against a MetaSearch::Builder:
327
+
328
+ <%= f.sort_link :title %>
329
+
330
+ The <tt>@search</tt> object is the instance of MetaSearch::Builder you got back earlier from
331
+ your controller. The other required parameter is the attribute name itself. Optionally,
332
+ you can provide a string as a 3rd parameter to override the default link name, and then
333
+ additional hashed for the +options+ and +html_options+ hashes for link_to.
334
+
335
+ By default, the link that is created will sort by the given column in ascending order when first clicked. If you'd like to reverse this (so the first click sorts the results in descending order), you can pass +:default_order => :desc+ in the options hash, like so:
336
+
337
+ <%= sort_link @search, :ratings, "Highest Rated", :default_order => :desc %>
338
+
339
+ You can sort by more than one column as well, by creating a link like:
340
+
341
+ <%= sort_link :name_and_salary %>
342
+
343
+ If you'd like to do a custom sort, you can do so by setting up two scopes in your model:
344
+
345
+ scope :sort_by_custom_name_asc, order('custom_name ASC')
346
+ scope :sort_by_custom_name_desc, order('custom_name DESC')
347
+
348
+ You can then do <tt>sort_link @search, :custom_name</tt> and it will work as you expect.
349
+
350
+ All <tt>sort_link</tt>-generated links will have the CSS class sort_link, as well as a
351
+ directional class (ascending or descending) if the link is for a currently sorted column,
352
+ for your styling enjoyment.
353
+
354
+ This feature should hopefully help out those of you migrating from Searchlogic, and a thanks
355
+ goes out to Ben Johnson for the HTML entities used for the up and down arrows, which provide
356
+ a nice default look.
357
+
358
+ === Including/excluding attributes and associations
359
+
360
+ If you'd like to allow only certain associations or attributes to be searched, you can do
361
+ so inside your models
362
+
363
+ class Article < ActiveRecord::Base
364
+ attr_searchable :some_public_data, :some_more_searchable_stuff
365
+ assoc_searchable :search_this_association_why_dontcha
366
+ end
367
+
368
+ If you'd rather blacklist attributes and associations rather than whitelist, use the
369
+ <tt>attr_unsearchable</tt> and <tt>assoc_unsearchable</tt> method instead. If a
370
+ whitelist is supplied, it takes precedence.
371
+
372
+ Excluded attributes on a model will be honored across associations, so if an Article
373
+ <tt>has_many :comments</tt> and the Comment model looks something like this:
374
+
375
+ class Comment < ActiveRecord::Base
376
+ validates_presence_of :user_id, :body
377
+ attr_unsearchable :user_id
378
+ end
379
+
380
+ Then your call to <tt>Article.search</tt> will allow <tt>:comments_body_contains</tt>
381
+ but not <tt>:comments_user_id_equals</tt> to be passed.
382
+
383
+ === Conditional access to searches
384
+
385
+ <tt>search_methods</tt>, <tt>attr_searchable</tt>, <tt>attr_unsearchable</tt>,
386
+ <tt>assoc_searchable</tt>, and <tt>assoc_unsearchable</tt> all accept an <tt>:if</tt>
387
+ option. If present, it should specify a Proc (or other object responding to <tt>call</tt>)
388
+ that accepts a single parameter. This parameter will be the instance of the MetaSearch::Builder
389
+ that gets created by a call to Model.search. Any unused search options (the second hash param)
390
+ that get passed to Model.search will be available via the Builder object's <tt>options</tt>
391
+ reader, and can be used for access control via this proc/object.
392
+
393
+ Example:
394
+
395
+ assoc_unsearchable :notes,
396
+ :if => proc {|s| s.options[:access] == 'blocked' || !s.options[:access]}
397
+
398
+ === Localization
399
+
400
+ MetaSearch supports i18n localization in a few different ways. Consider this abbreviated
401
+ example "flanders" locale:
402
+
403
+ flanders:
404
+ activerecord:
405
+ attributes:
406
+ company:
407
+ name: "Company name-diddly"
408
+ developer:
409
+ name: "Developer name-diddly"
410
+ salary: "Developer salary-doodly"
411
+ meta_search:
412
+ or: 'or-diddly'
413
+ predicates:
414
+ contains: "%{attribute} contains-diddly"
415
+ equals: "%{attribute} equals-diddly"
416
+ attributes:
417
+ company:
418
+ reverse_name: "Company reverse name-diddly"
419
+ developer:
420
+ name_contains: "Developer name-diddly contains-aroonie"
421
+
422
+ First, MetaSearch will use a key found under meta_search.attributes.model_name.attribute_name,
423
+ if it exists. As a fallback, it will use a localization based on the predicate type, along with
424
+ the usual ActiveRecord attribute localization (the activerecord.attributes.model_name keys above).
425
+ Additionally, a localized "or" can be specified for multi-column searches.
426
+
427
+ == Contributions
428
+
429
+ There are several ways you can help MetaSearch continue to improve.
430
+
431
+ * Use MetaSearch in your real-world projects and {submit bug reports or feature suggestions}[http://metautonomous.lighthouseapp.com/projects/53012-metasearch/].
432
+ * Better yet, if you’re so inclined, fix the issue yourself and submit a patch! Or you can {fork the project on GitHub}[http://github.com/ernie/meta_search] and send me a pull request (please include tests!)
433
+ * If you like MetaSearch, spread the word. More users == more eyes on code == more bugs getting found == more bugs getting fixed (hopefully!)
434
+ * Lastly, if MetaSearch has saved you hours of development time on your latest Rails gig, and you’re feeling magnanimous, please consider {making a donation}[http://pledgie.com/campaigns/9647] to the project. I have spent hours of my personal time coding and supporting MetaSearch, and your donation would go a great way toward justifying that time spent to my loving wife. :)
435
+
436
+ == Copyright
437
+
438
+ Copyright (c) 2010 {Ernie Miller}[http://metautonomo.us]. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,69 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "meta_search"
8
+ gem.summary = %Q{Object-based searching (and more) for simply creating search forms.}
9
+ gem.description = %Q{
10
+ Allows simple search forms to be created against an AR3 model
11
+ and its associations, has useful view helpers for sort links
12
+ and multiparameter fields as well.
13
+ }
14
+ gem.email = "ernie@metautonomo.us"
15
+ gem.homepage = "http://metautonomo.us/projects/metasearch/"
16
+ gem.authors = ["Ernie Miller"]
17
+ gem.post_install_message = <<END
18
+
19
+ *** Thanks for installing MetaSearch! ***
20
+ Be sure to check out http://metautonomo.us/projects/metasearch/ for a
21
+ walkthrough of MetaSearch's features, and click the donate button if
22
+ you're feeling especially appreciative. It'd help me justify this
23
+ "open source" stuff to my lovely wife. :)
24
+
25
+ END
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+ rescue LoadError
29
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
30
+ end
31
+
32
+ require 'rake/testtask'
33
+ Rake::TestTask.new(:test) do |test|
34
+ test.libs << 'lib' << 'test'
35
+ test.libs << 'vendor/rails/activerecord/lib'
36
+ test.libs << 'vendor/rails/activesupport/lib'
37
+ test.libs << 'vendor/rails/actionpack/lib'
38
+ test.libs << 'vendor/arel/lib'
39
+ test.pattern = 'test/**/test_*.rb'
40
+ test.verbose = true
41
+ end
42
+
43
+ begin
44
+ require 'rcov/rcovtask'
45
+ Rcov::RcovTask.new do |test|
46
+ test.libs << 'test'
47
+ test.pattern = 'test/**/test_*.rb'
48
+ test.verbose = true
49
+ end
50
+ rescue LoadError
51
+ task :rcov do
52
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
53
+ end
54
+ end
55
+
56
+ # Don't check dependencies on test, we're using vendored libraries
57
+ # task :test => :check_dependencies
58
+
59
+ task :default => :test
60
+
61
+ require 'rdoc/task'
62
+ Rake::RDocTask.new do |rdoc|
63
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
64
+
65
+ rdoc.rdoc_dir = 'rdoc'
66
+ rdoc.title = "meta_search #{version}"
67
+ rdoc.rdoc_files.include('README*')
68
+ rdoc.rdoc_files.include('lib/**/*.rb')
69
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.1.3