searchlogic 1.6.2 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,13 @@
1
+ == 1.6.3 released 2008-12-13
2
+
3
+ * Added in avg, count, and sum modifiers for SQLite and Postgres.
4
+ * Added ne for not_equal condition.
5
+ * Ignore :include option for calculations since we don't need it and AR throws an error for polymorphic relationships.
6
+ * Removed sum and count since they can not be in the WHERE statement, but must be in the HAVING statement
7
+ * Added in auto joins for groups so that the joins don't have to be manually specified.
8
+ * Use first column in column_names as the default column for calculations, since a column is required when using DISTINCT and some tables can have more than one primary key.
9
+ * On associations see what the first conditions "any" status is to determine if to join with "ANY" or "AND"
10
+
1
11
  == 1.6.2 released 2008-12-13
2
12
 
3
13
  * Remove duplicate joins at a lower level for a cleaner and less brittle approach.
@@ -130,7 +130,7 @@ module Searchlogic
130
130
  sql_parts.each do |part|
131
131
  part = part.strip
132
132
  if is_join_statement
133
- if !cleaned_parts.include?(part)
133
+ if !includes_join?(cleaned_parts, part)
134
134
  cleaned_parts << part
135
135
  else
136
136
  cleaned_parts.pop
@@ -145,6 +145,16 @@ module Searchlogic
145
145
  sql
146
146
  end
147
147
 
148
+ def includes_join?(cleaned_parts, part)
149
+ cleaned_parts.each do |cleaned_part|
150
+ a = cleaned_part.gsub("`", "")
151
+ b = part.gsub("`", "")
152
+ return true if a == b
153
+ return true if a == b.gsub(/([a-z\._]*) = ([a-z\._]*)/, '\2 = \1')
154
+ end
155
+ false
156
+ end
157
+
148
158
  def filter_options_with_searchlogic(options = {}, searching = true)
149
159
  return options unless Searchlogic::Search::Base.needed?(self, options)
150
160
  search = Searchlogic::Search::Base.create_virtual_class(self).new # call explicitly to avoid merging the scopes into the search
@@ -109,10 +109,6 @@ module Searchlogic
109
109
  "COT(#{column_name})"
110
110
  end
111
111
 
112
- def count_sql(column_name)
113
- "COUNT(#{colun_name})"
114
- end
115
-
116
112
  def degrees_sql(column_name)
117
113
  "DEGREES(#{column_name})"
118
114
  end
@@ -169,10 +165,6 @@ module Searchlogic
169
165
  "SQRT(#{column_name})"
170
166
  end
171
167
 
172
- def sum_sql(column_name)
173
- "SUM(#{column_name})"
174
- end
175
-
176
168
  def tan_sql(column_name)
177
169
  "TAN(#{column_name})"
178
170
  end
@@ -93,6 +93,10 @@ module Searchlogic
93
93
  "atan(#{column_name})"
94
94
  end
95
95
 
96
+ def avg_sql(column_name)
97
+ "AVG(#{column_name})"
98
+ end
99
+
96
100
  def ceil_sql(column_name)
97
101
  "ceil(#{column_name})"
98
102
  end
@@ -47,6 +47,11 @@ module Searchlogic
47
47
  "(strftime('%Y', #{column_name}) * 1)"
48
48
  end
49
49
 
50
+ # Number functions
51
+ def avg_sql(column_name)
52
+ "AVG(#{column_name})"
53
+ end
54
+
50
55
  # String functions
51
56
  def lower_sql(column_name)
52
57
  "lower(#{column_name})"
@@ -6,7 +6,7 @@ module Searchlogic
6
6
 
7
7
  class << self
8
8
  def condition_names_for_column
9
- super + ["does_not_equal", "not_equal", "is_not", "not"]
9
+ super + ["does_not_equal", "not_equal", "is_not", "not", "ne"]
10
10
  end
11
11
  end
12
12
 
@@ -16,7 +16,7 @@ module Searchlogic
16
16
  end
