searchgasm 1.3.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,14 @@
1
+ == 1.3.2 released 2008-10-03
2
+
3
+ * Fixed condition to type cast all values in an array
4
+ * Fixed bug to properly set the type for the type cast column
5
+ * Fixed bug to allow conditions on local columns
6
+ * Apparently ActiveRecord 2.2 doesnt remove duplicates on all joins, need to enforce this for ALL versions of ActiveRecord
7
+ * Fixed bug when passing a symbol as the SQL type for condition return types
8
+ * Moved duplicate removal to only apply when searching or calculating from a search object. Anything done in a normal ActiveRecord method should remain untouched and let ActiveRecord handle it. Just like in ActiveRecord if you do a User.all search and pass some :joins, you might get duplicate records. Searchgasm should not change that behavior, unless called from a searchgasm object.
9
+ * Discard meaningless array values when setting a condition.
10
+ * Delete blank strings from mass assignments on conditions.
11
+
1
12
  == 1.3.1 released 2008-10-02
2
13
 
3
14
  * Fixed bug when requiring a connection adapter that is not present
@@ -11,7 +11,6 @@ module Searchgasm
11
11
  def calculate_with_searchgasm(*args)
12
12
  options = args.extract_options!
13
13
  options = filter_options_with_searchgasm(options, false)
14
- args[1] = primary_key if options[:distinct] && [nil, :all].include?(args[1]) # quick fix for adding a column name if distinct is true and no specific column is provided
15
14
  args << options
16
15
  calculate_without_searchgasm(*args)
17
16
  end
@@ -44,8 +44,8 @@ module Searchgasm
44
44
 
45
45
  if column_obj
46
46
  self.column = column_obj.class < ::ActiveRecord::ConnectionAdapters::Column ? column_obj : klass.columns_hash[column_obj.to_s]
47
- column_type ||= column.type
48
- self.column_for_type_cast = column.class.new(column.name, column.default.to_s, self.class.value_type.to_s || column_type.to_s, column.null)
47
+ type = (!self.class.value_type.blank? && self.class.value_type.to_s) || (!column_type.blank? && column_type.to_s) || column.sql_type
48
+ self.column_for_type_cast = column.class.new(column.name, column.default.to_s, type, column.null)
49
49
  self.column_sql = column_sql || "#{klass.connection.quote_table_name(klass.table_name)}.#{klass.connection.quote_column_name(column.name)}"
50
50
  end
51
51
  end
@@ -60,13 +60,9 @@ module Searchgasm
60
60
  @explicitly_set_value == true
61
61
  end
62
62
 
63
- def meaningless_value?
64
- !explicitly_set_value? || (self.class.ignore_meaningless_value? && meaningless?(@value))
65
- end
66
-
67
63
  # You should refrain from overwriting this method, it performs various tasks before callign your to_conditions method, allowing you to keep to_conditions simple.
68
64
  def sanitize(alt_value = nil) # :nodoc:
69
- return if meaningless_value?
65
+ return if value_is_meaningless?
70
66
  v = alt_value || value
71
67
  if v.is_a?(Array) && !self.class.handle_array_value?
72
68
  merge_conditions(*v.collect { |i| sanitize(i) })
@@ -78,13 +74,7 @@ module Searchgasm
78
74
 
79
75
  # The value for the condition
80
76
  def value
81
- return @casted_value if @casted_value
82
-
83
- if !column_for_type_cast || meaningless_value?
84
- @casted_value = @value
85
- else
86
- @casted_value = @value.is_a?(String) ? column_for_type_cast.type_cast(@value) : @value
87
- end
77
+ @casted_value ||= type_cast_value(@value)
88
78
  end
89
79
 
90
80
  # Sets the value for the condition
@@ -94,10 +84,19 @@ module Searchgasm
94
84
  @value = v
95
85
  end
96
86
 
