Permalink
Browse files

Release v1.5.7

  • Loading branch information...
1 parent 585e145 commit 736788293d198281fb072cc388af5af58fecc396 @binarylogic binarylogic committed Nov 30, 2008
View
@@ -1,4 +1,9 @@
-== 1.5.6 released 2008-11-17
+== 1.5.7 released 2008-11-30
+
+* Fixed how grouping works, you can now specify "and_group" and "or_group", just like you can with conditions.
+* Specifying a join type will take priority. So "and_name_like" will ALWAYS join with AND, even is any = true for the search.
+
+== 1.5.6 released 2008-11-29
* The order conditions are set is now relevant and will be reflected in the SQL. Setting a condition first will make it first in the SQL, setting a condition last will make it last in the SQL.
* The above allows for prefixing any condition with and_ or or_. Thus letting you create somewhat more complex queries, since the order matters.
View
@@ -29,7 +29,10 @@ lib/searchlogic/condition/not_like.rb
lib/searchlogic/condition/not_nil.rb
lib/searchlogic/condition/sibling_of.rb
lib/searchlogic/condition/tree.rb
+lib/searchlogic/conditions/any_or_all.rb
lib/searchlogic/conditions/base.rb
+lib/searchlogic/conditions/groups.rb
+lib/searchlogic/conditions/magic_methods.rb
lib/searchlogic/conditions/protection.rb
lib/searchlogic/config/helpers.rb
lib/searchlogic/config/search.rb
@@ -109,7 +112,7 @@ test/condition_tests/equals_test.rb
test/condition_tests/greater_than_or_equal_to_test.rb
test/condition_tests/greater_than_test.rb
test/condition_tests/inclusive_descendant_of_test.rb
-test/condition_tests/keyswords_test.rb
+test/condition_tests/keywords_test.rb
test/condition_tests/less_than_or_equal_to_test.rb
test/condition_tests/less_than_test.rb
test/condition_tests/like_test.rb
@@ -122,7 +125,10 @@ test/condition_tests/not_have_keywords_test.rb
test/condition_tests/not_like_test.rb
test/condition_tests/not_nil_test.rb
test/condition_tests/sibling_of_test.rb
+test/conditions_tests/any_or_all_test.rb
test/conditions_tests/base_test.rb
+test/conditions_tests/groups_test.rb
+test/conditions_tests/magic_methods_test.rb
test/conditions_tests/protection_test.rb
test/config_test.rb
test/fixtures/accounts.yml
View
@@ -1,6 +1,17 @@
= Searchlogic
-Searchlogic is object based ActiveRecord searching, ordering, and pagination all in one. It's a simple, quick, all inclusive package for displaying data in your application.
+Searchlogic's goal is to keep your application free of searching clutter. It's is an ActiveRecord extension that allows you to perform simple and complex searches with a hash. Why is this great? Because GET and POST parameters are a hash. This means if you can execute a search with a hash, you can execute a search using GET or POST parameters. This makes searching in your application dead simple and clutter free:
+
+ @search = User.new_search(params[:search])
+ @users = @search.all
+
+Now think about it this way. How are resources / web services used? Through GET and POST. All of a sudden you have a resource that comes preloaded with a *very* flexible searching functionality, all with 2 lines of code.
+
+What about your interface? What is an HTML form's sole purpose? It's to send GET or POST parameters to a URI. Now you can build a form that represents a search. Meaning adding a condition to your search is as easy as adding a field to your form. That's what the @search object above is all about. You can pass that right into your form builder and build a form just like you would for an ActiveRecord object. Now you can use that handy form builder that you like you use and get rid of even more searching clutter in your views.
+
+Searching in your application has never been cleaner, more flexible, or easier.
+
+These are just the basics of Searchlogic, it can do a lot more, including pagination, ordering data, etc. All of these things are just as simple, if not simpler. Keep reading to find out everything it can do.
== Helpful links
@@ -238,16 +249,16 @@ Group with a block:
Group with a hash:
- search = User.new_search(:conditions => {
- :id_gt => 2,
- :group => [
+ search = User.new_search(:conditions => [
+ {:id_gt => 2},
+ {:group => [
{:first_name_like => "Ben"},
- {
- :last_name_like => "Johnson",
- :group => {:email_ends_with => "binarylogic.com"}
- }
- ]
- })
+ [
+ {:last_name_like => "Johnson"},
+ {:group => {:email_ends_with => "binarylogic.com"}}
+ ]
+ ]}
+ ])
# => id > 2 AND (first_name like '%Ben%') AND (last_name like '%Johnson%' AND (email like '%binarylogic.com'))
I want to end this by saying Searchlog was never meant to replace SQL, name_scopes, etc. If you need to perform complex searching there is nothing wrong with resorting to a named scope or using the traditional search methods. In fact, search logic plays nice with named_scopes anyways, so you can combine the 2 if needed:
@@ -7,7 +7,7 @@ module Condition # :nodoc:
class Base
include Shared::Utilities
- attr_accessor :any, :column, :column_for_type_cast, :column_sql, :column_sql_format, :klass, :object_name, :table_name
+ attr_accessor :column, :column_for_type_cast, :column_sql, :column_sql_format, :explicit_any, :klass, :object_name, :table_name
class_inheritable_accessor :handle_array_value, :ignore_meaningless_value, :join_arrays_with_or, :value_type
self.ignore_meaningless_value = true
@@ -61,8 +61,8 @@ def initialize(klass, options = {})
end
end
- def any? # :nodoc:
- any == true
+ def explicit_any? # :nodoc:
+ explicit_any == true
end
# Substitutes string vars with table and column name. Allows us to switch the column and table on the fly and have the condition update appropriately.
@@ -2,7 +2,7 @@ module Searchlogic
module Conditions
# = Any or All
#
- # Adds the ability to join all conditions wth "ANY" or "ALL".
+ # Adds the ability to join all conditions wth "AND" or "OR".
module AnyOrAll
# Determines if we should join the conditions with "AND" or "OR".
#
@@ -11,7 +11,7 @@ module AnyOrAll
# search.conditions.any = true # will join all conditions with "or", you can also set this to "true", "1", or "yes"
# search.conditions.any = false # will join all conditions with "and"
def any=(value)
- objects.each { |object| object.any = value }
+ (association_objects + group_objects).each { |object| object.any = value }
@any = value
end
@@ -138,13 +138,19 @@ def inspect
def sanitize
return @conditions if @conditions # return the conditions if the user set them with a string, aka sql conditions
joined_conditions = nil
- objects.each { |object| joined_conditions = merge_conditions(joined_conditions, object.class == self.class ? scope_condition(object.sanitize) : object.sanitize, :any => object.any?, :scope => false) }
+ objects.each do |object|
+ any = !object.explicit_any.nil? && (condition?(object) || group?(object)) ? object.explicit_any? : any?
+ sanitized_conditions = group?(object) ? scope_condition(object.sanitize) : object.sanitize
+ joined_conditions = merge_conditions(joined_conditions, sanitized_conditions, :any => any)
+ end
joined_conditions
end
# Allows you to set the conditions via a hash.
def conditions=(value)
case value
+ when Array
+ value.each { |v| self.conditions = v }
when Hash
remove_conditions_from_protected_assignement(value).each do |condition, condition_value|
next if [:conditions].include?(condition.to_sym) # protect sensitive methods
@@ -198,11 +204,19 @@ def reset!
private
def association_objects
- objects.select { |object| object.class < Base && object.class != self.class }
+ objects.select { |object| association?(object) }
+ end
+
+ def association?(object)
+ object.class < Base && object.class != self.class
end
def condition_objects
- objects.select { |object| object.class < Condition::Base }
+ objects.select { |object| condition?(object) }
+ end
+
+ def condition?(object)
+ object.class < Condition::Base
end
def objects
@@ -10,27 +10,62 @@ def self.included(klass)
end
# Creates a new group object to set condition off of. See examples at top of class on how to use this.
- def group(&block)
- obj = self.class.new
- yield obj if block_given?
- objects << obj
- obj
+ def group(conditions = nil, forward_arrays = false, &block)
+ if conditions.is_a?(Array) && !forward_arrays
+ group_objects = []
+ conditions.each { |condition| group_objects << group(condition, true, &block) }
+ group_objects
+ else
+ obj = self.class.new
+ obj.conditions = conditions unless conditions.nil?
+ yield obj if block_given?
+ objects << obj
+ obj
+ end
+ end
+ alias_method :group=, :group
+
+ def and_group(*args, &block)
+ obj = group(*args, &block)
+ case obj
+ when Array
+ obj.each { |o| o.group_any = false }
+ else
+ obj
+ end
end
+ alias_method :and_group=, :and_group
- # Lets you conditions to be groups or an array of conditions to be put in their own group. Each item in the array will create a new group. This is nice for using
- # groups in forms.
- def group=(value)
- case value
+ def or_group(*args, &block)
+ obj = group(*args, &block)
+ case obj
when Array
- value.each { |v| group.conditions = v }
+ obj.each { |o| o.group_any = true }
else
- group.conditions = value
+ obj
end
end
+ alias_method :or_group=, :or_group
+
+ def explicit_any=(value) # :nodoc:
+ @explicit_any = value
+ end
+
+ def explicit_any # :nodoc
+ @explicit_any
+ end
+
+ def explicit_any? # :nodoc:
+ ["true", "1", "yes"].include? explicit_any.to_s
+ end
private
def group_objects
- objects.select { |object| object.class == self.class }
+ objects.select { |object| group?(object) }
+ end
+
+ def group?(object)
+ object.class == self.class
end
end
end
@@ -223,6 +223,8 @@ def #{name}_object
def #{name}
#{name}_object.value
end
+ alias_method :and_#{name}, :#{name}
+ alias_method :or_#{name}, :#{name}
def #{name}=(value)
@conditions = nil
@@ -232,12 +234,12 @@ def #{name}=(value)
end
def and_#{name}=(value)
- #{name}_object.any = false
+ #{name}_object.explicit_any = false
self.#{name} = value
end
def or_#{name}=(value)
- #{name}_object.any = true
+ #{name}_object.explicit_any = true
self.#{name} = value
end
@@ -7,7 +7,6 @@ def merge_conditions(*conditions)
conditions.delete_if { |condition| condition.blank? }
return if conditions.blank?
return conditions.first if conditions.size == 1
- options[:scope] = true unless options.key?(:scope)
conditions_strs = []
conditions_subs = []
@@ -22,7 +21,7 @@ def merge_conditions(*conditions)
return if conditions_strs.blank?
join = options[:any] ? " OR " : " AND "
- conditions_str = options[:scope] ? "(#{conditions_strs.join(")#{join}(")})" : conditions_strs.join(join)
+ conditions_str = conditions_strs.join(join)
return conditions_str if conditions_subs.blank?
@@ -67,7 +67,7 @@ def to_a
MAJOR = 1
MINOR = 5
- TINY = 6
+ TINY = 7
# The current version as a Version instance
CURRENT = new(MAJOR, MINOR, TINY)
@@ -10,7 +10,7 @@ def test_sanitize
condition = Searchlogic::Condition::InclusiveDescendantOf.new(User)
condition.value = ben
- assert_equal ["(\"users\".\"id\" = ?) OR (\"users\".\"id\" = ? OR \"users\".\"id\" = ? OR \"users\".\"id\" = ?)", ben.id, drew.id, tren.id, jennifer.id], condition.sanitize
+ assert_equal ["\"users\".\"id\" = ? OR \"users\".\"id\" = ? OR \"users\".\"id\" = ? OR \"users\".\"id\" = ?", ben.id, drew.id, tren.id, jennifer.id], condition.sanitize
end
end
end
@@ -9,7 +9,7 @@ def test_sanitize
condition = Searchlogic::Condition::SiblingOf.new(User)
condition.value = drew
- assert_equal ["(\"users\".\"id\" != ?) AND (\"users\".\"parent_id\" = ?)", drew.id, ben.id], condition.sanitize
+ assert_equal ["\"users\".\"id\" != ? AND \"users\".\"parent_id\" = ?", drew.id, ben.id], condition.sanitize
end
end
end
@@ -73,7 +73,7 @@ def test_sanitize_with_and_or_any
conditions = Searchlogic::Cache::AccountConditions.new
conditions.name_contains = "Binary"
conditions.or_id_gt = 5
- assert conditions.id_gt_object.any?
+ assert conditions.id_gt_object.explicit_any?
assert_equal ["\"accounts\".\"name\" LIKE ? OR \"accounts\".\"id\" > ?", "%Binary%", 5], conditions.sanitize
now = Time.now
conditions.created_at_after = now
@@ -35,17 +35,20 @@ def test_group_block
def test_group_hash
now = Time.now
- conditions = Searchlogic::Cache::AccountConditions.new(
- :id_gt => 3,
- :group => [
+ conditions = Searchlogic::Cache::AccountConditions.new([
+ {:id_gt => 3},
+ {:group => [
{:name_like => "Binary"},
- {
- :id_gt => 5,
- :group => {:created_at_after => now}
- }
- ]
- )
- assert_equal ["\"accounts\".\"id\" > ? AND (\"accounts\".\"name\" LIKE ?) AND (\"accounts\".\"id\" > ? AND (\"accounts\".\"created_at\" > ?))", 3, "%Binary%", 5, now], conditions.sanitize
+ [
+ {:id_gt => 5},
+ {:group => {
+ :id_lt => 20,
+ :created_at_after => now
+ }}
+ ]
+ ]}
+ ])
+ assert_equal ["\"accounts\".\"id\" > ? AND (\"accounts\".\"name\" LIKE ?) AND (\"accounts\".\"id\" > ? AND (\"accounts\".\"id\" < ? AND \"accounts\".\"created_at\" > ?))", 3, "%Binary%", 5, 20, now], conditions.sanitize
end
end
end

0 comments on commit 7367882

Please sign in to comment.