17
17
 
18
18
  def any # :nodoc:
19
- any?
19
+ @any
20
20
  end
21
21
 
22
22
  # Convenience method for determining if we should join the conditions with "AND" or "OR".
@@ -139,9 +139,8 @@ module Searchlogic
139
139
  return @conditions if @conditions # return the conditions if the user set them with a string, aka sql conditions
140
140
  joined_conditions = nil
141
141
  objects.each do |object|
142
- any = !object.explicit_any.nil? && (condition?(object) || group?(object)) ? object.explicit_any? : any?
143
142
  sanitized_conditions = group?(object) ? scope_condition(object.sanitize) : object.sanitize
144
- joined_conditions = merge_conditions(joined_conditions, sanitized_conditions, :any => any)
143
+ joined_conditions = merge_conditions(joined_conditions, sanitized_conditions, :any => join_object_with_any?(object))
145
144
  end
146
145
  joined_conditions
147
146
  end
@@ -223,6 +222,15 @@ module Searchlogic
223
222
  @objects ||= []
224
223
  end
225
224
 
225
+ def join_object_with_any?(object)
226
+ return any? if !any.nil?
227
+ if condition?(object) || group?(object)
228
+ object.explicit_any?
229
+ elsif association?(object)
230
+ object.send(:join_object_with_any?, object.send(:objects).first)
231
+ end
232
+ end
233
+
226
234
  def remove_conditions_from_protected_assignement(conditions)
227
235
  return conditions if klass.accessible_conditions.nil? && klass.protected_conditions.nil?
228
236
  if klass.accessible_conditions
@@ -6,9 +6,25 @@ module Searchlogic
6
6
  module Groups
7
7
  def self.included(klass)
8
8
  klass.class_eval do
9
+ alias_method_chain :auto_joins, :groups
9
10
  end
10
11
  end
11
12
 
13
+ def auto_joins_with_groups
14
+ auto_joins = auto_joins_without_groups
15
+ auto_joins = auto_joins.is_a?(Array) ? auto_joins : [auto_joins].compact
16
+
17
+ group_objects.each do |group|
18
+ next if group.conditions.blank?
19
+ group_joins = group.auto_joins
20
+ next if group_joins.blank?
21
+ group_joins = group_joins.is_a?(Array) ? group_joins : [group_joins]
22
+ auto_joins += group_joins
23
+ end
24
+
25
+ auto_joins.blank? ? nil : (auto_joins.size == 1 ? auto_joins.first : auto_joins)
26
+ end
27
+
12
28
  # Creates a new group object to set condition off of. See examples at top of class on how to use this.
13
29
  def group(conditions = nil, &block)
14
30
  obj = self.class.new
@@ -11,7 +11,7 @@ module Searchlogic
11
11
  class << self
12
12
  # Which hidden fields to automatically include when creating a form with a Searchlogic object. See Searchlogic::Helpers::Form for more info.
13
13
  #
14
- # * <tt>Default:</tt> [:order_by, :order_as, :per_page]
14
+ # * <tt>Default:</tt> [:order_by, :order_as, :priority_order_by, :priority_order_as, :per_page]
15
15
  # * <tt>Accepts:</tt> Array, nil, false
16
16
  def hidden_fields
17
17
  @hidden_fields ||= (Searchlogic::Search::Base::SPECIAL_FIND_OPTIONS - [:page, :priority_order])
@@ -121,16 +121,16 @@ module Searchlogic
121
121
  return unless search_object.is_a?(Search::Base)
122
122
  name = args.first
123
123
  options = args.extract_options!
124
- options
124
+ html = ""
125
125
  search_options[:hidden_fields].each do |field|
126
- html = hidden_field(name, field, :object => search_object, :id => "#{name}_#{field}_#{options.object_id}", :value => (field == :order_by ? searchlogic_base64_value(search_object.order_by) : search_object.send(field)))
126
+ html << hidden_field(name, field, :object => search_object, :id => "#{name}_#{field}_#{options.object_id}", :value => (field == :order_by ? searchlogic_base64_value(search_object.order_by) : search_object.send(field)))
127
+ end
127
128
 
