Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 340 lines (234 sloc) 14.316 kB
6449698 @binarylogic Released verversion 0.9.7
authored
1 = Searchgasm
aa5b90a @binarylogic First commit
authored
2
9968056 @binarylogic Updated readme
authored
3 Searchgasm is orgasmic. Maybe not orgasmic, but you will get aroused. So go grab a towel and let's dive in.
1f7251c @binarylogic Added association_collection
authored
4
6449698 @binarylogic Released verversion 0.9.7
authored
5 <b>Searchgasm's inspiration comes right from ActiveRecord. ActiveRecord lets you create objects that represent a record in the database, so why can't you create objects that represent searching the database? Now you can!</b>
c703fbe @binarylogic Updated readme
authored
6
6449698 @binarylogic Released verversion 0.9.7
authored
7 == Under the hood
1271b7a @binarylogic Added gemspec
authored
8
6449698 @binarylogic Released verversion 0.9.7
authored
9 I'm a big fan of understanding what I'm using, so here's a quick explanation: The design behind this plugin is pretty simple. The search object "sanitizes" down into the options passed into ActiveRecord::Base.find(). It serves as a transparent filter between you and ActiveRecord::Base.find(). This filter provides "enhancements" that get translated into options that ActiveRecord::Base.find() can understand. It doesn't dig into the ActiveRecord internals, it only uses what is publicly available. It jumps in and helps out <em>only</em> when needed, otherwise it sits back and lets ActiveRecord do all of the work. Between that and the extensive tests, this is a solid and fast plugin.
cf23760 @binarylogic Added tests, new features, and improved readme
authored
10
6449698 @binarylogic Released verversion 0.9.7
authored
11 == Quicklinks
c4a3956 @binarylogic Updated helpers, cleaned up code, started documentation
authored
12
85bfebf @binarylogic Updated readme, Github has problems parsing rdoc
authored
13 * <b>Documentation:</b> http://searchgasm.rubyforge.org
14 * <b>Easy pagination, ordering, and searching tutorial:</b> http://www.binarylogic.com/2008/9/7/tutorial-pagination-ordering-and-searching-with-searchgasm
15 * <b>The tutorial above, live:</b> http://searchgasm_example.binarylogic.com
6449698 @binarylogic Released verversion 0.9.7
authored
16
17 == Install and use
18
19 sudo gem install searchgasm
20
3b7f5ae @binarylogic Updated installation guide in readme
authored
21 For rails
6449698 @binarylogic Released verversion 0.9.7
authored
22
3b7f5ae @binarylogic Updated installation guide in readme
authored
23 $ cd vendor/plugins
5400535 @binarylogic Updated installation guide in readme
authored
24 $ sudo gem unpack searchgasm
6449698 @binarylogic Released verversion 0.9.7
authored
25
26 Or as a plugin
27
28 script/plugin install git://github.com/binarylogic/searchgasm.git
29
30 Now try out some of the examples below:
31
32 <b>For all examples, let's assume the following relationships: User => Orders => Line Items</b>
33
34 == The beauty of searchgasm
35
36 Using Searchgasm in rails is the best part, because rails has all kinds of nifty methods to make dealing with ActiveRecord objects quick and easy, especially with forms. So let's take advantage of them! That's the idea behind this plugin. Searchgasm is searching, ordering, and pagination all rolled into one simple plugin. Take all of that pagination and searching cruft out of your models and let Searchgasm handle it. Check it out:
24a7d88 @binarylogic Updated readme
authored
37
38 # app/controllers/users_controller.rb
39 def index
d6f04d3 @binarylogic Big update, added helpers, more features, improved performance
authored
40 @search = User.new_search(params[:search])
24a7d88 @binarylogic Updated readme
authored
41 @users, @users_count = @search.all, @search.count
42 end
43
fc301c4 @binarylogic Updated readme
authored
44 Now your view. Things to note in this view:
45
46 1. Passing a search object right into form\_for and fields\_for
47 2. The built in conditions for each column and how you can traverse the relationships and set conditions on them
48 3. The order_by helper
49 4. The page and per_page helpers
50 5. All of your search logic is in 1 spot: your view. Nice and DRY.
f66721b @binarylogic Github needs to fix the escaping bug for readme
authored
51
28444ca @binarylogic Updated readme
authored
52 Your view:
dc39ad7 @binarylogic Updated readme
authored
53
ecd52d5 @binarylogic Updated readme
authored
54 # app/views/users/index.html.haml
55 - form_for @search do |f|
56 - f.fields_for @search.conditions do |users|
57 = users.text_field :first_name_contains
58 = users.calendar_date_select :created_after # nice rails plugin for replacing date_select
59 - users.fields_for users.object.orders do |orders|
60 = orders.select :total_gt, (1..100)
61 = f.submit "Search"
f66721b @binarylogic Github needs to fix the escaping bug for readme
authored
62
ecd52d5 @binarylogic Updated readme
authored
63 %table
64 %tr
65 %th= order_by :first_name
66 %th= order_by :last_name
67 %th= order_by :email
68 - @users.each do |user|
69 %tr
70 %td= user.first_name
71 %td= user.last_name
72 %td= user.email
f66721b @binarylogic Github needs to fix the escaping bug for readme
authored
73
ecd52d5 @binarylogic Updated readme
authored
74 Per page:
75 = per_page
76 Page:
390a7e3 @binarylogic Updated readme
authored
77 = pages
24a7d88 @binarylogic Updated readme
authored
78
a1e2d41 @binarylogic Fixed some probs in readme
authored
79 <b>See this example live: http://searchgasm_example.binarylogic.com</b>
cf23760 @binarylogic Added tests, new features, and improved readme
authored
80
6578ffd @binarylogic Updated readme
authored
81 You're probably saying, this is great, but I want to do all of this via AJAX. No problem. Check out the {live tutorial}(http://searchgasm_example.binarylogic.com/orders) based on this example, there is a link for an {AJAX example}(http://searchgasm_example.binarylogic.com/orders).
82
83 This is really just the tip of the iceberg. See below for more examples or {check out the documentation}[http://searchgasm.rubyforge.org] for options and explanations.
84
6449698 @binarylogic Released verversion 0.9.7
authored
85 == Simple Searching Example
7db3b5b @binarylogic Updated readme
authored
86
967e690 @binarylogic Cleaned up readme
authored
87 User.all(
88 :conditions => {
760ba27 @binarylogic Added new aliases for date and time columns
authored
89 :first_name_contains => "Ben", # first_name like '%Ben%'
90 :email_ends_with => "binarylogic.com" # email like '%binarylogic.com'
967e690 @binarylogic Cleaned up readme
authored
91 },
760ba27 @binarylogic Added new aliases for date and time columns
authored
92 :per_page => 20 # limit 20
c4a3956 @binarylogic Updated helpers, cleaned up code, started documentation
authored
93 :page => 3 # offset 40, which starts us on page 3
967e690 @binarylogic Cleaned up readme
authored
94 )
1271b7a @binarylogic Added gemspec
authored
95
6449698 @binarylogic Released verversion 0.9.7
authored
96 Instead of using the "all" method you could use any search method: first, find(:all), find(:first), count, sum, average, etc, just like ActiveRecord
4065f0d @binarylogic Updated readme
authored
97
6449698 @binarylogic Released verversion 0.9.7
authored
98 == Exhaustive Example w/ Object Based Searching (great for form_for or fields_for)
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
99
760ba27 @binarylogic Added new aliases for date and time columns
authored
100 # Instantiate
dcf6ebf @binarylogic Updated readme
authored
101 @search = User.new_search(
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
102 :conditions => {
103 :first_name_contains => "Ben",
104 :age_gt => 18,
105 :orders => {:total_lt => 100}
7db3b5b @binarylogic Updated readme
authored
106 },
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
107 :per_page => 20,
108 :page => 2,
109 :order_by => {:orders => :total},
110 :order_as => "DESC"
9968056 @binarylogic Updated readme
authored
111 )
760ba27 @binarylogic Added new aliases for date and time columns
authored
112
6449698 @binarylogic Released verversion 0.9.7
authored
113 # Set local conditions
dcf6ebf @binarylogic Updated readme
authored
114 @search.conditions.email_ends_with = "binarylogic.com"
6449698 @binarylogic Released verversion 0.9.7
authored
115
c36febc @binarylogic Updated readme
authored
116 # Set conditions on relationships
117 @search.conditions.oders.line_items.created_after = Time.now # can traverse through all relationships
760ba27 @binarylogic Added new aliases for date and time columns
authored
118
119 # Set options
5a9f70e @binarylogic Updated readme
authored
120 @search.per_page = 50 # overrides the 20 set above
c36febc @binarylogic Updated readme
authored
121 @search.order_by = [:first_name, {:user_group => :name}] # order by first name and then by the user group's name it belongs to
122 @search.order_as = "ASC"
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
123
760ba27 @binarylogic Added new aliases for date and time columns
authored
124 # Set ANY of the ActiveRecord options
dcf6ebf @binarylogic Updated readme
authored
125 @search.group = "last_name"
126 @search.readonly = true
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
127 # ... see ActiveRecord documentation
128
129 # Return results just like ActiveRecord
dcf6ebf @binarylogic Updated readme
authored
130 @search.all
131 @search.first
132
c703fbe @binarylogic Updated readme
authored
133 Take the @search object and pass it right into form\_for or fields\_for (see above).
cf23760 @binarylogic Added tests, new features, and improved readme
authored
134
6449698 @binarylogic Released verversion 0.9.7
authored
135 == Calculations
cf23760 @binarylogic Added tests, new features, and improved readme
authored
136
137 Using the object from above:
138
aa89fc3 @binarylogic Added searching for conditions objects
authored
139 @search.average('id')
140 @search.count
141 @search.maximum('id')
142 @search.minimum('id')
143 @search.sum('id')
6449698 @binarylogic Released verversion 0.9.7
authored
144 @search.calculate(:sum, 'id')
5a9f70e @binarylogic Updated readme
authored
145 # ...any of the above calculations, see ActiveRecord documentation on calculations
1f7251c @binarylogic Added association_collection
authored
146
cf23760 @binarylogic Added tests, new features, and improved readme
authored
147 Or do it from your model:
148
149 User.count(:conditions => {:first_name_contains => "Ben"})
47f2ffe @binarylogic Found pattpattern for search methods
authored
150 User.sum('id', :conditions => {:first_name_contains => "Ben"})
cf23760 @binarylogic Added tests, new features, and improved readme
authored
151 # ... all other calcualtions, etc.
152
6449698 @binarylogic Released verversion 0.9.7
authored
153 == Different ways to search, take your pick
7db3b5b @binarylogic Updated readme
authored
154
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
155 Any of the options used in the above example can be used in these, but for the sake of brevity I am only using a few:
7db3b5b @binarylogic Updated readme
authored
156
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
157 User.all(:conditions => {:age_gt => 18}, :per_page => 20)
7db3b5b @binarylogic Updated readme
authored
158
1271b7a @binarylogic Added gemspec
authored
159 User.first(:conditions => {:age_gt => 18}, :per_page => 20)
7db3b5b @binarylogic Updated readme
authored
160
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
161 User.find(:all, :conditions => {::age_gt => 18}, :per_page => 20)
7db3b5b @binarylogic Updated readme
authored
162
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
163 User.find(:first, :conditions => {::age_gt => 18}, :per_page => 20)
7db3b5b @binarylogic Updated readme
authored
164
760ba27 @binarylogic Added new aliases for date and time columns
authored
165 search = User.new_search(:conditions => {:age_gt => 18}) # build_search is an alias
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
166 search.conditions.first_name_contains = "Ben"
1271b7a @binarylogic Added gemspec
authored
167 search.per_page = 20
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
168 search.all
7db3b5b @binarylogic Updated readme
authored
169
6449698 @binarylogic Released verversion 0.9.7
authored
170 If you want to use Searchgasm directly:
7db3b5b @binarylogic Updated readme
authored
171
6449698 @binarylogic Released verversion 0.9.7
authored
172 search = Searchgasm::Search::Base.new(User, :conditions => {:age_gt => 18})
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
173 search.conditions.first_name_contains = "Ben"
1271b7a @binarylogic Added gemspec
authored
174 search.per_page = 20
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
175 search.all
7db3b5b @binarylogic Updated readme
authored
176
6449698 @binarylogic Released verversion 0.9.7
authored
177 == Search with conditions only
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
178
179 conditions = User.new_conditions(:age_gt => 18)
180 conditions.first_name_contains = "Ben"
181 conditions.all
182 # ... all operations above are available
183
184 Pass a conditions object right into ActiveRecord:
185
6449698 @binarylogic Released verversion 0.9.7
authored
186 User.all(:conditions => conditions)
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
187
6449698 @binarylogic Released verversion 0.9.7
authored
188 Again, if you want to use Searchgasm directly:
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
189
6449698 @binarylogic Released verversion 0.9.7
authored
190 conditions = Searchgasm::Conditions::Base.new(User, :age_gt => 18)
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
191 conditions.first_name_contains = "Ben"
6449698 @binarylogic Released verversion 0.9.7
authored
192 conditions.all
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
193
28cd46c @binarylogic Updated readme
authored
194 Now pass the conditions object right into form\_for or fields\_for (see above for example).
195
6449698 @binarylogic Released verversion 0.9.7
authored
196 == Scoped searching
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
197
86ba608 @binarylogic Updated readme
authored
198 @current_user.orders.find(:all, :conditions => {:total_lte => 500})
199 @current_user.orders.count(:conditions => {:total_lte => 500})
200 @current_user.orders.sum('total', :conditions => {:total_lte => 500})
1271b7a @binarylogic Added gemspec
authored
201
202 search = @current_user.orders.build_search('total', :conditions => {:total_lte => 500})
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
203
6449698 @binarylogic Released verversion 0.9.7
authored
204 == Searching trees
cf23760 @binarylogic Added tests, new features, and improved readme
authored
205
206 For tree data structures you get a few nifty methods. Let's assume Users is a tree data structure.
207
208 # Child of
209 User.all(:conditions => {:child_of => User.roots.first})
210 User.all(:conditions => {:child_of => User.roots.first.id})
211
212 # Sibling of
213 User.all(:conditions => {:sibling_of => User.roots.first})
214 User.all(:conditions => {:sibling_of => User.roots.first.id})
215
f5450d1 @binarylogic Changed structure of conditions
authored
216 # Descendant of (includes all recursive children: children, grand children, great grand children, etc)
217 User.all(:conditions => {:descendant_of => User.roots.first})
218 User.all(:conditions => {:descendant_of => User.roots.first.id})
cf23760 @binarylogic Added tests, new features, and improved readme
authored
219
f5450d1 @binarylogic Changed structure of conditions
authored
220 # Inclusive descendant_of. Same as above but includes the root
221 User.all(:conditions => {:inclusive_descendant_of => User.roots.first})
222 User.all(:conditions => {:inclusive_descendant_of => User.roots.first.id})
cf23760 @binarylogic Added tests, new features, and improved readme
authored
223
224
6449698 @binarylogic Released verversion 0.9.7
authored
225 == Available anywhere (relationships & scopes)
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
226
6449698 @binarylogic Released verversion 0.9.7
authored
227 Not only can you use searchgasm when searching, but you can use it when setting up relationships or scopes. Anywhere you specify conditions in ActiveRecord.
7db3b5b @binarylogic Updated readme
authored
228
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
229 class User < ActiveRecord::Base
230 has_many :expensive_pending_orders, :conditions => {:total_greater_than => 1_000_000, :state => :pending}, :per_page => 20
231 named_scope :sexy, :conditions => {:first_name => "Ben", email_ends_with => "binarylogic.com"}, :per_page => 20
7db3b5b @binarylogic Updated readme
authored
232 end
590f51e @binarylogic Updated readme
authored
233
6449698 @binarylogic Released verversion 0.9.7
authored
234 == Always use protection...against SQL injections
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
235
6449698 @binarylogic Released verversion 0.9.7
authored
236 If there is one thing we all know, it's to always use protection against SQL injections. That's why searchgasm protects you by default. The new\_search and new\_conditions methods are protected by default. This means that various checks are done to ensure it is not possible to perform any type of SQL injection. But this also limits how you can search, meaning you can't write raw SQL. If you want to be daring and search without protection, all that you have to do is add ! to the end of the methods: new\_search! and new\_conditions!.
590f51e @binarylogic Updated readme
authored
237
6449698 @binarylogic Released verversion 0.9.7
authored
238 === Protected from SQL injections
9968056 @binarylogic Updated readme
authored
239
33f192e @binarylogic Ehanced protection
authored
240 search = Account.new_search(params[:search])
241 conditions = Account.new_conditions(params[:conditions])
ae22512 @binarylogic Updated readme
authored
242
6449698 @binarylogic Released verversion 0.9.7
authored
243 === *NOT* protected from SQL injections
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
244
33f192e @binarylogic Ehanced protection
authored
245 accounts = Account.find(params[:search])
7db3b5b @binarylogic Updated readme
authored
246 accounts = Account.all(params[:search])
33f192e @binarylogic Ehanced protection
authored
247 account = Account.first(params[:search])
248 search = Account.new_search!(params[:search])
249 conditions = Account.new_conditions!(params[:conditions])
250
251 Lesson learned: use new\_search and new\_conditions when passing in params as *ANY* of the options.
aa5b90a @binarylogic First commit
authored
252
6449698 @binarylogic Released verversion 0.9.7
authored
253 == Available Conditions
ae22512 @binarylogic Updated readme
authored
254
1271b7a @binarylogic Added gemspec
authored
255 Depending on the type, each column comes preloaded with a bunch of nifty conditions:
ae22512 @binarylogic Updated readme
authored
256
7db3b5b @binarylogic Updated readme
authored
257 all columns
258 => :equals, :does_not_equal
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
259
7db3b5b @binarylogic Updated readme
authored
260 :string, :text
261 => :begins_with, :contains, :keywords, :ends_with
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
262
7db3b5b @binarylogic Updated readme
authored
263 :integer, :float, :decimal,:datetime, :timestamp, :time, :date
264 => :greater_than, :greater_than_or_equal_to, :less_than, :less_than_or_equal_to
ae22512 @binarylogic Updated readme
authored
265
cf23760 @binarylogic Added tests, new features, and improved readme
authored
266 tree data structures (see above "searching trees")
f5450d1 @binarylogic Changed structure of conditions
authored
267 => :child_of, :sibling_of, :descendant_of, :inclusive_descendant_of
cf23760 @binarylogic Added tests, new features, and improved readme
authored
268
7db3b5b @binarylogic Updated readme
authored
269 Some of these conditions come with aliases, so you have your choice how to call the conditions. For example you can use "greater\_than" or "gt":
1f7251c @binarylogic Added association_collection
authored
270
5a9f70e @binarylogic Updated readme
authored
271 :equals => :is
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
272 :does_not_equal => :is_not, :not
f5450d1 @binarylogic Changed structure of conditions
authored
273 :begins_with => :starts_with, :bw, :start
274 :contains => :like, :has
275 :ends_with => :ew, :ends, :end
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
276 :greater_than => :gt, :after
7db3b5b @binarylogic Updated readme
authored
277 :greater_than_or_equal_to => :at_least, :gte
f5450d1 @binarylogic Changed structure of conditions
authored
278 :keywords => :kwords, :kw
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
279 :less_than => :lt, :before
7db3b5b @binarylogic Updated readme
authored
280 :less_than_or_equal_to => :at_most, :lte
4fb5929 @binarylogic Added new features, cleaned up readme
authored
281
6449698 @binarylogic Released verversion 0.9.7
authored
282 For more information on each condition see Searchgasm::Condition. Each condition has it's own class and the source is pretty simple and self explanatory.
283
284 === Enhanced searching and blacklisted words
bec7f7d @binarylogic Reffeactored and changed everything, much nicer
authored
285
286 You will notice above there is "contains" and "keywords". The difference is that "keywords" is an enhanced search. It acts like a real keyword search. It finds those keywords, in any order, and blacklists meaningless words such as "and", "the", etc. "contains" finds the EXACT string in the column you are searching, spaces and all.
287
6449698 @binarylogic Released verversion 0.9.7
authored
288 === Roll your own conditions
e8274f3 @binarylogic Added example in readme for adding your own conditions
authored
289
290 I didn't include this function because its MySQL specific, and it's probably rarely used, but MySQL supports a "SOUNDS LIKE" function.
291
292 I want to use it, so let's add it:
293
294 # config/initializers/searchgasm.rb
295 # Actual function for MySQL databases only
6449698 @binarylogic Released verversion 0.9.7
authored
296 class SoundsLike < Searchgasm::Condition::Base
e8274f3 @binarylogic Added example in readme for adding your own conditions
authored
297 class << self
298 # I pass you the column, you tell me what you want the method to be called.
299 # If you don't want to add this condition for that column, return nil
300 # It defaults to "#{column.name}_sounds_like". So if thats what you want you don't even need to do this.
301 def name_for_column(column)
302 super
303 end
304
305 # Only do this if you want aliases for your condition
306 def aliases_for_column(column)
307 ["#{column.name}_sounds", "#{column.name}_similar_to"]
308 end
309 end
310
7e23dad @binarylogic Updated readme
authored
311 # You can return an array or a string. NOT a hash, because all of these conditions
312 # need to eventually get merged together. The array or string can be anything you would put in
313 # the :conditions option for ActiveRecord::Base.find()
e8274f3 @binarylogic Added example in readme for adding your own conditions
authored
314 def to_conditions(value)
315 ["#{quoted_table_name}.#{quoted_column_name} SOUNDS LIKE ?", value]
316 end
317 end
318
6449698 @binarylogic Released verversion 0.9.7
authored
319 Searchgasm::Conditions::Base.register_condition(SoundsLike)
e8274f3 @binarylogic Added example in readme for adding your own conditions
authored
320
321 Now test it out:
322
323 search = User.new_search
6449698 @binarylogic Released verversion 0.9.7
authored
324 search.conditions.first_name_sounds_like = "Ben"
e8274f3 @binarylogic Added example in readme for adding your own conditions
authored
325 search.all # will return any user that has a first name that sounds like "Ben"
326
6449698 @binarylogic Released verversion 0.9.7
authored
327 Pretty nifty, huh? You can create any condition ultimately creating any SQL you want. The sky is the limit. For more information see Searchgasm::Condition::Base
328
329 == Reporting problems / bugs
330
331 http://binarylogic.lighthouseapp.com/projects/16601-searchgasm
e8274f3 @binarylogic Added example in readme for adding your own conditions
authored
332
6449698 @binarylogic Released verversion 0.9.7
authored
333 == Credits
4fb5929 @binarylogic Added new features, cleaned up readme
authored
334
1320254 @binarylogic Fixed some probs in readme
authored
335 Author: {Ben Johnson}[http://github.com/binarylogic] of {Binary Logic}[http://www.binarylogic.com]
9b5304b @binarylogic Updated readme
authored
336
1320254 @binarylogic Fixed some probs in readme
authored
337 Credit to {Zack Ham}[http://github.com/zackham] and {Robert Malko}[http://github.com/malkomalko/] for helping with feature suggestions.
aa5b90a @binarylogic First commit
authored
338
339
1320254 @binarylogic Fixed some probs in readme
authored
340 Copyright (c) 2008 {Ben Johnson}[http://github.com/binarylogic] of {Binary Logic}[http://www.binarylogic.com], released under the MIT license
Something went wrong with that request. Please try again.