Permalink
Browse files

Released v1.0.4 (see changelog)

  • Loading branch information...
1 parent 3848ac1 commit 2badebdb5fc2851366536a10c0db9c6bce8bbdc5 @binarylogic committed Sep 18, 2008
View
@@ -1,3 +1,8 @@
+== 1.0.4 released 2008-09-18
+
+* Fixed bugs when performing calculations and searches on has_many through relationships.
+* Instead of merging the find_options myself, I delegated that to AR's with_scope function, which already does this. Much more solid, less intrusive.
+
== 1.0.3 released 2008-09-18
* Updated inspect to show the current options for your search. Plays nicer in the console.
View
@@ -39,7 +39,6 @@ lib/searchgasm/search/conditions.rb
lib/searchgasm/search/ordering.rb
lib/searchgasm/search/pagination.rb
lib/searchgasm/search/protection.rb
-lib/searchgasm/search/scoping.rb
lib/searchgasm/search.rb
lib/searchgasm/shared/searching.rb
lib/searchgasm/shared/utilities.rb
View
@@ -147,7 +147,7 @@ Take the @search object and pass it right into form\_for or fields\_for (see abo
Using the object from above:
@search.average('id')
- @search.count
+ @search.count # ignores limit and offset
@search.maximum('id')
@search.minimum('id')
@search.sum('id')
@@ -11,6 +11,12 @@ def calculate_with_searchgasm(*args)
calculate_without_searchgasm(*args)
end
+ def total(*args)
+ options = args.extract_options!
+ searcher = searchgasm_searcher(options)
+ searcher.total
+ end
+
# This is an alias method chain. It hooks into ActiveRecord's "find" method and checks to see if Searchgasm should get involved.
def find_with_searchgasm(*args)
options = args.extract_options!
@@ -126,41 +132,36 @@ def accessible_conditions # :nodoc:
private
def sanitize_options_with_searchgasm(options = {})
return options unless Searchgasm::Search::Base.needed?(self, options)
- search = Searchgasm::Search::Base.create_virtual_class(self).new(options) # call explicitly to avoid merging the scopes into the searcher
+ search = Searchgasm::Search::Base.create_virtual_class(self).new # call explicitly to avoid merging the scopes into the searcher
search.acting_as_filter = true
+ search.options = options
search.sanitize
end
def searchgasm_conditions(options = {})
- conditions = Searchgasm::Conditions::Base.create_virtual_class(self).new(options)
- conditions.conditions = (scope(:find) || {})[:conditions]
- conditions
+ searcher = nil
+ conditions = nil
+ conditions = options.delete(:conditions) if options[:conditions].is_a?(Hash)
+
+ with_scope(:find => {:conditions => options[:conditions]}) do
+ searcher = Searchgasm::Conditions::Base.create_virtual_class(self).new(scope(:find)[:conditions])
+ searcher.conditions = conditions unless conditions.nil?
+ end
+
+ searcher
end
def searchgasm_searcher(options = {})
- search = Searchgasm::Search::Base.create_virtual_class(self).new(options)
- options_from_scope_for_searchgasm(options).each { |option, value| search.send("#{option}=", value) }
- search
- end
-
- def options_from_scope_for_searchgasm(options)
- # The goal here is to mimic how scope work. Merge what scopes would and don't what they wouldn't.
- scope = scope(:find) || {}
- scope_options = {}
- [:group, :include, :select, :readonly, :from].each { |option| scope_options[option] = scope[option] if !options.has_key?(option) && scope.has_key?(option) }
+ searcher = nil
+ conditions = nil
+ conditions = options.delete(:conditions) if options[:conditions].is_a?(Hash)
- if scope[:joins] || options[:joins]
- scope_options[:joins] = []
- scope_options[:joins] += scope[:joins].is_a?(Array) ? scope[:joins] : [scope[:joins]] unless scope[:joins].blank?
- scope_options[:joins] += options[:joins].is_a?(Array) ? options[:joins] : [options[:joins]] unless options[:joins].blank?
- scope_options[:joins] = scope_options[:joins].first if scope_options[:joins].size == 1
+ with_scope(:find => options) do
+ searcher = Searchgasm::Search::Base.create_virtual_class(self).new(scope(:find))
+ searcher.conditions = conditions unless conditions.nil?
end
- scope_options[:limit] = scope[:limit] if !options.has_key?(:per_page) && !options.has_key?(:limit) && scope.has_key?(:per_page)
- scope_options[:offset] = scope[:offset] if !options.has_key?(:page) && !options.has_key?(:offset) && scope.has_key?(:offset)
- scope_options[:order] = scope[:order] if !options.has_key?(:order_by) && !options.has_key?(:order) && scope.has_key?(:order)
- scope_options[:conditions] = scope[:conditions] if scope.has_key?(:conditions)
- scope_options
+ searcher
end
end
end
@@ -83,17 +83,6 @@ def initialize(init_conditions = {})
self.conditions = init_conditions
end
- # Setup methods for searching
- [:all, :average, :calculate, :count, :find, :first, :maximum, :minimum, :sum].each do |method|
- class_eval <<-"end_eval", __FILE__, __LINE__
- def #{method}(*args)
- self.conditions = args.extract_options!
- args << {:conditions => sanitize}
- klass.#{method}(*args)
- end
- end_eval
- end
-
# A list of includes to use when searching, includes relationships
def includes
i = []
@@ -112,11 +101,11 @@ def inspect
end
# Sanitizes the conditions down into conditions that ActiveRecord::Base.find can understand.
- def sanitize(for_method = nil)
+ def sanitize(any = false)
conditions = merge_conditions(*objects.collect { |object| object.sanitize })
return sql if conditions.blank?
merged_conditions = merge_conditions(conditions, sql)
- for_method.blank? ? merged_conditions : {:conditions => merged_conditions}
+ merged_conditions
end
# Allows you to set the conditions via a hash.
@@ -36,7 +36,7 @@ def initialize(init_options = {})
# Flag to determine if searchgasm is acting as a filter for the ActiveRecord search methods.
# The purpose of this is to determine if Config.per_page should be implemented.
def acting_as_filter=(value)
- @acting_as_filter == true
+ @acting_as_filter = value
end
# See acting_as_filter=
@@ -84,11 +84,11 @@ def options=(values)
end
# Sanitizes everything down into options ActiveRecord::Base.find can understand
- def sanitize(for_method = nil)
+ def sanitize
find_options = {}
::ActiveRecord::Base.valid_find_options.each do |find_option|
value = send(find_option)
- next if value.blank? || (for_method == :count && [:limit, :offset].include?(find_option))
+ next if value.blank?
find_options[find_option] = value
end
find_options
@@ -51,8 +51,8 @@ def include_with_conditions
includes.blank? ? nil : (includes.size == 1 ? includes.first : includes)
end
- def sanitize_with_conditions(for_method = nil) # :nodoc:
- find_options = sanitize_without_conditions(for_method)
+ def sanitize_with_conditions # :nodoc:
+ find_options = sanitize_without_conditions
if conditions_obj = find_options.delete(:conditions)
new_conditions = conditions_obj.sanitize
find_options[:conditions] = new_conditions unless new_conditions.blank?
@@ -6,15 +6,31 @@ module Shared
# this module.
module Searching
# Use these methods just like you would in ActiveRecord
- SEARCH_METHODS = [:all, :average, :calculate, :count, :find, :first, :maximum, :minimum, :sum]
+ SEARCH_METHODS = [:all, :find, :first]
+ CALCULATION_METHODS = [:average, :calculate, :count, :maximum, :minimum, :sum]
# Setup methods for searching
SEARCH_METHODS.each do |method|
class_eval <<-"end_eval", __FILE__, __LINE__
def #{method}(*args)
options = args.extract_options!
klass.send(:with_scope, :find => options) do
- args << sanitize(:#{method})
+ args << (self.class < Searchgasm::Conditions::Base ? {:conditions => sanitize} : sanitize)
+ klass.#{method}(*args)
+ end
+ end
+ end_eval
+ end
+
+ # Setup methods for calculating
+ CALCULATION_METHODS.each do |method|
+ class_eval <<-"end_eval", __FILE__, __LINE__
+ def #{method}(*args)
+ options = args.extract_options!
+ klass.send(:with_scope, :find => options) do
+ find_options = (self.class < Searchgasm::Conditions::Base ? {:conditions => sanitize} : sanitize)
+ find_options.delete(:select)
+ args << find_options
klass.#{method}(*args)
end
end
@@ -67,7 +67,7 @@ def to_a
MAJOR = 1
MINOR = 0
- TINY = 3
+ TINY = 4
# The current version as a Version instance
CURRENT = new(MAJOR, MINOR, TINY)
@@ -51,13 +51,11 @@ def test_has_many_through
search = Account.find(1).orders.new_search
assert_equal [Order.find(1)], search.all
assert_equal Order.find(1), search.first
+ assert_equal 1, search.average("id")
+ assert_equal 1, search.count
end
def test_habtm
end
-
- def test_special_options
- #order, see AR doc, etc
- end
end
@@ -80,4 +80,9 @@ def test_counting
def test_scoping
assert_equal nil, Account.send(:scope, :find)
end
+
+ def test_count
+ assert_equal 3, Account.count
+ assert_equal 3, Account.count(:limit => 1)
+ end
end
View
@@ -29,6 +29,14 @@ def test_initialize
assert_equal 10, search.limit
assert_equal true, search.readonly
end
+
+ def test_acting_as_filter
+ search = Account.new_search
+ search.acting_as_filter = true
+ assert search.acting_as_filter?
+ search.acting_as_filter = false
+ assert !search.acting_as_filter?
+ end
def test_setting_first_level_options
search = Account.new_search
@@ -131,8 +139,7 @@ def test_sanitize
search.conditions.users.id_greater_than = 2
search.page = 3
search.readonly = true
- assert_equal({:include => :users, :offset => 4, :readonly => true, :conditions => ["(\"accounts\".\"name\" LIKE ?) AND (\"users\".\"id\" > ?)", "%Binary%", 2], :limit => 2 }, search.sanitize(:all))
- assert_equal({:include => :users, :readonly => true, :conditions => ["(\"accounts\".\"name\" LIKE ?) AND (\"users\".\"id\" > ?)", "%Binary%", 2] }, search.sanitize(:count))
+ assert_equal({:include => :users, :offset => 4, :readonly => true, :conditions => ["(\"accounts\".\"name\" LIKE ?) AND (\"users\".\"id\" > ?)", "%Binary%", 2], :limit => 2 }, search.sanitize)
end
def test_scope

0 comments on commit 2badebd

Please sign in to comment.