Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 216 lines (137 sloc) 9.783 kb
a9cbc43 @binarylogic Add v2 files
authored
1 = Searchlogic
2
c2bea31 @binarylogic Update readme
authored
3 <b>Searchlogic has been <em>completely</em> rewritten for v2. It is much simpler and has taken an entirely new approach. To give you an idea, v1 had ~2300 lines of code, v2 has ~420 lines of code.</b>
a9cbc43 @binarylogic Add v2 files
authored
4
c2bea31 @binarylogic Update readme
authored
5 Searchlogic provides common named scopes and object based searching for ActiveRecord.
a9cbc43 @binarylogic Add v2 files
authored
6
8752f2b @binarylogic Update readme and start using github to host gems
authored
7 == Helpful links
8
9 * <b>Documentation:</b> http://rdoc.info/projects/binarylogic/searchlogic
10 * <b>Repository:</b> http://github.com/binarylogic/searchlogic/tree/master
11 * <b>Bugs / feature suggestions:</b> http://binarylogic.lighthouseapp.com/projects/16601-searchlogic
12 * <b>Google group:</b> http://groups.google.com/group/searchlogic
13
14 <b>Before contacting me directly, please read:</b>
51d707c @binarylogic Update README
authored
15
8752f2b @binarylogic Update readme and start using github to host gems
authored
16 If you find a bug or a problem please post it on lighthouse. If you need help with something, please use google groups. I check both regularly and get emails when anything happens, so that is the best place to get help. This also benefits other people in the future with the same questions / problems. Thank you.
51d707c @binarylogic Update README
authored
17
8752f2b @binarylogic Update readme and start using github to host gems
authored
18 == Install & use
51d707c @binarylogic Update README
authored
19
a77b72d @binarylogic Added inner_join convenience method.
authored
20 Install the gem from rubyforge:
21
22 sudo gem install searchlogic
23
24 Or from github:
51d707c @binarylogic Update README
authored
25
a77b72d @binarylogic Added inner_join convenience method.
authored
26 sudo gem install binarylogic-searchlogic
8752f2b @binarylogic Update readme and start using github to host gems
authored
27
a77b72d @binarylogic Added inner_join convenience method.
authored
28 Now just include it in your project and you are ready to go.
8752f2b @binarylogic Update readme and start using github to host gems
authored
29
a77b72d @binarylogic Added inner_join convenience method.
authored
30 You can also install this as a plugin:
51d707c @binarylogic Update README
authored
31
a77b72d @binarylogic Added inner_join convenience method.
authored
32 script/plugin install git://github.com/binarylogic/searchlogic.git
33
34 See below for usage examples.
51d707c @binarylogic Update README
authored
35
7db0934 @binarylogic Some readme cleanup
authored
36 == Search using conditions on columns
37
a9cbc43 @binarylogic Add v2 files
authored
38 Instead of explaining what Searchlogic can do, let me show you. Let's start at the top:
39
40 # We have the following model
41 User(id: integer, created_at: datetime, username: string, age: integer)
42
43 # Searchlogic gives you a bunch of named scopes for free:
44 User.username_equals("bjohnson")
45 User.username_does_not_equal("bjohnson")
46 User.username_begins_with("bjohnson")
47 User.username_like("bjohnson")
48 User.username_ends_with("bjohnson")
49 User.age_greater_than(20)
50 User.age_greater_than_or_equal_to(20)
51 User.age_less_than(20)
52 User.age_less_than_or_equal_to(20)
53 User.username_null
54 User.username_blank
55
56 # You can also order by columns
57 User.ascend_by_username
58 User.descend_by_username
59 User.order("ascend_by_username")
60
9744f24 @binarylogic Added any or all named scopes. See README.
authored
61 Any named scope Searchlogic creates is dynamic and created via method_missing. Meaning it will only create what you need. Also, keep in mind, these are just named scopes, you can chain them, call methods off of them, etc:
a9cbc43 @binarylogic Add v2 files
authored
62
63 scope = User.username_like("bjohnson").age_greater_than(20).ascend_by_username
64 scope.all
65 scope.first
66 scope.count
67 # etc...
68
0e5912a @binarylogic Ignore blank values when settings conditions via a Hash on the SearchPro...
authored
69 That's all pretty standard, but here's where Searchlogic starts to get interesting...
70
1cb9ecb @binarylogic * Allow the chaining of conditions off of a search object. Ex: search.us...
authored
71 == Search using conditions on associated columns
a9cbc43 @binarylogic Add v2 files
authored
72
73 You also get named scopes for any of your associations:
74
75 # We have the following relationships
76 User.has_many :orders
77 Order.has_many :line_items
78 LineItem
79
80 # Set conditions on association columns
81 User.orders_total_greater_than(20)
82 User.orders_line_items_price_greater_than(20)
83
84 # Order by association columns
85 User.ascend_by_order_total
86 User.descend_by_orders_line_items_price
87
764f859 @binarylogic Use inner joins for conditions instead of left outer
authored
88 Again these are just named scopes. You can chain them together, call methods off of them, etc. What's great about these named scopes is that they do NOT use the :include option, making them <em>much</em> faster. Instead they create a INNER JOIN and pass it to the :joins option, which is great for performance. To prove my point here is a quick benchmark from an application I am working on:
0e5912a @binarylogic Ignore blank values when settings conditions via a Hash on the SearchPro...
authored
89
90 Benchmark.bm do |x|
91 x.report { 10.times { Event.tickets_id_gt(10).all(:include => :tickets) } }
85fdcc6 @binarylogic Clean up how the SearchProxy calls scopes with no arity
authored
92 x.report { 10.times { Event.tickets_id_gt(10).all } }
0e5912a @binarylogic Ignore blank values when settings conditions via a Hash on the SearchPro...
authored
93 end
94 user system total real
95 10.120000 0.170000 10.290000 ( 12.625521)
96 2.630000 0.050000 2.680000 ( 3.313754)
97
98 If you want to use the :include option, just specify it:
a9cbc43 @binarylogic Add v2 files
authored
99
100 User.orders_line_items_price_greater_than(20).all(:include => {:orders => :line_items})
101
0e5912a @binarylogic Ignore blank values when settings conditions via a Hash on the SearchPro...
authored
102 Obviously, only do this if you want to actually use the included objects.
a9cbc43 @binarylogic Add v2 files
authored
103
7776b27 @binarylogic Some readme cleanup
authored
104 == Make searching and ordering data in your application trivial
a9cbc43 @binarylogic Add v2 files
authored
105
8563a4d @binarylogic * Split out left outer join creation into its own method, allowing you t...
authored
106 The above is great, but what about tying all of this in with a search form in your application? What would be really nice is if we could use an object that represented a single search. Like this...
a9cbc43 @binarylogic Add v2 files
authored
107
8563a4d @binarylogic * Split out left outer join creation into its own method, allowing you t...
authored
108 search = User.search(:username_like => "bjohnson", :age_less_than => 20)
109 search.all
a9cbc43 @binarylogic Add v2 files
authored
110
111 The above is equivalent to:
112
8563a4d @binarylogic * Split out left outer join creation into its own method, allowing you t...
authored
113 User.username_like("bjohnson").age_less_than(20).all
114
115 You can set, read, and chain conditions off of your search too:
116
117 search.username_like => "bjohnson"
118 search.age_gt = 2 => 2
119 search.id_gt(10).email_begins_with("bjohnson") => <#Searchlogic::Search...>
120 search.all => An array of users
121 search.count => integer
122 # .. etc
a9cbc43 @binarylogic Add v2 files
authored
123
a77b72d @binarylogic Added inner_join convenience method.
authored
124 So let's start with the controller...
125
126 === Your controller
127
128 The search class just chains named scopes together for you. What's so great about that? It keeps your controllers extremely simple:
a9cbc43 @binarylogic Add v2 files
authored
129
130 class UsersController < ApplicationController
131 def index
132 @search = User.search(params[:search])
133 @users = @search.all
134 end
135 end
136
a77b72d @binarylogic Added inner_join convenience method.
authored
137 It doesn't get any simpler than that.
138
139 === Your form
140
141 Adding a search condition is as simple as adding a condition to your form. Remember all of those named scopes above? Just create fields with the same names:
a9cbc43 @binarylogic Add v2 files
authored
142
143 - form_for @search do |f|
144 = f.text_field :username_like
145 = f.select :age_greater_than, (0..100)
146 = f.text_field :orders_total_greater_than
147 = f.submit
148
a77b72d @binarylogic Added inner_join convenience method.
authored
149 When a Searchlogic::Search object is passed to form_for it will add a hidden field for the "order" condition, to preserve the order of the data.
150
151 === Additional helpers
152
153 There really isn't a big need for helpers in searchlogic, other than helping you order data. If you want to order your search with a link, just specify the name of the column. Ex:
0f4b5d6 @binarylogic Add in some basic helpers
authored
154
155 = order @search, :by => :age
a77b72d @binarylogic Added inner_join convenience method.
authored
156 = order @search, :by => :created_at, :as => "Created date"
157
158 The first one will create a link that alternates between calling "ascend_by_age" and "descend_by_age". If you wanted to order your data by more than just a column, create your own named scopes: "ascend_by_*" and "descend_by_*". The "order" helper is a very straight forward helper, checkout the docs for some of the options.
0f4b5d6 @binarylogic Add in some basic helpers
authored
159
a77b72d @binarylogic Added inner_join convenience method.
authored
160 <b>This helper is just a convenience method. It's extremely simple and there is nothing wrong with creating your own. If it doesn't do what you want, copy the code, modify it, and create your own. You could even fork the project, modify it there, and use your own gem.</b>
0f4b5d6 @binarylogic Add in some basic helpers
authored
161
a9cbc43 @binarylogic Add v2 files
authored
162 == Use your existing named scopes
163
164 This is one of the big differences between Searchlogic v1 and v2. What about your existing named scopes? Let's say you have this:
165
166 User.named_scope :four_year_olds, :conditions => {:age => 4}
167
168 Again, these are all just named scopes, use it in the same way:
169
170 User.search(:four_year_olds => true, :username_like => "bjohnson")
171
172 Notice we pass true as the value. If a named scope does not accept any parameters (arity == 0) you can simply pass it true or false. If you pass false, the named scope will be ignored. If your named scope accepts a parameter, the value will be passed right to the named scope regardless of the value.
173
174 Now just throw it in your form:
175
176 - form_for @search do |f|
177 = f.text_field :username_like
178 = f.check_box :four_year_olds
179 = f.submit
180
0e5912a @binarylogic Ignore blank values when settings conditions via a Hash on the SearchPro...
authored
181 What's great about this is that you can do just about anything you want. If Searchlogic doesn't provide a named scope for that crazy edge case that you need, just create your own named scope. The sky is the limit.
a9cbc43 @binarylogic Add v2 files
authored
182
9744f24 @binarylogic Added any or all named scopes. See README.
authored
183 == Use any or all
184
185 Every condition you've seen in this readme also has 2 related conditions that you can use. Example:
186
1cb9ecb @binarylogic * Allow the chaining of conditions off of a search object. Ex: search.us...
authored
187 User.username_like_any("bjohnson", "thunt") # will return any users that have either of the strings in their username
188 User.username_like_all("bjohnson", "thunt") # will return any users that have all of the strings in their username
189 User.username_like_any(["bjohnson", "thunt"]) # also accepts an array
9744f24 @binarylogic Added any or all named scopes. See README.
authored
190
191 This is great for checkbox filters, etc. Where you can pass an array right from your form to this condition.
192
a9cbc43 @binarylogic Add v2 files
authored
193 == Pagination (leverage will_paginate)
194
195 Instead of recreating the wheel with pagination, Searchlogic works great with will_paginate. All that Searchlogic is doing is creating named scopes, and will_paginate works great with named scopes:
196
197 User.username_like("bjohnson").age_less_than(20).paginate(:page => params[:page])
7db0934 @binarylogic Some readme cleanup
authored
198 User.search(:username_like => "bjohnson", :age_less_than => 20).paginate(:page => params[:page])
a9cbc43 @binarylogic Add v2 files
authored
199
200 If you don't like will_paginate, use another solution, or roll your own. Pagination really has nothing to do with searching, and the main goal for Searchlogic v2 was to keep it lean and simple. No reason to recreate the wheel and bloat the library.
201
202 == Under the hood
203
204 Before I use a library in my application I like to glance at the source and try to at least understand the basics of how it works. If you are like me, a nice little explanation from the author is always helpful:
205
206 Searchlogic utilizes method_missing to create all of these named scopes. When it hits method_missing it creates a named scope to ensure it will never hit method missing for that named scope again. Sort of a caching mechanism. It works in the same fashion as ActiveRecord's "find_by_*" methods. This way only the named scopes you need are created and nothing more.
207
764f859 @binarylogic Use inner joins for conditions instead of left outer
authored
208 That's about it, the named scope options are pretty bare bones and created just like you would manually.
a9cbc43 @binarylogic Add v2 files
authored
209
d8f61c4 @binarylogic Update readme
authored
210 == Credit
211
7db0934 @binarylogic Some readme cleanup
authored
212 Thanks a lot to {Tyler Hunt}[http://github.com/tylerhunt] for helping plan, design, and start the project. He was a big help.
d8f61c4 @binarylogic Update readme
authored
213
a9cbc43 @binarylogic Add v2 files
authored
214 == Copyright
215
216 Copyright (c) 2009 {Ben Johnson of Binary Logic}[http://www.binarylogic.com], released under the MIT license
Something went wrong with that request. Please try again.