87
+ def value_is_meaningless? # :nodoc:
88
+ meaningless?(@value)
89
+ end
90
+
97
91
  private
98
92
  def meaningless?(v)
99
- return false if v == false
100
- v.blank?
93
+ case v
94
+ when Array
95
+ v.each { |i| return false unless meaningless?(i) }
96
+ true
97
+ else
98
+ !explicitly_set_value? || (self.class.ignore_meaningless_value? && v != false && v.blank?)
99
+ end
101
100
  end
102
101
 
103
102
  def meaningful?(v)
@@ -115,6 +114,17 @@ module Searchgasm
115
114
  def quoted_table_name
116
115
  quote_table_name(klass.table_name)
117
116
  end
117
+
118
+ def type_cast_value(v)
119
+ case v
120
+ when Array
121
+ v.collect { |i| type_cast_value(i) }.compact
122
+ else
123
+ return if meaningless?(v)
124
+ return v if !column_for_type_cast || !v.is_a?(String)
125
+ column_for_type_cast.type_cast(v)
126
+ end
127
+ end
118
128
  end
119
129
  end
120
130
  end
@@ -10,7 +10,6 @@ module Searchgasm
10
10
  end
11
11
 
12
12
  def to_conditions(value)
13
- # Some databases handle null values differently, let AR handle this
14
13
  if value == true
15
14
  "#{column_sql} is NULL or #{column_sql} = ''"
16
15
  elsif value == false
@@ -199,7 +199,22 @@ module Searchgasm
199
199
  when Hash
200
200
  assert_valid_conditions(value)
201
201
  remove_conditions_from_protected_assignement(value).each do |condition, condition_value|
202
- send("#{condition}=", condition_value)
202
+
203
+ # delete all blanks from mass assignments, forms submit blanks, blanks are meaningless
204
+ # equals condition thinks everything is meaningful, and arrays can be pased
205
+ new_condition_value = nil
206
+ case condition_value
207
+ when Array
208
+ new_condition_value = []
209
+ condition_value.each { |v| new_condition_value << v unless v == "" }
210
+ next if new_condition_value.size == 0
211
+ new_condition_value = new_condition_value.first if new_condition_value.size == 1
212
+ else
213
+ next if condition_value == ""
214
+ new_condition_value = condition_value
215
+ end
216
+
217
+ send("#{condition}=", new_condition_value)
203
218
  end
204
219
  else
205
220
  reset_objects!
@@ -219,7 +234,7 @@ module Searchgasm
219
234
  next if relationship_conditions.blank?
220
235
  conditions_hash[object.relationship_name.to_sym] = relationship_conditions
221
236
  else
222
- next if object.meaningless_value?
237
+ next if object.value_is_meaningless?
223
238
  conditions_hash[name] = object.value
224
239
  end
225
240
  end
@@ -374,7 +389,7 @@ module Searchgasm
374
389
  @conditions = nil
375
390
 
376
391
  #{name}_object.value = value
377
- reset_#{name}! if #{name}_object.meaningless_value?
392
+ reset_#{name}! if #{name}_object.value_is_meaningless?
378
393
  value
379
394
  end
380
395
 
@@ -395,7 +410,20 @@ module Searchgasm
395
410
 
396
411
  def assert_valid_conditions(conditions)
397
412
  conditions.each do |condition, value|
398
- raise(ArgumentError, "The #{condition} condition is not a valid condition") if !(self.class.condition_names + self.class.association_names + ["any"]).include?(condition.to_s) && respond_to?(condition)
413
+ next if (self.class.condition_names + self.class.association_names + ["any"]).include?(condition.to_s)
414
+
415
+ go_to_next = false
416
+ self.class.column_details.each do |column_detail|
417
+ if column_detail[:column].name == condition.to_s || column_detail[:aliases].include?(condition.to_s)
418
+ go_to_next = true
419
+ break
420
+ end
421
+ end
422
+ next if go_to_next
423
+
424
+ next unless respond_to?(condition)
425
+
426
+ raise(ArgumentError, "The #{condition} condition is not a valid condition")
399
427
  end
