searchlogic 1.5.4 → 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,16 @@
1
+ == 1.5.6 released 2008-11-17
2
+
3
+ * 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.
4
+ * The above allows for prefixing any condition with and_ or or_. Thus letting you create somewhat more complex queries, since the order matters.
5
+ * Added ability to group conditions to mimic parenthesis in raw SQL.
6
+ * Major clean up in the Searchlogic::Conditions name space: faster, smaller, cleaner, and modular.
7
+
8
+ == 1.5.5 released 2008-11-17
9
+
10
+ * Cleaned up class_name configuration for helpers, so that setting them to nil disables the class name
11
+ * Added page_links_div_wrapper and page_links_div_wrapper_class_name configuration option to add an wrapping div around page_links
12
+ * Added page_links_act_like_will_paginate configuration option to help with the transition from will_paginate
13
+
1
14
  == 1.5.4 released 2008-11-16
2
15
 
3
16
  * Removed subclass requirement for adding conditions in Conditions::Base
data/Manifest CHANGED
@@ -29,7 +29,10 @@ lib/searchlogic/condition/not_like.rb
29
29
  lib/searchlogic/condition/not_nil.rb
30
30
  lib/searchlogic/condition/sibling_of.rb
31
31
  lib/searchlogic/condition/tree.rb
32
+ lib/searchlogic/conditions/any_or_all.rb
32
33
  lib/searchlogic/conditions/base.rb
34
+ lib/searchlogic/conditions/groups.rb
35
+ lib/searchlogic/conditions/magic_methods.rb
33
36
  lib/searchlogic/conditions/protection.rb
34
37
  lib/searchlogic/config/helpers.rb
35
38
  lib/searchlogic/config/search.rb
@@ -109,7 +112,7 @@ test/condition_tests/equals_test.rb
109
112
  test/condition_tests/greater_than_or_equal_to_test.rb
110
113
  test/condition_tests/greater_than_test.rb
111
114
  test/condition_tests/inclusive_descendant_of_test.rb
112
- test/condition_tests/keyswords_test.rb
115
+ test/condition_tests/keywords_test.rb
113
116
  test/condition_tests/less_than_or_equal_to_test.rb
114
117
  test/condition_tests/less_than_test.rb
115
118
  test/condition_tests/like_test.rb
@@ -122,7 +125,10 @@ test/condition_tests/not_have_keywords_test.rb
122
125
  test/condition_tests/not_like_test.rb
123
126
  test/condition_tests/not_nil_test.rb
124
127
  test/condition_tests/sibling_of_test.rb
128
+ test/conditions_tests/any_or_all_test.rb
125
129
  test/conditions_tests/base_test.rb
130
+ test/conditions_tests/groups_test.rb
131
+ test/conditions_tests/magic_methods_test.rb
126
132
  test/conditions_tests/protection_test.rb
127
133
  test/config_test.rb
128
134
  test/fixtures/accounts.yml
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = Searchlogic
2
2
 
3
- Searchlogic is object based ActiveRecord searching, ordering, and pagination all in one.
3
+ 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.
4
4
 
5
5
  == Helpful links
6
6
 
@@ -13,12 +13,12 @@ Searchlogic is object based ActiveRecord searching, ordering, and pagination all
13
13
 
14
14
  sudo gem install searchlogic
15
15
 
16
- For rails
17
-
18
- $ cd vendor/plugins
19
- $ sudo gem unpack searchlogic
16
+ For rails, as a gem (recommended)
17
+
18
+ # config/environment.rb
19
+ config.gem "searchlogic"
20
20
 
21
- Or as a plugin
21
+ Or as a plugin (for older versions of rails)
22
22
 
23
23
  script/plugin install git://github.com/binarylogic/searchlogic.git
24
24
 
@@ -178,17 +178,84 @@ Any of the options used in the above example can be used in these, but for the s
178
178
  search.per_page = 20
179
179
  search.all
180
180
 
181
+ search = User.new_search(:conditions => {:age_gt => 18}) do |s|
182
+ s.conditions.first_name_contains = "Ben"
183
+ s.per_page = 20
184
+ end
185
+ search.all
186
+
181
187
  == Match ANY or ALL of the conditions
182
188
 
183
189
  As you saw above, the nice thing about Searchlogic is it's integration with forms. I designed the "any" option so that forms can set this as well, just like a condition.