128
- # For edge rails and older version compatibility, passing a binding to concat was deprecated
129
- begin
130
- concat(html)
131
- rescue ArgumentError, NameError
132
- concat(html, block.binding)
133
- end
129
+ # For edge rails and older version compatibility, passing a binding to concat was deprecated
130
+ begin
131
+ concat(content_tag(:div, html, :style => 'margin:0;padding:0'))
132
+ rescue ArgumentError, NameError
133
+ concat(content_tag(:div, html, :style => 'margin:0;padding:0'), block.binding)
134
134
  end
135
135
  args << options
136
136
  end
@@ -11,7 +11,7 @@ module Searchlogic #:nodoc:
11
11
  AR_FIND_OPTIONS = ::ActiveRecord::Base.valid_find_options
12
12
 
13
13
  # Options ActiveRecord allows when performing calculations
14
- AR_CALCULATIONS_OPTIONS = (::ActiveRecord::Base.valid_calculations_options - [:select, :limit, :offset, :order, :group])
14
+ AR_CALCULATIONS_OPTIONS = (::ActiveRecord::Base.valid_calculations_options - [:select, :limit, :offset, :order, :group, :include])
15
15
 
16
16
  AR_OPTIONS = (AR_FIND_OPTIONS + AR_CALCULATIONS_OPTIONS).uniq
17
17
 
@@ -120,8 +120,8 @@ module Searchlogic #:nodoc:
120
120
  end
121
121
 
122
122
  def select
123
- return @select if klass.connection.adapter_name == "PostgreSQL" # Postgres needs ALL of the column names here, including association columns, etc. Which is very strange, so I disable this feature for Postgres all together.
124
- @select ||= "DISTINCT #{klass.connection.quote_table_name(klass.table_name)}.*" if !joins.blank? && Config.search.remove_duplicates?
123
+ @select ||= "DISTINCT #{klass.connection.quote_table_name(klass.table_name)}.*" if !joins.blank? && Config.search.remove_duplicates? && klass.connection.adapter_name != "PostgreSQL"
124
+ @select
125
125
  end
126
126
 
127
127
  def scope
@@ -18,7 +18,7 @@ module Searchlogic
18
18
  options = sanitize(#{SEARCH_METHODS.include?(method)})
19
19
  if #{CALCULATION_METHODS.include?(method)}
20
20
  options[:distinct] = true if #{method == :count} && !joins.blank? && Config.search.remove_duplicates?
21
- args[0] = klass.primary_key if [nil, :all].include?(args[0])
21
+ args[0] = klass.column_names.first if [nil, :all].include?(args[0])
22
22
  end
23
23
  args << options
24
24
  results = klass.#{method}(*args)
@@ -67,7 +67,7 @@ module Searchlogic
67
67
 
68
68
  MAJOR = 1
69
69
  MINOR = 6
70
- TINY = 2
70
+ TINY = 3
71
71
 
72
72
  # The current version as a Version instance
73
73
  CURRENT = new(MAJOR, MINOR, TINY)
data/searchlogic.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{searchlogic}
5
- s.version = "1.6.2"
5
+ s.version = "1.6.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Ben Johnson of Binary Logic"]
9
- s.date = %q{2008-12-13}
9
+ s.date = %q{2009-02-02}
10
10
  s.description = %q{Object based ActiveRecord searching, ordering, pagination, and more!}
11
11
  s.email = %q{bjohnson@binarylogic.com}
12
12
  s.extra_rdoc_files = ["CHANGELOG.rdoc", "lib/searchlogic/active_record/associations.rb", "lib/searchlogic/active_record/base.rb", "lib/searchlogic/active_record/connection_adapters/mysql_adapter.rb", "lib/searchlogic/active_record/connection_adapters/postgresql_adapter.rb", "lib/searchlogic/active_record/connection_adapters/sqlite_adapter.rb", "lib/searchlogic/condition/base.rb", "lib/searchlogic/condition/begins_with.rb", "lib/searchlogic/condition/blank.rb", "lib/searchlogic/condition/child_of.rb", "lib/searchlogic/condition/descendant_of.rb", "lib/searchlogic/condition/ends_with.rb", "lib/searchlogic/condition/equals.rb", "lib/searchlogic/condition/greater_than.rb", "lib/searchlogic/condition/greater_than_or_equal_to.rb", "lib/searchlogic/condition/inclusive_descendant_of.rb", "lib/searchlogic/condition/keywords.rb", "lib/searchlogic/condition/less_than.rb", "lib/searchlogic/condition/less_than_or_equal_to.rb", "lib/searchlogic/condition/like.rb", "lib/searchlogic/condition/nested_set.rb", "lib/searchlogic/condition/nil.rb", "lib/searchlogic/condition/not_begin_with.rb", "lib/searchlogic/condition/not_blank.rb", "lib/searchlogic/condition/not_end_with.rb", "lib/searchlogic/condition/not_equal.rb", "lib/searchlogic/condition/not_have_keywords.rb", "lib/searchlogic/condition/not_like.rb", "lib/searchlogic/condition/not_nil.rb", "lib/searchlogic/condition/sibling_of.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/multiparameter_attributes.rb", "lib/searchlogic/conditions/protection.rb", "lib/searchlogic/config/helpers.rb", "lib/searchlogic/config/search.rb", "lib/searchlogic/config.rb", "lib/searchlogic/core_ext/hash.rb", "lib/searchlogic/core_ext/object.rb", "lib/searchlogic/helpers/control_types/link.rb", "lib/searchlogic/helpers/control_types/links.rb", "lib/searchlogic/helpers/control_types/remote_link.rb", "lib/searchlogic/helpers/control_types/remote_links.rb", "lib/searchlogic/helpers/control_types/remote_select.rb", "lib/searchlogic/helpers/control_types/select.rb", "lib/searchlogic/helpers/form.rb", "lib/searchlogic/helpers/utilities.rb", "lib/searchlogic/modifiers/absolute.rb", "lib/searchlogic/modifiers/acos.rb", "lib/searchlogic/modifiers/asin.rb", "lib/searchlogic/modifiers/atan.rb", "lib/searchlogic/modifiers/avg.rb", "lib/searchlogic/modifiers/base.rb", "lib/searchlogic/modifiers/ceil.rb", "lib/searchlogic/modifiers/char_length.rb", "lib/searchlogic/modifiers/cos.rb", "lib/searchlogic/modifiers/cot.rb", "lib/searchlogic/modifiers/count.rb", "lib/searchlogic/modifiers/day_of_month.rb", "lib/searchlogic/modifiers/day_of_week.rb", "lib/searchlogic/modifiers/day_of_year.rb", "lib/searchlogic/modifiers/degrees.rb", "lib/searchlogic/modifiers/exp.rb", "lib/searchlogic/modifiers/floor.rb", "lib/searchlogic/modifiers/hex.rb", "lib/searchlogic/modifiers/hour.rb", "lib/searchlogic/modifiers/log.rb", "lib/searchlogic/modifiers/log10.rb", "lib/searchlogic/modifiers/log2.rb", "lib/searchlogic/modifiers/lower.rb", "lib/searchlogic/modifiers/ltrim.rb", "lib/searchlogic/modifiers/md5.rb", "lib/searchlogic/modifiers/microseconds.rb", "lib/searchlogic/modifiers/milliseconds.rb", "lib/searchlogic/modifiers/minute.rb", "lib/searchlogic/modifiers/month.rb", "lib/searchlogic/modifiers/octal.rb", "lib/searchlogic/modifiers/radians.rb", "lib/searchlogic/modifiers/round.rb", "lib/searchlogic/modifiers/rtrim.rb", "lib/searchlogic/modifiers/second.rb", "lib/searchlogic/modifiers/sign.rb", "lib/searchlogic/modifiers/sin.rb", "lib/searchlogic/modifiers/square_root.rb", "lib/searchlogic/modifiers/sum.rb", "lib/searchlogic/modifiers/tan.rb", "lib/searchlogic/modifiers/trim.rb", "lib/searchlogic/modifiers/upper.rb", "lib/searchlogic/modifiers/week.rb", "lib/searchlogic/modifiers/year.rb", "lib/searchlogic/search/base.rb", "lib/searchlogic/search/conditions.rb", "lib/searchlogic/search/ordering.rb", "lib/searchlogic/search/pagination.rb", "lib/searchlogic/search/protection.rb", "lib/searchlogic/search/searching.rb", "lib/searchlogic/shared/utilities.rb", "lib/searchlogic/shared/virtual_classes.rb", "lib/searchlogic/version.rb", "lib/searchlogic.rb", "README.rdoc", "TODO.rdoc"]