400
428
  end
401
429
 
@@ -156,7 +156,7 @@ module Searchgasm
156
156
 
157
157
  def remove_duplicates # :nodoc:
158
158
  return @remove_duplicates if @set_remove_duplicates
159
- @remove_duplicates ||= ::ActiveRecord::VERSION::MAJOR < 2 || (::ActiveRecord::VERSION::MAJOR == 2 && ::ActiveRecord::VERSION::MINOR < 2)
159
+ @remove_duplicates ||= true
160
160
  end
161
161
 
162
162
  def remove_duplicates? # :nodoc:
@@ -19,7 +19,7 @@ module Searchgasm
19
19
  def deep_delete_duplicate_keys(hash)
20
20
  hash.each do |k, v|
21
21
  if v.is_a?(Hash) && self[k]
22
- self[k].deep_delete_duplicates(v)
22
+ self[k].deep_delete_duplicate_keys(v)
23
23
  delete(k) if self[k].blank?
24
24
  else
25
25
  delete(k)
@@ -113,17 +113,6 @@ module Searchgasm #:nodoc:
113
113
  find_options[find_option] = value
114
114
  end
115
115
 
116
- if Config.remove_duplicates?
117
- unless find_options[:joins].blank?
118
- # The following is to return uniq records since we are using joins instead of includes
119
- if searching
120
- find_options[:group] ||= "#{quote_table_name(klass.table_name)}.#{quote_column_name(klass.primary_key)}"
121
- else
122
- find_options[:distinct] = true
123
- end
124
- end
125
- end
126
-
127
116
  find_options
128
117
  end
129
118
 
@@ -21,8 +21,15 @@ module Searchgasm
21
21
  find_options = {}
22
22
  options = args.extract_options! # can't pass options, your options are in the search
23
23
  klass.send(:with_scope, :find => scope) do