184
190
 
185
- @search = User.new_search(:conditions => {:age_gt => 18}) do |search|
186
- search.conditions.first_name_contains = "Ben"
187
- search.conditions.any = true # can set this to "true" or "1" or "yes"
188
- search.all # will join all conditions with "or" instead of "and"
189
- end
191
+ @search = User.new_search(:conditions => {:age_gt => 18})
192
+ @search.conditions.first_name_contains = "Ben"
193
+ @search.conditions.any = true # can set this to "true" or "1" or "yes"
194
+ @search.all # will join all conditions with "or" instead of "and"
190
195
  # ... all operations above are available
191
196
 
197
+ What if you want to mix and match?
198
+
199
+ @search = User.new_search(:conditions => {:age_gt => 18})
200
+ @search.conditions.or_first_name_contains = "Ben"
201
+ @search.conditions.or_last_name_contains = "Johnson"
202
+ @search.conditions.and_id_gt = 5 # the and_ is optional, calling just id_gt is the same thing
203
+ @search.all # will join conditions in the orders they were set with their specified join condition
204
+ # => age > 17 OR first_name like '%Ben%' OR lsat_name like '%Johnson%' AND id > 5
205
+
206
+ The order the conditions is set is relevant, as the SQL will be built in the same order.
207
+
208
+ == Grouping conditions
209
+
210
+ In more complex searching situations you might want to group conditions. Just like you use parenthesis in raw SQL. Searchlogic's "group" function is basically a way to implement parenthesis in your conditions. It's simple:
211
+
212
+ Group off an object:
213
+
214
+ search = User.new_search
215
+ search.id_gt = 2
216
+ group1 = search.conditions.group
217
+ group.first_name_like = "Ben"
218
+ group2 = search.conditions.group
219
+ group.last_name_like = "Johnson"
220
+ group21 = group2.group
221
+ group21.email_ends_with = "binarylogic.com"
222
+ # => id > 2 AND (first_name like '%Ben%') AND (last_name like '%Johnson%' AND (email like '%binarylogic.com'))
223
+
224
+ Group with a block:
225
+
226
+ search = User.new_search
227
+ search.id_gt = 2
228
+ search.conditions.group do |group|
229
+ group.first_name_like = "Ben"
230
+ end
231
+ search.conditions.group do |group|
232
+ group.last_name_like = "Johnson"
233
+ group.group do |sub_group|
234
+ sub_group.email_ends_with = "binarylogic.com"
235
+ end
236
+ end
237
+ # => id > 2 AND (first_name like '%Ben%') AND (last_name like '%Johnson%' AND (email like '%binarylogic.com'))
238
+
239
+ Group with a hash:
240
+
241
+ search = User.new_search(:conditions => {
242
+ :id_gt => 2,
243
+ :group => [
244
+ {:first_name_like => "Ben"},
245
+ {
246
+ :last_name_like => "Johnson",
247
+ :group => {:email_ends_with => "binarylogic.com"}
248
+ }
249
+ ]
250
+ })
251
+ # => id > 2 AND (first_name like '%Ben%') AND (last_name like '%Johnson%' AND (email like '%binarylogic.com'))
252
+
253
+ 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:
254
+
255
+ @search = User.my_awesome_scope.another_cool_scope.new_search
256
+
257
+ The only reason I added this was to allow searchlogic to extend a little further into those advanced searches. If you need to scope conditions by using parenthesis, etc. you should resort to named_scopes or the traditional search method.
258
+
192
259
  == Scoped searching
193
260
 
194
261
  @current_user.orders.find(:all, :conditions => {:total_lte => 500})
data/Rakefile CHANGED
@@ -1,15 +1,19 @@
1
1
  require 'rubygems'
2
- require 'echoe'
3
-
4
2
  require File.dirname(__FILE__) << "/lib/searchlogic/version"
5
3
 
6
- Echoe.new 'searchlogic' do |p|
7
- p.version = Searchlogic::Version::STRING
8
- p.author = "Ben Johnson of Binary Logic"
9
- p.email = 'bjohnson@binarylogic.com'
10
- p.project = 'searchlogic'
11
- p.summary = "Object based ActiveRecord searching, ordering, pagination, and more!"
12
- p.url = "http://github.com/binarylogic/searchlogic"
13
- p.dependencies = %w(activerecord activesupport)
14
- p.include_rakefile = true
4
+ begin
5
+ require 'echoe'
6
+
7
+ Echoe.new 'searchlogic' do |p|
8
+ p.version = Searchlogic::Version::STRING
9
+ p.author = "Ben Johnson of Binary Logic"
10
+ p.email = 'bjohnson@binarylogic.com'
11
+ p.project = 'searchlogic'
12
+ p.summary = "Object based ActiveRecord searching, ordering, pagination, and more!"
13
+ p.url = "http://github.com/binarylogic/searchlogic"
14
+ p.dependencies = %w(activerecord activesupport)
15
+ end
16
+ rescue LoadError => boom
17
+ puts "You are missing a dependency required for meta-operations on this gem."
18
+ puts "#{boom.to_s.capitalize}."
15
19
  end
@@ -7,7 +7,7 @@ module Searchlogic
7
7
  class Base
8
8
  include Shared::Utilities
9
9
 
10
- attr_accessor :column, :column_for_type_cast, :column_sql, :column_sql_format, :klass, :table_name
10
+ attr_accessor :any, :column, :column_for_type_cast, :column_sql, :column_sql_format, :klass, :object_name, :table_name
11
11
  class_inheritable_accessor :handle_array_value, :ignore_meaningless_value, :join_arrays_with_or, :value_type
12
12
  self.ignore_meaningless_value = true
13
13
 
@@ -61,6 +61,10 @@ module Searchlogic
61
61
  end
62
62
  end
63
63
 
64
+ def any? # :nodoc:
65
+ any == true
66
+ end
67
+
64
68
  # 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.
65
69
  # The table name could be variable depending on the condition. Take STI and more than one child model is used in the condition, the first gets the parent table name, the rest get aliases.
66
70
  def column_sql
@@ -5,7 +5,7 @@ module Searchlogic
5
5
  self.join_arrays_with_or = true
6
6
 
7
7
  BLACKLISTED_WORDS = ('a'..'z').to_a + ["about", "an", "are", "as", "at", "be", "by", "com", "de", "en", "for", "from", "how", "in", "is", "it", "la", "of", "on", "or", "that", "the", "the", "this", "to", "und", "was", "what", "when", "where", "who", "will", "with", "www"] # from ranks.nl
8
- FOREIGN_CHARACTERS = 'àáâãäåßéèêëìíîïñòóôõöùúûüýÿ'
8
+ ALLOWED_CHARACTERS = 'àáâãäåßéèêëìíîïñòóôõöùúûüýÿ\-_\.@'
9
9
 
10
10
  class << self
11
11
  def condition_names_for_column
@@ -35,7 +35,7 @@ module Searchlogic
35
35
  def replace_non_alnum_characters!(search_parts)
36
36
  search_parts.each do |word|
37
37
  word.downcase!
38
- word.gsub!(/[^[:alnum:]#{FOREIGN_CHARACTERS}]/, '')
38
+ word.gsub!(/[^[:alnum:]#{ALLOWED_CHARACTERS}]/, '')
39
39
  end
40
40
  end
41
41
 
@@ -0,0 +1,42 @@
1
+ module Searchlogic
2
+ module Conditions
3
+ # = Any or All
4
+ #
5
+ # Adds the ability to join all conditions wth "ANY" or "ALL".
6
+ module AnyOrAll
7
+ # Determines if we should join the conditions with "AND" or "OR".
8
+ #
9
+ # === Examples
10
+ #
11
+ # search.conditions.any = true # will join all conditions with "or", you can also set this to "true", "1", or "yes"
12
+ # search.conditions.any = false # will join all conditions with "and"
13
+ def any=(value)
14
+ objects.each { |object| object.any = value }
15
+ @any = value
16
+ end
17
+
18
+ def any # :nodoc:
19
+ any?
20
+ end
21
+
22
+ # Convenience method for determining if we should join the conditions with "AND" or "OR".
23
+ def any?
24
+ ["true", "1", "yes"].include? @any.to_s
25
+ end
26
+
27
+ # Sets the conditions to be searched by "or"
28
+ def any!
29
+ self.any = true
30
+ end
31
+
32
+ def all? # :nodoc:
33
+ !any?
34
+ end
35
+
36
+ # Sets the conditions to be searched by "and"
37
+ def all!
38
+ self.any = false
39
+ end
40
+ end
41
+ end
42
+ end