Permalink
Browse files

Updated searchgasm

  • Loading branch information...
1 parent ba5860a commit 5622daac5eb673b5b1a1bca2fe14684dfedf38e1 @binarylogic committed Sep 7, 2008
Showing with 383 additions and 348 deletions.
  1. +1 −1 config/environments/development.rb
  2. +0 −335 vendor/plugins/searchgasm-0.9.8/README.rdoc
  3. +2 −0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/CHANGELOG
  4. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/MIT-LICENSE
  5. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/Manifest
  6. +340 −0 vendor/plugins/searchgasm-0.9.9/README.rdoc
  7. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/Rakefile
  8. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/examples/README.rdoc
  9. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/init.rb
  10. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm.rb
  11. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/active_record/associations.rb
  12. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/active_record/base.rb
  13. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/base.rb
  14. +1 −1 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/begins_with.rb
  15. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/child_of.rb
  16. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/contains.rb
  17. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/descendant_of.rb
  18. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/does_not_equal.rb
  19. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/ends_with.rb
  20. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/equals.rb
  21. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/greater_than.rb
  22. 0 ...lugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/greater_than_or_equal_to.rb
  23. 0 ...plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/inclusive_descendant_of.rb
  24. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/keywords.rb
  25. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/less_than.rb
  26. 0 ...r/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/less_than_or_equal_to.rb
  27. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/sibling_of.rb
  28. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/condition/tree.rb
  29. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/conditions/base.rb
  30. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/conditions/protection.rb
  31. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/config.rb
  32. +1 −1 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/helpers/form_helper.rb
  33. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/helpers/search_helper.rb
  34. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/helpers/utilities_helper.rb
  35. +2 −1 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/search/base.rb
  36. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/search/conditions.rb
  37. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/search/ordering.rb
  38. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/search/pagination.rb
  39. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/search/protection.rb
  40. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/utilities.rb
  41. +1 −1 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/lib/searchgasm/version.rb
  42. +2 −2 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/searchgasm.gemspec
  43. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/fixtures/accounts.yml
  44. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/fixtures/orders.yml
  45. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/fixtures/users.yml
  46. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/libs/acts_as_tree.rb
  47. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/libs/rexml_fix.rb
  48. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/test_active_record_associations.rb
  49. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/test_active_record_base.rb
  50. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/test_condition.rb
  51. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/test_conditions_base.rb
  52. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/test_helper.rb
  53. +17 −6 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/test_search_base.rb
  54. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/test_search_ordering.rb
  55. +16 −0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/test_search_pagination.rb
  56. 0 vendor/plugins/{searchgasm-0.9.8 → searchgasm-0.9.9}/test/test_search_protection.rb