24
- args << sanitize(#{SEARCH_METHODS.include?(method)})
25
- klass.#{method}(*args)
24
+ options = sanitize(#{SEARCH_METHODS.include?(method)})
25
+ if #{CALCULATION_METHODS.include?(method)}
26
+ options[:distinct] = true
27
+ args[0] = klass.primary_key if [nil, :all].include?(args[0])
28
+ end
29
+ args << options
30
+ result = klass.#{method}(*args)
31
+ result.uniq! if result.is_a?(Array) && Config.remove_duplicates?
32
+ result
26
33
  end
27
34
  end
28
35
  end_eval
@@ -67,7 +67,7 @@ module Searchgasm
67
67
 
68
68
  MAJOR = 1
69
69
  MINOR = 3
70
- TINY = 1
70
+ TINY = 2
71
71
 
72
72
  # The current version as a Version instance
73
73
  CURRENT = new(MAJOR, MINOR, TINY)
data/searchgasm.gemspec CHANGED
@@ -1,18 +1,18 @@
1
1
 
2
- # Gem::Specification for Searchgasm-1.3.1
2
+ # Gem::Specification for Searchgasm-1.3.2
3
3
  # Originally generated by Echoe
4
4
 
5
5
  --- !ruby/object:Gem::Specification
6
6
  name: searchgasm
7
7
  version: !ruby/object:Gem::Version
8
- version: 1.3.1
8
+ version: 1.3.2
9
9
  platform: ruby
10
10
  authors:
11
11
  - Ben Johnson of Binary Logic
12
12
  autorequire:
13
13
  bindir: bin
14
14
 
15
- date: 2008-10-02 00:00:00 -04:00
15
+ date: 2008-10-03 00:00:00 -04:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
@@ -65,7 +65,7 @@ class TestActiveRecordAssociations < Test::Unit::TestCase
65
65
  assert_equal 2, search.count
66
66
 
67
67
  search.conditions.first_name_contains = "Ben"
68
-
68
+
69
69
  assert_equal [User.find(1)], search.all
70
70
  assert_equal User.find(1), search.first
71
71
  assert_equal 1, search.average("id")
@@ -7,19 +7,19 @@ class TestConditionTypes < Test::Unit::TestCase
7
7
  assert_equal ["\"accounts\".\"name\" LIKE ?", "Binary%"], condition.sanitize
8
8
 
9
9
  condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
10
- condition.value = true
10
+ condition.value = "true"
11
11
  assert_equal "\"accounts\".\"id\" is NULL or \"accounts\".\"id\" = ''", condition.sanitize
12
12
 
13
13
  condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
14
- condition.value = false
14
+ condition.value = "false"
15
15
  assert_equal "\"accounts\".\"id\" is NOT NULL and \"accounts\".\"id\" != ''", condition.sanitize
16
16
 
17
17
  condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
18
- condition.value = "true"
18
+ condition.value = true
19
19
  assert_equal "\"accounts\".\"id\" is NULL or \"accounts\".\"id\" = ''", condition.sanitize
20
20
 
21
21
  condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
22
- condition.value = "false"
22
+ condition.value = false
23
23
  assert_equal "\"accounts\".\"id\" is NOT NULL and \"accounts\".\"id\" != ''", condition.sanitize
24
24
 
25
25
  condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
@@ -117,8 +117,9 @@ class TestConditionsBase < Test::Unit::TestCase
117
117
  conditions.name_contains = "awesome"
118
118
  assert_equal({:name_like => "awesome"}, conditions.conditions)
119
119
 
120
- conditions.conditions = {:id_gt => "", :name_starts_with => "Ben"}
121
- assert_equal({:name_like => "awesome", :name_begins_with => "Ben"}, conditions.conditions)
120
+ now = Time.now
121
+ conditions.conditions = {:id_gt => "", :id => "", :name => ["", "", ""], :created_at => ["", now], :name_starts_with => "Ben"}
122
+ assert_equal({:name_like => "awesome", :name_begins_with => "Ben", :created_at_equals => now}, conditions.conditions)
122
123
  end
123
124
 
124
125
  # Other general usage tests, need to clean these up
@@ -140,7 +140,7 @@ class TestSearchBase < Test::Unit::TestCase
140
140
  search.conditions.users.id_greater_than = 2
141
141
  search.page = 3
142
142
  search.readonly = true
143
- assert_equal({:joins => :users, :group => "\"accounts\".\"id\"", :offset => 4, :readonly => true, :conditions => ["(\"accounts\".\"name\" LIKE ?) AND (\"users\".\"id\" > ?)", "%Binary%", 2], :limit => 2 }, search.sanitize)
143
+ assert_equal({:joins => :users, :offset => 4, :readonly => true, :conditions => ["(\"accounts\".\"name\" LIKE ?) AND (\"users\".\"id\" > ?)", "%Binary%", 2], :limit => 2 }, search.sanitize)
144
144
  end
145
145
 
146
146
  def test_scope
@@ -199,6 +199,15 @@ class TestSearchBase < Test::Unit::TestCase
199
199
 
200
200
  search.readonly = true
201
201
  assert_equal 4, search.sum('id')
202
+
203
+ search = Account.new_search(:conditions => {:users => {:orders => {:id_gt => 1}}})
204
+ assert_equal 1, search.count
205
+
206
+ search = Order.new_search(:conditions => {:user => {:account => {:id_gt => 1}}})
207
+ assert_equal 1, search.count
208
+
209
+ search = UserGroup.new_search(:conditions => {:users => {:orders => {:id_gt => 1}}})
210
+ assert_equal 1, search.count
202
211
  end
203
212
 
204
213
  def test_method_creation_in_scope
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchgasm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.3.2
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-10-02 00:00:00 -04:00
12
+ date: 2008-10-03 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency