searchlogic 1.6.2 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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