@@ -17,4 +17,4 @@
config.action_mailer.raise_delivery_errors = false
config.plugin_paths += ["../../Ruby Libs"]
-config.plugins = ["calendar_date_select", "searchgasm-0.9.8"]
+config.plugins = ["calendar_date_select", "searchgasm-0.9.9"]
@@ -1,335 +0,0 @@
-= Searchgasm
-
-Searchgasm is orgasmic. Maybe not orgasmic, but you will get aroused. So go grab a towel and let's dive in.
-
-<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>
-
-== Under the hood
-
-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.
-
-== Quicklinks
-
-* <b>Documentation:</b> http://searchgasm.rubyforge.org
-* <b>Easy pagination, ordering, and searching tutorial:</b> http://www.binarylogic.com/2008/9/7/tutorial-pagination-ordering-and-searching-with-searchgasm
-* <b>The tutorial above, live:</b> http://searchgasm_example.binarylogic.com
-
-== Install and use
-
- sudo gem install searchgasm
-
-For rails > 2.1
-
- # environment.rb
- config.gem "searchgasm"
-
-For rails < 2.1
-
- # environment.rb
- require "searchgasm"
-
-Or as a plugin
-
- script/plugin install git://github.com/binarylogic/searchgasm.git
-
-Now try out some of the examples below:
-
-<b>For all examples, let's assume the following relationships: User => Orders => Line Items</b>
-
-== The beauty of searchgasm
-
-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:
-
- # app/controllers/users_controller.rb
- def index
- @search = User.new_search(params[:search])
- @users, @users_count = @search.all, @search.count
- end
-
-Now your view. Notice you can use your search object <b>just like</b> an ActiveRecord object.
-
- # app/views/users/index.html.haml
- - form_for @search do |f|
- - f.fields_for @search.conditions do |users|
- = users.text_field :first_name_contains
- = users.calendar_date_select :created_after # nice rails plugin for replacing date_select
- - users.fields_for users.object.orders do |orders|
- = orders.select :total_gt, (1..100)
- = f.submit "Search"
-
- %table
- %tr
- %th= order_by :first_name
- %th= order_by :last_name
- %th= order_by :email
- - @users.each do |user|
- %tr
- %td= user.first_name
- %td= user.last_name
- %td= user.email
-
- Per page:
- = per_page
- Page:
- = page
-
-Nice and simple. 2 lines in your controller, no "cruft" in your models, pagination as simple as calling the "page" and "per_page" helpers, ordering as simple as calling "order_by", and all searching conditions in 1 spot: your form. For documentation on helpers see Searchgasm::Helpers::FormHelper and Searchgasm::Helpers::SearchHelper.
-
-<b>See this example live: http://searchgasm_example.binarylogic.com</b>
-
-== Simple Searching Example
-
- User.all(
- :conditions => {
- :first_name_contains => "Ben", # first_name like '%Ben%'
- :email_ends_with => "binarylogic.com" # email like '%binarylogic.com'
- },
- :per_page => 20 # limit 20
- :page => 3 # offset 40, which starts us on page 3
- )
-
-Instead of using the "all" method you could use any search method: first, find(:all), find(:first), count, sum, average, etc, just like ActiveRecord
-
-== Exhaustive Example w/ Object Based Searching (great for form_for or fields_for)
-
- # Instantiate
- @search = User.new_search(
- :conditions => {
- :first_name_contains => "Ben",
- :age_gt => 18,
- :orders => {:total_lt => 100}
- },
- :per_page => 20,
- :page => 2,
- :order_by => {:orders => :total},
- :order_as => "DESC"
- )
-
- # Set local conditions
- @search.conditions.email_ends_with = "binarylogic.com"
-
- # Set conditions on relationships
- @search.conditions.oders.line_items.created_after = Time.now # can traverse through all relationships
-
- # Set options
- @search.per_page = 50 # overrides the 20 set above
- @search.order_by = [:first_name, {:user_group => :name}] # order by first name and then by the user group's name it belongs to
- @search.order_as = "ASC"
-
- # Set ANY of the ActiveRecord options
- @search.group = "last_name"
- @search.readonly = true
- # ... see ActiveRecord documentation
-
- # Return results just like ActiveRecord
- @search.all
- @search.first
-
-Take the @search object and pass it right into form\_for or fields\_for (see above).
-
-== Calculations
-
-Using the object from above:
-
- @search.average('id')
- @search.count
- @search.maximum('id')
- @search.minimum('id')
- @search.sum('id')
- @search.calculate(:sum, 'id')
- # ...any of the above calculations, see ActiveRecord documentation on calculations
-
-Or do it from your model:
-
- User.count(:conditions => {:first_name_contains => "Ben"})
- User.sum('id', :conditions => {:first_name_contains => "Ben"})
- # ... all other calcualtions, etc.
-
-== Different ways to search, take your pick
-
-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:
-
- User.all(:conditions => {:age_gt => 18}, :per_page => 20)
-
- User.first(:conditions => {:age_gt => 18}, :per_page => 20)
-
- User.find(:all, :conditions => {::age_gt => 18}, :per_page => 20)
-
- User.find(:first, :conditions => {::age_gt => 18}, :per_page => 20)
-
- search = User.new_search(:conditions => {:age_gt => 18}) # build_search is an alias
- search.conditions.first_name_contains = "Ben"
- search.per_page = 20
- search.all
-
-If you want to use Searchgasm directly:
-
- search = Searchgasm::Search::Base.new(User, :conditions => {:age_gt => 18})
- search.conditions.first_name_contains = "Ben"
- search.per_page = 20
- search.all
-
-== Search with conditions only
-
- conditions = User.new_conditions(:age_gt => 18)
- conditions.first_name_contains = "Ben"
- conditions.all
- # ... all operations above are available
-
-Pass a conditions object right into ActiveRecord:
-
- User.all(:conditions => conditions)
-
-Again, if you want to use Searchgasm directly:
-
- conditions = Searchgasm::Conditions::Base.new(User, :age_gt => 18)
- conditions.first_name_contains = "Ben"
- conditions.all
-
-Now pass the conditions object right into form\_for or fields\_for (see above for example).
-
-== Scoped searching
-
- @current_user.orders.find(:all, :conditions => {:total_lte => 500})
- @current_user.orders.count(:conditions => {:total_lte => 500})
- @current_user.orders.sum('total', :conditions => {:total_lte => 500})
-
- search = @current_user.orders.build_search('total', :conditions => {:total_lte => 500})
-
-== Searching trees
-
-For tree data structures you get a few nifty methods. Let's assume Users is a tree data structure.
-
- # Child of
- User.all(:conditions => {:child_of => User.roots.first})
- User.all(:conditions => {:child_of => User.roots.first.id})
-
- # Sibling of
- User.all(:conditions => {:sibling_of => User.roots.first})
- User.all(:conditions => {:sibling_of => User.roots.first.id})
-
- # Descendant of (includes all recursive children: children, grand children, great grand children, etc)
- User.all(:conditions => {:descendant_of => User.roots.first})
- User.all(:conditions => {:descendant_of => User.roots.first.id})
-
- # Inclusive descendant_of. Same as above but includes the root
- User.all(:conditions => {:inclusive_descendant_of => User.roots.first})
- User.all(:conditions => {:inclusive_descendant_of => User.roots.first.id})
-
-
-== Available anywhere (relationships & scopes)
-
-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.
-
- class User < ActiveRecord::Base
- has_many :expensive_pending_orders, :conditions => {:total_greater_than => 1_000_000, :state => :pending}, :per_page => 20
- named_scope :sexy, :conditions => {:first_name => "Ben", email_ends_with => "binarylogic.com"}, :per_page => 20
- end
-
-== Always use protection...against SQL injections
-
-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!.
-
-=== Protected from SQL injections
-
- search = Account.new_search(params[:search])
- conditions = Account.new_conditions(params[:conditions])
-
-=== *NOT* protected from SQL injections
-
- accounts = Account.find(params[:search])
- accounts = Account.all(params[:search])
- account = Account.first(params[:search])
- search = Account.new_search!(params[:search])
- conditions = Account.new_conditions!(params[:conditions])
-
-Lesson learned: use new\_search and new\_conditions when passing in params as *ANY* of the options.
-
-== Available Conditions
-
-Depending on the type, each column comes preloaded with a bunch of nifty conditions:
-
- all columns
- => :equals, :does_not_equal
-
- :string, :text
- => :begins_with, :contains, :keywords, :ends_with
-
- :integer, :float, :decimal,:datetime, :timestamp, :time, :date
- => :greater_than, :greater_than_or_equal_to, :less_than, :less_than_or_equal_to
-
- tree data structures (see above "searching trees")
- => :child_of, :sibling_of, :descendant_of, :inclusive_descendant_of
-
-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":
-
- :equals; => :is
- :does_not_equal => :is_not, :not
- :begins_with => :starts_with, :bw, :start
- :contains => :like, :has
- :ends_with => :ew, :ends, :end
- :greater_than => :gt, :after
- :greater_than_or_equal_to => :at_least, :gte
- :keywords => :kwords, :kw
- :less_than => :lt, :before
- :less_than_or_equal_to => :at_most, :lte
-
-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.
-
-=== Enhanced searching and blacklisted words
-
-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.
-
-=== Roll your own conditions
-
-I didn't include this function because its MySQL specific, and it's probably rarely used, but MySQL supports a "SOUNDS LIKE" function.
-
-I want to use it, so let's add it:
-
- # config/initializers/searchgasm.rb
- # Actual function for MySQL databases only
- class SoundsLike < Searchgasm::Condition::Base
- class << self
- # I pass you the column, you tell me what you want the method to be called.
- # If you don't want to add this condition for that column, return nil
- # It defaults to "#{column.name}_sounds_like". So if thats what you want you don't even need to do this.
- def name_for_column(column)
- super
- end
-
- # Only do this if you want aliases for your condition
- def aliases_for_column(column)
- ["#{column.name}_sounds", "#{column.name}_similar_to"]
- end
- end
-
- # You can return an array or a string. NOT a hash, because all of these conditions
- # need to eventually get merged together. The array or string can be anything you would put in
- # the :conditions option for ActiveRecord::Base.find()
- def to_conditions(value)
- ["#{quoted_table_name}.#{quoted_column_name} SOUNDS LIKE ?", value]
- end
- end
-
- Searchgasm::Conditions::Base.register_condition(SoundsLike)
-
-Now test it out:
-
- search = User.new_search
- search.conditions.first_name_sounds_like = "Ben"
- search.all # will return any user that has a first name that sounds like "Ben"
-
-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
-
-== Reporting problems / bugs
-
-http://binarylogic.lighthouseapp.com/projects/16601-searchgasm
-
-== Credits
-
-Author: {Ben Johnson}[http://github.com/binarylogic] of {Binary Logic}[http://www.binarylogic.com]
-
-Credit to {Zack Ham}[http://github.com/zackham] and {Robert Malko}[http://github.com/malkomalko/] for helping with feature suggestions.
-
-
-Copyright (c) 2008 {Ben Johnson}[http://github.com/binarylogic] of {Binary Logic}[http://www.binarylogic.com], released under the MIT license
@@ -1,3 +1,5 @@
+v0.9.9. Fixed setting per_page to nil, false, or ''. This is done to "show all" results.
+
v0.9.8. Fixed order_by helper bug when determing the text with arrays. Should use the first value instead of last. Added in per_page config option.
v0.9.7. Complete class restructure, much more organized, added in documentation, added in helpers for using searchgasm in a rails app, updated readme with link to documentation as well as a live example, some bug fixes, more tests
Oops, something went wrong.

0 comments on commit 5622daa

Please sign in to comment.