@@ -104,5 +104,12 @@ module ActiveRecordTests
104
104
  def test_includes
105
105
  assert_nothing_raised { Account.all(:conditions => {:users => {:first_name_like => "Ben"}}, :include => :users) }
106
106
  end
107
+
108
+ def test_remove_duplicate_joins
109
+ query = "SELECT DISTINCT `ticket_groups`.* FROM `ticket_groups` INNER JOIN tickets ON ticket_groups.id = tickets.ticket_group_id LEFT OUTER JOIN `tickets` ON tickets.ticket_group_id = ticket_groups.id WHERE (`tickets`.`id` = 2) AND ((`tickets`.event_id = 810802042)) LIMIT 20"
110
+ cleaned_query = ActiveRecord::Base.send(:remove_duplicate_joins, query)
111
+ expected_query = "SELECT DISTINCT `ticket_groups`.* FROM `ticket_groups` INNER JOIN tickets ON ticket_groups.id = tickets.ticket_group_id WHERE (`tickets`.`id` = 2) AND ((`tickets`.event_id = 810802042)) LIMIT 20"
112
+ assert_equal expected_query, cleaned_query
113
+ end
107
114
  end
108
115
  end
@@ -174,5 +174,12 @@ module ConditionsTests
174
174
  conditions.reset!
175
175
  assert_equal [], conditions.send(:objects)
176
176
  end
177
+
178
+ def test_join_with_or_with_association
179
+ conditions = Searchlogic::Cache::AccountConditions.new
180
+ conditions.name_ends_with = "Binary"
181
+ conditions.users.or_first_name_like = "whatever"
182
+ assert_equal ["\"accounts\".\"name\" LIKE ? OR \"users\".\"first_name\" LIKE ?", "%Binary", "%whatever%"], conditions.sanitize
183
+ end
177
184
  end
178
185
  end
@@ -48,5 +48,21 @@ module ConditionsTests
48
48
  ])
49
49
  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
50
50
  end
51
+
52
+ def test_auto_joins
53
+ conditions = Searchlogic::Cache::AccountConditions.new
54
+ conditions.group do |g|
55
+ g.users.first_name_like = "Ben"
56
+ end
57
+ assert_equal :users, conditions.auto_joins
58
+
59
+ search = Searchlogic::Cache::AccountSearch.new
60
+ search.conditions.users.first_name_like = "Ben"
61
+ search.conditions.group do |g|
62
+ g.users.orders.id_gt = 5
63
+ end
64
+ assert_equal [:users, {:users => :orders}], search.conditions.auto_joins
65
+ assert_nothing_raised { search.all }
66
+ end
51
67
  end
52
68
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchlogic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.2
4
+ version: 1.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Johnson of Binary Logic
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-13 00:00:00 -05:00
12
+ date: 2009-02-02 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency