Permalink
Browse files

Improved inspect and made protection persistent among associated cond…

…itions.
  • Loading branch information...
1 parent 07f8a72 commit e3d7cd5959cbe87ca8b20593826e9bd175910f33 @binarylogic committed Sep 14, 2008
View
@@ -3,3 +3,4 @@
pkg/*
coverage/*
doc/*
+benchmarks/*
View
@@ -1,7 +1,12 @@
+== 1.0.3 released 2008-09-14
+
+* Updated inspect to show the current options for your search. Plays nicer in the console.
+* Made sure protection state is persistent among relationship conditions.
+
== 1.0.2 released 2008-09-12
* Moved cached searchers out of the global namespace and into the Searchgasm::Cache namespce.
-* Various changes to improve performance. Added in benchmark reports in readme as well as a benchmarks directory.
+* Various changes to improve performance through profiling / benchmarking. http://pastie.org/271936
* Config.per_page works with new_search & new_search! only. Where as before it was only working if the search was protected.
== 1.0.1 released 2008-09-11
@@ -50,7 +55,7 @@
== 0.9.4 released 2008-09-03
* Cleaned up search methods
-* Removed reset!method for both searching and searching by conditions
+* Removed reset! method for both searching and searching by conditions
== 0.9.3 released 2008-09-02
View
@@ -330,21 +330,6 @@ Pretty nifty, huh? You can create any condition ultimately creating any SQL you
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.
-== Performance / Benchmarking
-
-I ran searchgasm through some performance tests using ruby-prof. After working on it for a little while I improved performance quite a bit. Notice the "2nd instantiation" report. This is implementing caching and skips all dynamic method creation / meta programming. It resulted in code over 50 times faster.
-
- user system total real
- 1st instantiation: 0.000000 0.000000 0.000000 ( 0.005466)
- 2nd instantiation: 0.000000 0.000000 0.000000 ( 0.000108)
- Local ordering: 0.000000 0.000000 0.000000 ( 0.000265)
- Advanced ordering: 0.000000 0.000000 0.000000 ( 0.000413)
- Local conditions: 0.000000 0.000000 0.000000 ( 0.000241)
- Advanced conditions: 0.000000 0.000000 0.000000 ( 0.000602)
- Its complicated: 0.000000 0.000000 0.000000 ( 0.001017)
-
-I also included the benchmarking file in benchmarks/benchmark.rb to see for yourself.
-
== Reporting problems / bugs
http://binarylogic.lighthouseapp.com/projects/16601-searchgasm
View
@@ -9,7 +9,7 @@ Echoe.new 'searchgasm' do |p|
p.email = 'bjohnson@binarylogic.com'
p.project = 'searchgasm'
p.summary = "Orgasmic ActiveRecord searching"
- p.description = "Makes ActiveRecord searching easier, robust, and powerful. Automatic conditions, pagination support, object based searching, and more."
+ p.description = "Object based ActiveRecord searching, ordering, pagination, and more!"
p.url = "http://github.com/binarylogic/searchgasm"
p.dependencies = %w(activerecord activesupport)
p.include_rakefile = true
@@ -1,43 +0,0 @@
-require File.dirname(__FILE__) + '/benchmark_helper.rb'
-
-times = 1
-
-Benchmark.bm(20) do |x|
- x.report("1st instantiation:") { Account.new_search }
- x.report("2nd instantiation:") { Account.new_search }
-
- # Now that we see the benefits of caching, lets cache the rest of the classes and perform the rest of the tests,
- # so that they are fair
- User.new_search
- Order.new_search
-
- x.report("Local ordering:") do
- times.times do
- Account.new_search(:order_by => :name).sanitize
- end
- end
-
- x.report("Advanced ordering:") do
- times.times do
- Account.new_search(:order_by => {:users => {:orders => :total}}).sanitize
- end
- end
-
- x.report("Local conditions:") do
- times.times do
- Account.new_search(:conditions => {:name_like => "Binary"}).sanitize
- end
- end
-
- x.report("Advanced conditions:") do
- times.times do
- Account.new_search(:conditions => {:users => {:orders => {:total_gt => 1}}}).sanitize
- end
- end
-
- x.report("Its complicated:") do
- times.times do
- Account.new_search(:conditions => {:users => {:orders => {:total_gt => 1, :created_at_after => Time.now}, :first_name_like => "Ben"}, :name_begins_with => "Awesome"}, :per_page => 20, :page => 2, :order_by => {:users => {:orders => :total}}, :order_as => "ASC").sanitize
- end
- end
-end
@@ -1,52 +0,0 @@
-require "rubygems"
-require "benchmark"
-require "ruby-prof"
-require "activerecord"
-require File.dirname(__FILE__) + '/../test/libs/acts_as_tree'
-require File.dirname(__FILE__) + '/../lib/searchgasm'
-
-ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
-
-ActiveRecord::Schema.define(:version => 1) do
- create_table :accounts do |t|
- t.datetime :created_at
- t.datetime :updated_at
- t.string :name
- t.boolean :active
- end
-
- create_table :users do |t|
- t.datetime :created_at
- t.datetime :updated_at
- t.integer :account_id
- t.integer :parent_id
- t.string :first_name
- t.string :last_name
- t.boolean :active
- t.text :bio
- end
-
- create_table :orders do |t|
- t.datetime :created_at
- t.datetime :updated_at
- t.integer :user_id
- t.float :total
- t.text :description
- t.binary :receipt
- end
-end
-
-class Account < ActiveRecord::Base
- has_many :users, :dependent => :destroy
- has_many :orders, :through => :users
-end
-
-class User < ActiveRecord::Base
- acts_as_tree
- belongs_to :account
- has_many :orders, :dependent => :destroy
-end
-
-class Order < ActiveRecord::Base
- belongs_to :user
-end
View
@@ -1,15 +0,0 @@
-require File.dirname(__FILE__) + '/benchmark_helper.rb'
-require "ruby-prof"
-
-Account.new_search
-User.new_search
-Order.new_search
-
-RubyProf.start
-
-# Put profile code here
-
-result = RubyProf.stop
-
-printer = RubyProf::FlatPrinter.new(result)
-printer.print(STDOUT, 0)
@@ -125,6 +125,12 @@ def includes
i.blank? ? nil : (i.size == 1 ? i.first : i)
end
+ def inspect
+ conditions_hash = conditions
+ conditions_hash[:protected] = true if protected?
+ conditions_hash.inspect
+ end
+
# Sanitizes the conditions down into conditions that ActiveRecord::Base.find can understand.
def sanitize
conditions = merge_conditions(*objects.collect { |object| object.sanitize })
@@ -171,8 +177,9 @@ def add_associations!
self.class.class_eval <<-"end_eval", __FILE__, __LINE__
def #{association.name}
if @#{association.name}.nil?
- @#{association.name} = #{association.class_name}.new_conditions
+ @#{association.name} = Searchgasm::Conditions::Base.create_virtual_class(#{association.class_name}).new
@#{association.name}.relationship_name = "#{association.name}"
+ @#{association.name}.protect = protect
objects << @#{association.name}
end
@#{association.name}
@@ -6,7 +6,7 @@ module Conditions
module Protection
def self.included(klass)
klass.class_eval do
- attr_accessor :protect
+ attr_reader :protect
alias_method_chain :conditions=, :protection
end
end
@@ -22,6 +22,11 @@ def conditions_with_protection=(conditions)
self.conditions_without_protection = conditions
end
+ def protect=(value)
+ associations.each { |association| association.protect = value }
+ @protect = value
+ end
+
def protect?
protect == true
end
@@ -1,6 +1,9 @@
module Searchgasm
module Helpers
module ControlTypes
+ # = Links Control Types
+ #
+ # These helpers create a group of links to help navigate through search data.
module Links
# Creates a group of links that order the data by a column or columns. All that this does is loop through the :choices option and call order_by_link and then glue it all together.
#
@@ -11,7 +14,7 @@ module Links
#
# === Options
#
- # Please look at order_by_link. All options there are applicable here and are passed onto each option.
+ # Please look at order_by_link. All options there are applicable here and are passed onto each option. Here are the options specific to this method:
#
# * <tt>:choices</tt> -- default: the models column names, the choices to loop through when calling order_by_link
def order_by_links(options = {})
@@ -32,7 +35,7 @@ def order_by_links(options = {})
#
# === Options
#
- # Please look at order_as_link. All options there are applicable here and are passed onto each option.
+ # Please look at order_as_link. All options there are applicable here and are passed onto each option. Here are the options specific to this method:
#
# * <tt>:choices</tt> -- default: ["asc", "desc"], the choices to loop through when calling order_as_link
def order_as_links(options = {})
@@ -53,7 +56,7 @@ def order_as_links(options = {})
#
# === Options
#
- # Please look at per_page_link. All options there are applicable here and are passed onto each option.
+ # Please look at per_page_link. All options there are applicable here and are passed onto each option. Here are the options specific to this method:
#
# * <tt>:choices</tt> -- default: [10, 25, 50, 100, 150, 200, nil], the choices to loop through when calling per_page_link.
def per_page_links(options = {})
@@ -88,11 +91,11 @@ def per_page_links(options = {})
#
# === Options
#
- # Please look at per_page_link. All options there are applicable here and are passed onto each option.
+ # Please look at per_page_link. All options there are applicable here and are passed onto each option. Here are the options specific to this method:
#
# * <tt>:spread</tt> -- default: 3, set to nil to show all page, this represents how many choices available on each side of the current page
- # * <tt>:prev</tt> -- default: < Prev, set to nil to omit. This is an extra link on the left side of the page links that will go to the previous page
- # * <tt>:next</tt> -- default: Next >, set to nil to omit. This is an extra link on the right side of the page links that will go to the next page
+ # * <tt>:prev</tt> -- default: "< Prev", set to nil to omit. This is an extra link on the left side of the page links that will go to the previous page
+ # * <tt>:next</tt> -- default: "Next >", set to nil to omit. This is an extra link on the right side of the page links that will go to the next page
# * <tt>:first</tt> -- default: nil, set to nil to omit. This is an extra link on thefar left side of the page links that will go to the first page
# * <tt>:last</tt> -- default: nil, set to nil to omit. This is an extra link on the far right side of the page links that will go to the last page
def page_links(options = {})
@@ -1,6 +1,9 @@
module Searchgasm
module Helpers
module ControlTypes
+ # = Remote Links Control Types
+ #
+ # These helpers use rails built in remote_function as links. They are the same thing as the Links control type, but just use rails built in remote helpers.
module RemoteLinks
# Same as order_by_links, but uses link_to_remote instead of remote.
#
@@ -1,6 +1,9 @@
module Searchgasm
module Helpers
module ControlTypes
+ # = Remote Select Control Types
+ #
+ # These helpers use rails built in remote_function as links. They are the same thing as the Select control type, but just use rails built in remote helpers.
module RemoteSelect
# Please see order_by_links. All options are the same and applicable here. The only difference is that instead of a group of links, this gets returned as a select form element that will perform the same function when the value is changed.
def remote_order_by_select(options = {})
@@ -1,6 +1,9 @@
module Searchgasm
module Helpers
module ControlTypes
+ # = Select Control Types
+ #
+ # These create <select> tags to help navigate through search data. This is here as an alternative to the Links control types.
module Select
# Please see order_by_links. All options are the same and applicable here. The only difference is that instead of a group of links, this gets returned as a select form element that will perform the same function when the value is changed.
def order_by_select(options = {})
@@ -83,8 +83,13 @@ def acting_as_filter?
# Makes using searchgasm in the console less annoying and keeps the output meaningful and useful
def inspect
- options_as_nice_string = ::ActiveRecord::Base.valid_find_options.collect { |name| "#{name}: #{send(name)}" }.join(", ")
- "#<#{klass} #{options_as_nice_string}>"
+ current_find_options = {}
+ ::ActiveRecord::Base.valid_find_options.each do |option|
+ value = send(option)
+ next if value.nil?
+ current_find_options[option] = value
+ end
+ "#<#{klass}Search #{current_find_options.inspect}>"
end
def limit=(value)

0 comments on commit e3d7cd5

Please sign in to comment.