searchgasm 1.2.1 → 1.2.2
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 +11 -1
- data/Manifest +7 -2
- data/README.rdoc +1 -1
- data/Rakefile +1 -1
- data/TODO.rdoc +5 -0
- data/lib/searchgasm/active_record/connection_adapters/mysql_adapter.rb +15 -0
- data/lib/searchgasm/active_record/connection_adapters/postgresql_adapter.rb +0 -0
- data/lib/searchgasm/active_record/connection_adapters/sqlite_adapter.rb +0 -0
- data/lib/searchgasm/condition/base.rb +26 -10
- data/lib/searchgasm/condition/{is_blank.rb → blank.rb} +5 -6
- data/lib/searchgasm/condition/does_not_equal.rb +1 -1
- data/lib/searchgasm/condition/during_evening.rb +32 -0
- data/lib/searchgasm/condition/equals.rb +1 -1
- data/lib/searchgasm/condition/greater_than.rb +2 -1
- data/lib/searchgasm/condition/greater_than_or_equal_to.rb +7 -1
- data/lib/searchgasm/condition/less_than.rb +2 -1
- data/lib/searchgasm/condition/less_than_or_equal_to.rb +7 -1
- data/lib/searchgasm/condition/nil.rb +21 -0
- data/lib/searchgasm/conditions/base.rb +6 -3
- data/lib/searchgasm/config.rb +22 -0
- data/lib/searchgasm/helpers/control_types/link.rb +9 -26
- data/lib/searchgasm/helpers/control_types/select.rb +4 -4
- data/lib/searchgasm/helpers/utilities.rb +49 -11
- data/lib/searchgasm/search/base.rb +10 -8
- data/lib/searchgasm/search/ordering.rb +4 -4
- data/lib/searchgasm/shared/utilities.rb +10 -0
- data/lib/searchgasm/version.rb +1 -1
- data/lib/searchgasm.rb +4 -3
- data/searchgasm.gemspec +18 -8
- data/test/test_active_record_base.rb +1 -0
- data/test/test_condition_base.rb +10 -8
- data/test/test_condition_types.rb +30 -30
- data/test/test_conditions_base.rb +1 -0
- data/test/test_search_base.rb +4 -0
- data/test/test_search_ordering.rb +14 -1
- metadata +17 -7
- data/lib/searchgasm/condition/is_nil.rb +0 -23
data/CHANGELOG.rdoc
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
== 1.2.
|
1
|
+
== 1.2.2 released 2008-09-29
|
2
|
+
|
3
|
+
* Fixed bug when reverse engineering order to order_by, assumed ASC and DESC would always be present when they are not.
|
4
|
+
* False is a meaningful value for some conditions, and false.blank? == true. So instead of using value.blank? to ignore conditions we use meaningless?(value), which returns false if it is false.
|
5
|
+
* Fixed aliases for lt, lte, gt, and gte.
|
6
|
+
* Fixed bug when writing conditions on associations via a hash with string keys
|
7
|
+
* Added Config.remove_duplicates to turn off the "automatic" removing of duplicates if desired.
|
8
|
+
* Updated searchgasm_state helper to insert the entire state all at once.
|
9
|
+
* Added CSS class "ordering" to order_by_link if the search is being ordered by that.
|
10
|
+
|
11
|
+
== 1.2.1 released 2008-09-25
|
2
12
|
|
3
13
|
* Fixed problem when determining if an order_by_link is currently being ordered. Just "stringified" both comparable values.
|
4
14
|
* Removed default order_by and order_as. They will ONLY have values if you specify how to order, otherwise they are nil.
|
data/Manifest
CHANGED
@@ -3,22 +3,26 @@ examples/README.rdoc
|
|
3
3
|
init.rb
|
4
4
|
lib/searchgasm/active_record/associations.rb
|
5
5
|
lib/searchgasm/active_record/base.rb
|
6
|
+
lib/searchgasm/active_record/connection_adapters/mysql_adapter.rb
|
7
|
+
lib/searchgasm/active_record/connection_adapters/postgresql_adapter.rb
|
8
|
+
lib/searchgasm/active_record/connection_adapters/sqlite_adapter.rb
|
6
9
|
lib/searchgasm/condition/base.rb
|
7
10
|
lib/searchgasm/condition/begins_with.rb
|
11
|
+
lib/searchgasm/condition/blank.rb
|
8
12
|
lib/searchgasm/condition/child_of.rb
|
9
13
|
lib/searchgasm/condition/contains.rb
|
10
14
|
lib/searchgasm/condition/descendant_of.rb
|
11
15
|
lib/searchgasm/condition/does_not_equal.rb
|
16
|
+
lib/searchgasm/condition/during_evening.rb
|
12
17
|
lib/searchgasm/condition/ends_with.rb
|
13
18
|
lib/searchgasm/condition/equals.rb
|
14
19
|
lib/searchgasm/condition/greater_than.rb
|
15
20
|
lib/searchgasm/condition/greater_than_or_equal_to.rb
|
16
21
|
lib/searchgasm/condition/inclusive_descendant_of.rb
|
17
|
-
lib/searchgasm/condition/is_blank.rb
|
18
|
-
lib/searchgasm/condition/is_nil.rb
|
19
22
|
lib/searchgasm/condition/keywords.rb
|
20
23
|
lib/searchgasm/condition/less_than.rb
|
21
24
|
lib/searchgasm/condition/less_than_or_equal_to.rb
|
25
|
+
lib/searchgasm/condition/nil.rb
|
22
26
|
lib/searchgasm/condition/sibling_of.rb
|
23
27
|
lib/searchgasm/condition/tree.rb
|
24
28
|
lib/searchgasm/conditions/base.rb
|
@@ -66,3 +70,4 @@ test/test_search_conditions.rb
|
|
66
70
|
test/test_search_ordering.rb
|
67
71
|
test/test_search_pagination.rb
|
68
72
|
test/test_search_protection.rb
|
73
|
+
TODO.rdoc
|
data/README.rdoc
CHANGED
@@ -345,7 +345,7 @@ What that rule means is that any options you pass when searching get "sanitized"
|
|
345
345
|
|
346
346
|
Author: {Ben Johnson}[http://github.com/binarylogic] of {Binary Logic}[http://www.binarylogic.com]
|
347
347
|
|
348
|
-
Credit to {Zack Ham}[http://github.com/zackham]
|
348
|
+
Credit to {Zack Ham}[http://github.com/zackham] for helping with feature suggestions.
|
349
349
|
|
350
350
|
|
351
351
|
Copyright (c) 2008 {Ben Johnson}[http://github.com/binarylogic] of {Binary Logic}[http://www.binarylogic.com], released under the MIT license
|
data/Rakefile
CHANGED
@@ -10,6 +10,6 @@ Echoe.new 'searchgasm' do |p|
|
|
10
10
|
p.project = 'searchgasm'
|
11
11
|
p.summary = "Object based ActiveRecord searching, ordering, pagination, and more!"
|
12
12
|
p.url = "http://github.com/binarylogic/searchgasm"
|
13
|
-
p.dependencies =
|
13
|
+
p.dependencies = %w(activerecord activesupport)
|
14
14
|
p.include_rakefile = true
|
15
15
|
end
|
data/TODO.rdoc
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
= To Do
|
2
|
+
|
3
|
+
1. Add month condition for date and datetime columns. So you can specify a specific month, by name, number, etc.
|
4
|
+
2. Add day condition for time and datetime columns. So you can specify that the time is during the day or the night.
|
5
|
+
3. Add weekend condition for date and datetime columns. So you can specify if the date is on a friday, saturday, or sunday
|
File without changes
|
File without changes
|
@@ -8,9 +8,8 @@ module Searchgasm
|
|
8
8
|
include Shared::Utilities
|
9
9
|
|
10
10
|
attr_accessor :column, :klass
|
11
|
-
class_inheritable_accessor :
|
12
|
-
self.
|
13
|
-
self.type_cast_value = true
|
11
|
+
class_inheritable_accessor :ignore_meaningless, :type_cast_sql_type
|
12
|
+
self.ignore_meaningless = true
|
14
13
|
|
15
14
|
class << self
|
16
15
|
# Name of the condition inferred from the class name
|
@@ -29,12 +28,8 @@ module Searchgasm
|
|
29
28
|
[]
|
30
29
|
end
|
31
30
|
|
32
|
-
def
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def type_cast_value? # :nodoc:
|
37
|
-
type_cast_value == true
|
31
|
+
def ignore_meaningless? # :nodoc:
|
32
|
+
ignore_meaningless == true
|
38
33
|
end
|
39
34
|
|
40
35
|
# Sane as name_for_column but for the class as a whole. For example the tree methods apply to the class as a whole and not
|
@@ -48,6 +43,16 @@ module Searchgasm
|
|
48
43
|
[]
|
49
44
|
end
|
50
45
|
|
46
|
+
# A utility method for using in name_for_column. Determines if a column contains a date.
|
47
|
+
def date_column?(column)
|
48
|
+
[:datetime, :date, :timestamp].include?(column.type)
|
49
|
+
end
|
50
|
+
|
51
|
+
# A utility method for using in name_for_column. Determines if a column contains a date and a time.
|
52
|
+
def datetime_column?(column)
|
53
|
+
[:datetime, :timestamp, :time, :date].include?(column.type)
|
54
|
+
end
|
55
|
+
|
51
56
|
# A utility method for using in name_for_column. For example the keywords condition only applied to string columns, the great than condition doesnt.
|
52
57
|
def string_column?(column)
|
53
58
|
[:string, :text].include?(column.type)
|
@@ -57,6 +62,11 @@ module Searchgasm
|
|
57
62
|
def comparable_column?(column)
|
58
63
|
[:integer, :float, :decimal, :datetime, :timestamp, :time, :date].include?(column.type)
|
59
64
|
end
|
65
|
+
|
66
|
+
# A utility method for using in name_for_column. Determines if a column contains a time.
|
67
|
+
def time_column?(column)
|
68
|
+
[:datetime, :timestamp, :time].include?(column.type)
|
69
|
+
end
|
60
70
|
end
|
61
71
|
|
62
72
|
def initialize(klass, column = nil)
|
@@ -118,14 +128,20 @@ module Searchgasm
|
|
118
128
|
|
119
129
|
# The value for the condition
|
120
130
|
def value
|
121
|
-
|
131
|
+
@value.is_a?(String) ? column_for_type_cast.type_cast(@value) : @value
|
122
132
|
end
|
123
133
|
|
124
134
|
# Sets the value for the condition
|
125
135
|
def value=(v)
|
136
|
+
return if self.class.ignore_meaningless? && meaningless?(v)
|
126
137
|
self.explicitly_set_value = true
|
127
138
|
@value = v
|
128
139
|
end
|
140
|
+
|
141
|
+
private
|
142
|
+
def column_for_type_cast
|
143
|
+
@column_for_type_cast ||= self.class.type_cast_sql_type ? self.column.class.new(column.name, column.default.to_s, self.class.type_cast_sql_type.to_s, column.null) : column
|
144
|
+
end
|
129
145
|
end
|
130
146
|
end
|
131
147
|
end
|
@@ -1,20 +1,19 @@
|
|
1
1
|
module Searchgasm
|
2
2
|
module Condition
|
3
|
-
class
|
4
|
-
self.
|
5
|
-
self.type_cast_value = false
|
3
|
+
class Blank < Base
|
4
|
+
self.type_cast_sql_type = "boolean"
|
6
5
|
|
7
6
|
class << self
|
8
7
|
def aliases_for_column(column)
|
9
|
-
["#{column.name}
|
8
|
+
["#{column.name}_is_blank"]
|
10
9
|
end
|
11
10
|
end
|
12
11
|
|
13
12
|
def to_conditions(value)
|
14
13
|
# Some databases handle null values differently, let AR handle this
|
15
|
-
if value == true
|
14
|
+
if value == true
|
16
15
|
"#{quoted_table_name}.#{quoted_column_name} is NULL or #{quoted_table_name}.#{quoted_column_name} = ''"
|
17
|
-
elsif value == false
|
16
|
+
elsif value == false
|
18
17
|
"#{quoted_table_name}.#{quoted_column_name} is NOT NULL and #{quoted_table_name}.#{quoted_column_name} != ''"
|
19
18
|
end
|
20
19
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Searchgasm
|
2
|
+
module Condition
|
3
|
+
class DuringEvening < Base
|
4
|
+
class << self
|
5
|
+
def name_for_column(column)
|
6
|
+
return unless time_column?(column)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def aliases_for_column(column)
|
11
|
+
column_names = [column.name]
|
12
|
+
column_names << column.name.gsub(/_(at|on)$/, "") if column.name =~ /_(at|on)$/
|
13
|
+
|
14
|
+
aliases = []
|
15
|
+
column_names.each { |column_name| aliases += ["#{column_name}_in_the_evening", "#{column_name}_in_evening", "#{column_name}_evening"] }
|
16
|
+
aliases << "#{column_names.last}_during_evening" if column_names.size > 1
|
17
|
+
aliases
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_conditions(value)
|
22
|
+
evening_start = 17
|
23
|
+
evening_end = 22
|
24
|
+
|
25
|
+
# Need to set up a funcion in each adapter for dealing with dates. Mysql uses HOUR(), sqlite uses strftime(), postgres uses date_part('hour', date). Could potentially be a pain in the ass.
|
26
|
+
# Also, you could set up an hour = condition, and leverage that to do this.
|
27
|
+
if value == true
|
28
|
+
["#{quoted_table_name}.#{quoted_column_name} >= ? AND #{quoted_table_name}.#{quoted_column_name} <= ?", value]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -9,10 +9,11 @@ module Searchgasm
|
|
9
9
|
|
10
10
|
def aliases_for_column(column)
|
11
11
|
column_names = [column.name]
|
12
|
-
column_names << column.name.gsub(/
|
12
|
+
column_names << column.name.gsub(/_(at|on)$/, "") if datetime_column?(column) && column.name =~ /_(at|on)$/
|
13
13
|
|
14
14
|
aliases = []
|
15
15
|
column_names.each { |column_name| aliases += ["#{column_name}_gt", "#{column_name}_after"] }
|
16
|
+
aliases << "#{column_names.last}_greater_than" if column_names.size > 1
|
16
17
|
aliases
|
17
18
|
end
|
18
19
|
end
|
@@ -8,7 +8,13 @@ module Searchgasm
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def aliases_for_column(column)
|
11
|
-
[
|
11
|
+
column_names = [column.name]
|
12
|
+
column_names << column.name.gsub(/_(at|on)$/, "") if datetime_column?(column) && column.name =~ /_(at|on)$/
|
13
|
+
|
14
|
+
aliases = []
|
15
|
+
column_names.each { |column_name| aliases += ["#{column_name}_gte", "#{column_name}_at_least"] }
|
16
|
+
aliases << "#{column_names.last}_greater_than_or_equal_to" if column_names.size > 1
|
17
|
+
aliases
|
12
18
|
end
|
13
19
|
end
|
14
20
|
|
@@ -9,10 +9,11 @@ module Searchgasm
|
|
9
9
|
|
10
10
|
def aliases_for_column(column)
|
11
11
|
column_names = [column.name]
|
12
|
-
column_names << column.name.gsub(/
|
12
|
+
column_names << column.name.gsub(/_(at|on)$/, "") if datetime_column?(column) && column.name =~ /_(at|on)$/
|
13
13
|
|
14
14
|
aliases = []
|
15
15
|
column_names.each { |column_name| aliases += ["#{column_name}_lt", "#{column_name}_before"] }
|
16
|
+
aliases << "#{column_names.last}_less_than" if column_names.size > 1
|
16
17
|
aliases
|
17
18
|
end
|
18
19
|
end
|
@@ -8,7 +8,13 @@ module Searchgasm
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def aliases_for_column(column)
|
11
|
-
[
|
11
|
+
column_names = [column.name]
|
12
|
+
column_names << column.name.gsub(/_(at|on)$/, "") if datetime_column?(column) && column.name =~ /_(at|on)$/
|
13
|
+
|
14
|
+
aliases = []
|
15
|
+
column_names.each { |column_name| aliases += ["#{column_name}_lte", "#{column_name}_at_most"] }
|
16
|
+
aliases << "#{column_names.last}_less_than_or_equal_to" if column_names.size > 1
|
17
|
+
aliases
|
12
18
|
end
|
13
19
|
end
|
14
20
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Searchgasm
|
2
|
+
module Condition
|
3
|
+
class Nil < Base
|
4
|
+
self.type_cast_sql_type = "boolean"
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def aliases_for_column(column)
|
8
|
+
["#{column.name}_is_nil", "#{column.name}_is_null", "#{column.name}_null"]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_conditions(value)
|
13
|
+
if value == true
|
14
|
+
"#{quoted_table_name}.#{quoted_column_name} is NULL"
|
15
|
+
elsif value == false
|
16
|
+
"#{quoted_table_name}.#{quoted_column_name} is NOT NULL"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -68,8 +68,11 @@ module Searchgasm
|
|
68
68
|
|
69
69
|
if conditions.is_a?(Hash)
|
70
70
|
return true if conditions[:any]
|
71
|
+
stringified_conditions = conditions.stringify_keys
|
72
|
+
stringified_conditions.keys.each { |condition| return false if condition.include?(".") } # setting conditions on associations, which is just another way of writing SQL, and we ignore SQL
|
73
|
+
|
71
74
|
column_names = model_class.column_names
|
72
|
-
|
75
|
+
stringified_conditions.keys.each do |condition|
|
73
76
|
return true unless column_names.include?(condition)
|
74
77
|
end
|
75
78
|
end
|
@@ -132,7 +135,7 @@ module Searchgasm
|
|
132
135
|
when Hash
|
133
136
|
assert_valid_conditions(value)
|
134
137
|
remove_conditions_from_protected_assignement(value).each do |condition, condition_value|
|
135
|
-
next if condition_value
|
138
|
+
next if meaningless?(condition_value) # ignore blanks on mass assignments
|
136
139
|
send("#{condition}=", condition_value)
|
137
140
|
end
|
138
141
|
else
|
@@ -216,7 +219,7 @@ module Searchgasm
|
|
216
219
|
def #{name}; #{name}_object.value; end
|
217
220
|
|
218
221
|
def #{name}=(value)
|
219
|
-
if value
|
222
|
+
if meaningless?(value) && #{name}_object.class.ignore_meaningless?
|
220
223
|
reset_#{name}!
|
221
224
|
else
|
222
225
|
@conditions = nil
|
data/lib/searchgasm/config.rb
CHANGED
@@ -153,6 +153,28 @@ module Searchgasm
|
|
153
153
|
def per_page_choices=(value)
|
154
154
|
@per_page_choices = value
|
155
155
|
end
|
156
|
+
|
157
|
+
def remove_duplicates # :nodoc:
|
158
|
+
return @remove_duplicates if @set_remove_duplicates
|
159
|
+
@remove_duplicates ||= ::ActiveRecord::VERSION::MAJOR < 2 || (::ActiveRecord::VERSION::MAJOR == 2 && ::ActiveRecord::VERSION::MINOR < 2)
|
160
|
+
end
|
161
|
+
|
162
|
+
def remove_duplicates? # :nodoc:
|
163
|
+
remove_duplicates == true
|
164
|
+
end
|
165
|
+
|
166
|
+
# If you are using ActiveRecord < 2.2.0 then ActiveRecord does not remove duplicates when using the :joins option, when it should. To fix this problem searchgasm does this for you. Searchgasm tries to act
|
167
|
+
# just like ActiveRecord, but in this instance it doesn't make sense.
|
168
|
+
#
|
169
|
+
# As a result, Searchgasm removes all duplicates results in *ALL* search / calculation queries. It does this by forcing the DISTINCT or GROUP BY operation in your SQL. Which might come as a surprise to you
|
170
|
+
# since it is not the "norm". If you don't want searchgasm to do this, set this to false.
|
171
|
+
#
|
172
|
+
# * <tt>Default:</tt> true
|
173
|
+
# * <tt>Accepts:</tt> Boolean
|
174
|
+
def remove_duplicates=(value)
|
175
|
+
@set_remove_duplicates = true
|
176
|
+
@remove_duplicates = value
|
177
|
+
end
|
156
178
|
end
|
157
179
|
end
|
158
180
|
end
|
@@ -85,9 +85,8 @@ module Searchgasm
|
|
85
85
|
# * <tt>:search_params</tt> -- default: nil, Additional search params to add to the url, must be a hash. Adds the options into the :params_scope.
|
86
86
|
# * <tt>:exclude_search_params</tt> -- default: nil, Same as :exclude_params but for the :search_params.
|
87
87
|
def order_by_link(order_by, options = {})
|
88
|
-
order_by = deep_stringify(order_by)
|
89
88
|
add_order_by_link_defaults!(order_by, options)
|
90
|
-
html =
|
89
|
+
html = searchgasm_state(options)
|
91
90
|
|
92
91
|
if !options[:is_remote]
|
93
92
|
html += link_to(options[:text], options[:url], options[:html])
|
@@ -119,7 +118,7 @@ module Searchgasm
|
|
119
118
|
# * <tt>:exclude_search_params</tt> -- default: nil, Same as :exclude_params but for the :search_params.
|
120
119
|
def order_as_link(order_as, options = {})
|
121
120
|
add_order_as_link_defaults!(order_as, options)
|
122
|
-
html =
|
121
|
+
html = searchgasm_state(options)
|
123
122
|
|
124
123
|
if !options[:is_remote]
|
125
124
|
html += link_to(options[:text], options[:url], options[:html])
|
@@ -159,9 +158,8 @@ module Searchgasm
|
|
159
158
|
# * <tt>:search_params</tt> -- default: nil, Additional search params to add to the url, must be a hash. Adds the options into the :params_scope.
|
160
159
|
# * <tt>:exclude_search_params</tt> -- default: nil, Same as :exclude_params but for the :search_params.
|
161
160
|
def priority_order_by_link(priority_order_by, priority_order_as, options = {})
|
162
|
-
priority_order_by = deep_stringify(priority_order_by)
|
163
161
|
add_priority_order_by_link_defaults!(priority_order_by, priority_order_as, options)
|
164
|
-
html =
|
162
|
+
html = searchgasm_state(options)
|
165
163
|
|
166
164
|
if !options[:is_remote]
|
167
165
|
html += link_to(options[:text], options[:url], options[:html])
|
@@ -195,7 +193,7 @@ module Searchgasm
|
|
195
193
|
# * <tt>:exclude_search_params</tt> -- default: nil, Same as :exclude_params but for the :search_params.
|
196
194
|
def per_page_link(per_page, options = {})
|
197
195
|
add_per_page_link_defaults!(per_page, options)
|
198
|
-
html =
|
196
|
+
html = searchgasm_state(options)
|
199
197
|
|
200
198
|
if !options[:is_remote]
|
201
199
|
html += link_to(options[:text], options[:url], options[:html])
|
@@ -227,7 +225,7 @@ module Searchgasm
|
|
227
225
|
# * <tt>:exclude_search_params</tt> -- default: nil, Same as :exclude_params but for the :search_params.
|
228
226
|
def page_link(page, options = {})
|
229
227
|
add_page_link_defaults!(page, options)
|
230
|
-
html =
|
228
|
+
html = searchgasm_state(options)
|
231
229
|
|
232
230
|
if !options[:is_remote]
|
233
231
|
html += link_to(options[:text], options[:url], options[:html])
|
@@ -241,10 +239,12 @@ module Searchgasm
|
|
241
239
|
private
|
242
240
|
def add_order_by_link_defaults!(order_by, options = {})
|
243
241
|
add_searchgasm_control_defaults!(:order_by, options)
|
242
|
+
ordering_by_this = searchgasm_ordering_by?(order_by, options)
|
243
|
+
searchgasm_add_class!(options[:html], "ordering") if ordering_by_this
|
244
244
|
options[:text] ||= determine_order_by_text(order_by)
|
245
245
|
options[:asc_indicator] ||= Config.asc_indicator
|
246
246
|
options[:desc_indicator] ||= Config.desc_indicator
|
247
|
-
options[:text] += options[:search_obj].desc? ? options[:desc_indicator] : options[:asc_indicator] if
|
247
|
+
options[:text] += options[:search_obj].desc? ? options[:desc_indicator] : options[:asc_indicator] if ordering_by_this
|
248
248
|
options[:url] = searchgasm_params(options.merge(:search_params => {:order_by => order_by}))
|
249
249
|
options
|
250
250
|
end
|
@@ -261,7 +261,7 @@ module Searchgasm
|
|
261
261
|
options[:column_name] ||= determine_order_by_text(priority_order_by).downcase
|
262
262
|
options[:activate_text] ||= "Show #{options[:column_name]} first"
|
263
263
|
options[:deactivate_text] ||= "Don't show #{options[:column_name]} first"
|
264
|
-
active = deep_stringify(options[:search_obj].priority_order_by) == priority_order_by && options[:search_obj].priority_order_as == priority_order_as
|
264
|
+
active = deep_stringify(options[:search_obj].priority_order_by) == deep_stringify(priority_order_by) && options[:search_obj].priority_order_as == priority_order_as
|
265
265
|
options[:text] ||= active ? options[:deactivate_text] : options[:activate_text]
|
266
266
|
if active
|
267
267
|
options.merge!(:search_params => {:priority_order_by => nil, :priority_order_as => nil})
|
@@ -298,23 +298,6 @@ module Searchgasm
|
|
298
298
|
determine_order_by_text(v, k)
|
299
299
|
end
|
300
300
|
end
|
301
|
-
|
302
|
-
def deep_stringify(obj)
|
303
|
-
case obj
|
304
|
-
when String
|
305
|
-
obj
|
306
|
-
when Symbol
|
307
|
-
obj.to_s
|
308
|
-
when Array
|
309
|
-
obj.collect { |item| deep_stringify(item) }
|
310
|
-
when Hash
|
311
|
-
new_obj = {}
|
312
|
-
obj.each { |key, value| new_obj[key.to_s] = deep_stringify(value) }
|
313
|
-
new_obj
|
314
|
-
else
|
315
|
-
obj
|
316
|
-
end
|
317
|
-
end
|
318
301
|
end
|
319
302
|
end
|
320
303
|
end
|
@@ -8,25 +8,25 @@ module Searchgasm
|
|
8
8
|
# Please see order_by_links. All options are the same and applicable here. The only difference is that instead of a group of links, this gets returned as a select form element that will perform the same function when the value is changed.
|
9
9
|
def order_by_select(options = {})
|
10
10
|
add_order_by_select_defaults!(options)
|
11
|
-
|
11
|
+
searchgasm_state(options) + select(options[:params_scope], :order_by, options[:choices], options[:tag], options[:html] || {})
|
12
12
|
end
|
13
13
|
|
14
14
|
# Please see order_as_links. All options are the same and applicable here. The only difference is that instead of a group of links, this gets returned as a select form element that will perform the same function when the value is changed.
|
15
15
|
def order_as_select(options = {})
|
16
16
|
add_order_as_select_defaults!(options)
|
17
|
-
|
17
|
+
searchgasm_state(options) + select(options[:params_scope], :order_as, options[:choices], options[:tag], options[:html])
|
18
18
|
end
|
19
19
|
|
20
20
|
# Please see per_page_links. All options are the same and applicable here. The only difference is that instead of a group of links, this gets returned as a select form element that will perform the same function when the value is changed.
|
21
21
|
def per_page_select(options = {})
|
22
22
|
add_per_page_select_defaults!(options)
|
23
|
-
|
23
|
+
searchgasm_state(options) + select(options[:params_scope], :per_page, options[:choices], options[:tag], options[:html])
|
24
24
|
end
|
25
25
|
|
26
26
|
# Please see page_links. All options are the same and applicable here, excep the :prev, :next, :first, and :last options. The only difference is that instead of a group of links, this gets returned as a select form element that will perform the same function when the value is changed.
|
27
27
|
def page_select(options = {})
|
28
28
|
add_page_select_defaults!(options)
|
29
|
-
|
29
|
+
searchgasm_state(options) + select(options[:params_scope], :page, (options[:first_page]..options[:last_page]), options[:tag], options[:html])
|
30
30
|
end
|
31
31
|
|
32
32
|
private
|
@@ -37,10 +37,12 @@ module Searchgasm
|
|
37
37
|
search_params.deep_delete(options[:exclude_search_params])
|
38
38
|
|
39
39
|
if options[:search_params]
|
40
|
+
|
41
|
+
#raise params_copy.inspect if options[:search_params][:order_by] == :id
|
40
42
|
search_params.deep_merge!(options[:search_params])
|
41
43
|
|
42
44
|
if options[:search_params][:order_by] && !options[:search_params][:order_as]
|
43
|
-
search_params[:order_as] = (options[:
|
45
|
+
search_params[:order_as] = (searchgasm_ordering_by?(options[:search_params][:order_by], options) && options[:search_obj].asc?) ? "DESC" : "ASC"
|
44
46
|
end
|
45
47
|
|
46
48
|
[:order_by, :priority_order_by].each { |base64_field| search_params[base64_field] = searchgasm_base64_value(search_params[base64_field]) if search_params.has_key?(base64_field) }
|
@@ -90,6 +92,30 @@ module Searchgasm
|
|
90
92
|
url += (url.last == "?" ? "" : (url.include?("?") ? "&" : "?")) + literal_param_strings.join("&")
|
91
93
|
end
|
92
94
|
|
95
|
+
# When you set up a search form using form_for for remote_form_for searchgasm adds in some *magic* for you.
|
96
|
+
#
|
97
|
+
# Take the instance where a user orders the data by something other than the default, and then does a search. The user would expect the search to remember what the user selected to order the data by, right?
|
98
|
+
# What searchgasm does is add in some hidden fields, somewhere in the page, the represent the searchgasm "state". These are automatically added for you when you use the searchgasm helpers.
|
99
|
+
# Such as: page_links, page_link, order_by_link, per_page_select, etc. So if you are using those you do not need to worry about this helper.
|
100
|
+
#
|
101
|
+
# If for some reason you do not use any of these you need to put the searchgasm state on your page somewhere. Somewhere where the state will *always* be up-to-date, which would be most likely be in the
|
102
|
+
# partial that renders your search results (assuming you are using AJAX). Otherwise when the user starts a new search, the state will be reset. Meaning the order_by, per_page, etc will all be reset.
|
103
|
+
#
|
104
|
+
# === Options
|
105
|
+
# * <tt>:params_scope</tt> -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
|
106
|
+
# * <tt>:search_obj</tt> -- default: @#{params_scope}, this is your search object, everything revolves around this. It will try to infer the name from your params_scope. If your params_scope is :search it will try to get @search, etc. If it can not be inferred by this, you need to pass the object itself.
|
107
|
+
def searchgasm_state(options)
|
108
|
+
return "" if @added_searchgasm_state
|
109
|
+
add_searchgasm_defaults!(options)
|
110
|
+
html = ""
|
111
|
+
(Search::Base::SPECIAL_FIND_OPTIONS - [:page, :priority_order]).each do |option|
|
112
|
+
value = options[:search_obj].send(option)
|
113
|
+
html += hidden_field(options[:params_scope], option, :value => (option == :order_by ? searchgasm_base64_value(value) : value))
|
114
|
+
end
|
115
|
+
@added_searchgasm_state = true
|
116
|
+
html
|
117
|
+
end
|
118
|
+
|
93
119
|
private
|
94
120
|
# Adds default options for all helper methods.
|
95
121
|
def add_searchgasm_defaults!(options)
|
@@ -117,22 +143,17 @@ module Searchgasm
|
|
117
143
|
|
118
144
|
def searchgasm_base64_value(order_by)
|
119
145
|
case order_by
|
120
|
-
when String
|
146
|
+
when String, Symbol
|
121
147
|
order_by
|
122
148
|
when Array, Hash
|
123
149
|
[Marshal.dump(order_by)].pack("m")
|
124
150
|
end
|
125
151
|
end
|
126
152
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
value = options[:search_obj].send(option)
|
132
|
-
html = hidden_field(options[:params_scope], option, :value => (option == :order_by ? searchgasm_base64_value(value) : value))
|
133
|
-
@added_state_for << option
|
134
|
-
end
|
135
|
-
html
|
153
|
+
def searchgasm_ordering_by?(order_by, options)
|
154
|
+
stringified_search_order_by = deep_stringify(options[:search_obj].order_by)
|
155
|
+
stringified_order_by = deep_stringify(order_by)
|
156
|
+
(options[:search_obj].order_by.blank? && options[:search_obj].klass.primary_key == stringified_order_by) || stringified_search_order_by == stringified_order_by
|
136
157
|
end
|
137
158
|
|
138
159
|
def literal_param_strings(literal_params, prefix)
|
@@ -152,6 +173,23 @@ module Searchgasm
|
|
152
173
|
|
153
174
|
param_strings
|
154
175
|
end
|
176
|
+
|
177
|
+
def deep_stringify(obj)
|
178
|
+
case obj
|
179
|
+
when String
|
180
|
+
obj
|
181
|
+
when Symbol
|
182
|
+
obj.to_s
|
183
|
+
when Array
|
184
|
+
obj.collect { |item| deep_stringify(item) }
|
185
|
+
when Hash
|
186
|
+
new_obj = {}
|
187
|
+
obj.each { |key, value| new_obj[key.to_s] = deep_stringify(value) }
|
188
|
+
new_obj
|
189
|
+
else
|
190
|
+
obj
|
191
|
+
end
|
192
|
+
end
|
155
193
|
end
|
156
194
|
end
|
157
195
|
end
|
@@ -112,16 +112,18 @@ module Searchgasm #:nodoc:
|
|
112
112
|
next if value.blank?
|
113
113
|
find_options[find_option] = value
|
114
114
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
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
|
122
124
|
end
|
123
125
|
end
|
124
|
-
|
126
|
+
|
125
127
|
find_options
|
126
128
|
end
|
127
129
|
|
@@ -39,7 +39,6 @@ module Searchgasm
|
|
39
39
|
|
40
40
|
# Convenience method for determining if the ordering is ascending
|
41
41
|
def asc?
|
42
|
-
return false if order_as.nil?
|
43
42
|
!desc?
|
44
43
|
end
|
45
44
|
|
@@ -199,7 +198,8 @@ module Searchgasm
|
|
199
198
|
# Reversege engineer order, only go 1 level deep with relationships, anything beyond that is probably excessive and not good for performance
|
200
199
|
order_parts = order.split(",").collect do |part|
|
201
200
|
part.strip!
|
202
|
-
part.gsub!(/ (ASC|DESC)$/i, "")
|
201
|
+
part.gsub!(/ (ASC|DESC)$/i, "")
|
202
|
+
part.gsub!(/(.*)\./, "")
|
203
203
|
table_name = ($1 ? $1.gsub(/[^a-z0-9_]/i, "") : nil)
|
204
204
|
part.gsub!(/[^a-z0-9_]/i, "")
|
205
205
|
reflection = nil
|
@@ -223,9 +223,9 @@ module Searchgasm
|
|
223
223
|
value = order_by_value.values.first
|
224
224
|
case value
|
225
225
|
when Hash
|
226
|
-
{key => build_order_by_auto_joins(value)}
|
226
|
+
{key.to_sym => build_order_by_auto_joins(value)}
|
227
227
|
else
|
228
|
-
key
|
228
|
+
key.to_sym
|
229
229
|
end
|
230
230
|
else
|
231
231
|
nil
|
@@ -45,6 +45,16 @@ module Searchgasm
|
|
45
45
|
|
46
46
|
new_joins.compact.uniq
|
47
47
|
end
|
48
|
+
|
49
|
+
# "meaningful" is subjective which is why this is not a core extension like .blank?
|
50
|
+
def meaningless?(value)
|
51
|
+
return false if value == false
|
52
|
+
value.blank?
|
53
|
+
end
|
54
|
+
|
55
|
+
def meaningful?(value)
|
56
|
+
!meaningless?
|
57
|
+
end
|
48
58
|
end
|
49
59
|
end
|
50
60
|
end
|
data/lib/searchgasm/version.rb
CHANGED
data/lib/searchgasm.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
2
2
|
|
3
3
|
require "active_record"
|
4
|
+
require "active_record/version"
|
4
5
|
require "active_support"
|
5
6
|
|
6
7
|
# Core Ext
|
@@ -33,17 +34,17 @@ require "searchgasm/conditions/base"
|
|
33
34
|
# Condition
|
34
35
|
require "searchgasm/condition/base"
|
35
36
|
require "searchgasm/condition/begins_with"
|
37
|
+
require "searchgasm/condition/blank"
|
36
38
|
require "searchgasm/condition/contains"
|
37
39
|
require "searchgasm/condition/does_not_equal"
|
38
40
|
require "searchgasm/condition/ends_with"
|
39
41
|
require "searchgasm/condition/equals"
|
40
42
|
require "searchgasm/condition/greater_than"
|
41
43
|
require "searchgasm/condition/greater_than_or_equal_to"
|
42
|
-
require "searchgasm/condition/is_blank"
|
43
|
-
require "searchgasm/condition/is_nil"
|
44
44
|
require "searchgasm/condition/keywords"
|
45
45
|
require "searchgasm/condition/less_than"
|
46
46
|
require "searchgasm/condition/less_than_or_equal_to"
|
47
|
+
require "searchgasm/condition/nil"
|
47
48
|
require "searchgasm/condition/tree"
|
48
49
|
require "searchgasm/condition/child_of"
|
49
50
|
require "searchgasm/condition/descendant_of"
|
@@ -77,7 +78,7 @@ module Searchgasm
|
|
77
78
|
include Protection
|
78
79
|
end
|
79
80
|
|
80
|
-
[:begins_with, :child_of, :contains, :descendant_of, :does_not_equal, :ends_with, :equals, :greater_than, :greater_than_or_equal_to, :inclusive_descendant_of, :
|
81
|
+
[:begins_with, :blank, :child_of, :contains, :descendant_of, :does_not_equal, :ends_with, :equals, :greater_than, :greater_than_or_equal_to, :inclusive_descendant_of, :nil, :keywords, :less_than, :less_than_or_equal_to, :sibling_of].each do |condition|
|
81
82
|
Base.register_condition("Searchgasm::Condition::#{condition.to_s.camelize}".constantize)
|
82
83
|
end
|
83
84
|
end
|
data/searchgasm.gemspec
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Searchgasm-1.2.
|
2
|
+
# Gem::Specification for Searchgasm-1.2.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.2.
|
8
|
+
version: 1.2.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-09-
|
15
|
+
date: 2008-09-29 00:00:00 -04:00
|
16
16
|
default_executable:
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
@@ -55,22 +55,26 @@ extra_rdoc_files:
|
|
55
55
|
- CHANGELOG.rdoc
|
56
56
|
- lib/searchgasm/active_record/associations.rb
|
57
57
|
- lib/searchgasm/active_record/base.rb
|
58
|
+
- lib/searchgasm/active_record/connection_adapters/mysql_adapter.rb
|
59
|
+
- lib/searchgasm/active_record/connection_adapters/postgresql_adapter.rb
|
60
|
+
- lib/searchgasm/active_record/connection_adapters/sqlite_adapter.rb
|
58
61
|
- lib/searchgasm/condition/base.rb
|
59
62
|
- lib/searchgasm/condition/begins_with.rb
|
63
|
+
- lib/searchgasm/condition/blank.rb
|
60
64
|
- lib/searchgasm/condition/child_of.rb
|
61
65
|
- lib/searchgasm/condition/contains.rb
|
62
66
|
- lib/searchgasm/condition/descendant_of.rb
|
63
67
|
- lib/searchgasm/condition/does_not_equal.rb
|
68
|
+
- lib/searchgasm/condition/during_evening.rb
|
64
69
|
- lib/searchgasm/condition/ends_with.rb
|
65
70
|
- lib/searchgasm/condition/equals.rb
|
66
71
|
- lib/searchgasm/condition/greater_than.rb
|
67
72
|
- lib/searchgasm/condition/greater_than_or_equal_to.rb
|
68
73
|
- lib/searchgasm/condition/inclusive_descendant_of.rb
|
69
|
-
- lib/searchgasm/condition/is_blank.rb
|
70
|
-
- lib/searchgasm/condition/is_nil.rb
|
71
74
|
- lib/searchgasm/condition/keywords.rb
|
72
75
|
- lib/searchgasm/condition/less_than.rb
|
73
76
|
- lib/searchgasm/condition/less_than_or_equal_to.rb
|
77
|
+
- lib/searchgasm/condition/nil.rb
|
74
78
|
- lib/searchgasm/condition/sibling_of.rb
|
75
79
|
- lib/searchgasm/condition/tree.rb
|
76
80
|
- lib/searchgasm/conditions/base.rb
|
@@ -96,28 +100,33 @@ extra_rdoc_files:
|
|
96
100
|
- lib/searchgasm/version.rb
|
97
101
|
- lib/searchgasm.rb
|
98
102
|
- README.rdoc
|
103
|
+
- TODO.rdoc
|
99
104
|
files:
|
100
105
|
- CHANGELOG.rdoc
|
101
106
|
- examples/README.rdoc
|
102
107
|
- init.rb
|
103
108
|
- lib/searchgasm/active_record/associations.rb
|
104
109
|
- lib/searchgasm/active_record/base.rb
|
110
|
+
- lib/searchgasm/active_record/connection_adapters/mysql_adapter.rb
|
111
|
+
- lib/searchgasm/active_record/connection_adapters/postgresql_adapter.rb
|
112
|
+
- lib/searchgasm/active_record/connection_adapters/sqlite_adapter.rb
|
105
113
|
- lib/searchgasm/condition/base.rb
|
106
114
|
- lib/searchgasm/condition/begins_with.rb
|
115
|
+
- lib/searchgasm/condition/blank.rb
|
107
116
|
- lib/searchgasm/condition/child_of.rb
|
108
117
|
- lib/searchgasm/condition/contains.rb
|
109
118
|
- lib/searchgasm/condition/descendant_of.rb
|
110
119
|
- lib/searchgasm/condition/does_not_equal.rb
|
120
|
+
- lib/searchgasm/condition/during_evening.rb
|
111
121
|
- lib/searchgasm/condition/ends_with.rb
|
112
122
|
- lib/searchgasm/condition/equals.rb
|
113
123
|
- lib/searchgasm/condition/greater_than.rb
|
114
124
|
- lib/searchgasm/condition/greater_than_or_equal_to.rb
|
115
125
|
- lib/searchgasm/condition/inclusive_descendant_of.rb
|
116
|
-
- lib/searchgasm/condition/is_blank.rb
|
117
|
-
- lib/searchgasm/condition/is_nil.rb
|
118
126
|
- lib/searchgasm/condition/keywords.rb
|
119
127
|
- lib/searchgasm/condition/less_than.rb
|
120
128
|
- lib/searchgasm/condition/less_than_or_equal_to.rb
|
129
|
+
- lib/searchgasm/condition/nil.rb
|
121
130
|
- lib/searchgasm/condition/sibling_of.rb
|
122
131
|
- lib/searchgasm/condition/tree.rb
|
123
132
|
- lib/searchgasm/conditions/base.rb
|
@@ -165,6 +174,7 @@ files:
|
|
165
174
|
- test/test_search_ordering.rb
|
166
175
|
- test/test_search_pagination.rb
|
167
176
|
- test/test_search_protection.rb
|
177
|
+
- TODO.rdoc
|
168
178
|
- searchgasm.gemspec
|
169
179
|
has_rdoc: true
|
170
180
|
homepage: http://github.com/binarylogic/searchgasm
|
@@ -186,7 +196,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
186
196
|
version:
|
187
197
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
198
|
requirements:
|
189
|
-
- - "
|
199
|
+
- - ">="
|
190
200
|
- !ruby/object:Gem::Version
|
191
201
|
version: "1.2"
|
192
202
|
version:
|
@@ -11,6 +11,7 @@ class TestActiveRecordBase < Test::Unit::TestCase
|
|
11
11
|
assert_equal 1, Account.find(:first).id
|
12
12
|
assert_equal [1,2,3], Account.find(:all, nil).map(&:id)
|
13
13
|
assert_equal [1,2,3], Account.find(:all, {}).map(&:id)
|
14
|
+
assert_equal [1,2,3], Account.find(:all, :select => "id, name").map(&:id)
|
14
15
|
end
|
15
16
|
|
16
17
|
def test_standard_calculations
|
data/test/test_condition_base.rb
CHANGED
@@ -12,16 +12,18 @@ class TestConditionBase < Test::Unit::TestCase
|
|
12
12
|
assert_equal nil, Searchgasm::Condition::Keywords.name_for_column(Account.columns_hash["id"])
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
assert !Searchgasm::Condition::Equals.
|
17
|
-
assert Searchgasm::Condition::Keywords.
|
15
|
+
def test_ignore_meaningless?
|
16
|
+
assert !Searchgasm::Condition::Equals.ignore_meaningless?
|
17
|
+
assert Searchgasm::Condition::Keywords.ignore_meaningless?
|
18
|
+
assert !Searchgasm::Condition::DoesNotEqual.ignore_meaningless?
|
18
19
|
end
|
19
20
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
def test_type_cast_sql_type
|
22
|
+
assert_equal nil, Searchgasm::Condition::Equals.type_cast_sql_type
|
23
|
+
assert_equal nil, Searchgasm::Condition::Keywords.type_cast_sql_type
|
24
|
+
assert_equal "boolean", Searchgasm::Condition::Nil.type_cast_sql_type
|
25
|
+
assert_equal "boolean", Searchgasm::Condition::Blank.type_cast_sql_type
|
26
|
+
assert_equal nil, Searchgasm::Condition::GreaterThan.type_cast_sql_type
|
25
27
|
end
|
26
28
|
|
27
29
|
def test_string_column
|
@@ -6,6 +6,30 @@ class TestConditionTypes < Test::Unit::TestCase
|
|
6
6
|
condition.value = "Binary"
|
7
7
|
assert_equal condition.sanitize, ["\"accounts\".\"name\" LIKE ?", "Binary%"]
|
8
8
|
|
9
|
+
condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
|
10
|
+
condition.value = true
|
11
|
+
assert_equal condition.sanitize, "\"accounts\".\"id\" is NULL or \"accounts\".\"id\" = ''"
|
12
|
+
|
13
|
+
condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
|
14
|
+
condition.value = false
|
15
|
+
assert_equal condition.sanitize, "\"accounts\".\"id\" is NOT NULL and \"accounts\".\"id\" != ''"
|
16
|
+
|
17
|
+
condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
|
18
|
+
condition.value = "true"
|
19
|
+
assert_equal condition.sanitize, "\"accounts\".\"id\" is NULL or \"accounts\".\"id\" = ''"
|
20
|
+
|
21
|
+
condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
|
22
|
+
condition.value = "false"
|
23
|
+
assert_equal condition.sanitize, "\"accounts\".\"id\" is NOT NULL and \"accounts\".\"id\" != ''"
|
24
|
+
|
25
|
+
condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
|
26
|
+
condition.value = nil
|
27
|
+
assert_equal condition.sanitize, nil
|
28
|
+
|
29
|
+
condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash["id"])
|
30
|
+
condition.value = ""
|
31
|
+
assert_equal condition.sanitize, nil
|
32
|
+
|
9
33
|
condition = Searchgasm::Condition::ChildOf.new(User)
|
10
34
|
condition.value = User.first.id
|
11
35
|
assert_equal condition.sanitize, ["\"users\".\"parent_id\" = ?", User.first.id]
|
@@ -62,51 +86,27 @@ class TestConditionTypes < Test::Unit::TestCase
|
|
62
86
|
condition.value = User.find(1)
|
63
87
|
assert_equal condition.sanitize, ["(\"users\".\"id\" = ?) OR (\"users\".\"id\" = ? OR \"users\".\"id\" = ?)", 1, 2, 3]
|
64
88
|
|
65
|
-
condition = Searchgasm::Condition::
|
66
|
-
condition.value = true
|
67
|
-
assert_equal condition.sanitize, "\"accounts\".\"id\" is NULL or \"accounts\".\"id\" = ''"
|
68
|
-
|
69
|
-
condition = Searchgasm::Condition::IsBlank.new(Account, Account.columns_hash["id"])
|
70
|
-
condition.value = false
|
71
|
-
assert_equal condition.sanitize, "\"accounts\".\"id\" is NOT NULL and \"accounts\".\"id\" != ''"
|
72
|
-
|
73
|
-
condition = Searchgasm::Condition::IsBlank.new(Account, Account.columns_hash["id"])
|
74
|
-
condition.value = "true"
|
75
|
-
assert_equal condition.sanitize, "\"accounts\".\"id\" is NULL or \"accounts\".\"id\" = ''"
|
76
|
-
|
77
|
-
condition = Searchgasm::Condition::IsBlank.new(Account, Account.columns_hash["id"])
|
78
|
-
condition.value = "false"
|
79
|
-
assert_equal condition.sanitize, "\"accounts\".\"id\" is NOT NULL and \"accounts\".\"id\" != ''"
|
80
|
-
|
81
|
-
condition = Searchgasm::Condition::IsBlank.new(Account, Account.columns_hash["id"])
|
82
|
-
condition.value = nil
|
83
|
-
assert_equal condition.sanitize, nil
|
84
|
-
|
85
|
-
condition = Searchgasm::Condition::IsBlank.new(Account, Account.columns_hash["id"])
|
86
|
-
condition.value = ""
|
87
|
-
assert_equal condition.sanitize, nil
|
88
|
-
|
89
|
-
condition = Searchgasm::Condition::IsNil.new(Account, Account.columns_hash["id"])
|
89
|
+
condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash["id"])
|
90
90
|
condition.value = true
|
91
91
|
assert_equal condition.sanitize, "\"accounts\".\"id\" is NULL"
|
92
92
|
|
93
|
-
condition = Searchgasm::Condition::
|
93
|
+
condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash["id"])
|
94
94
|
condition.value = false
|
95
95
|
assert_equal condition.sanitize, "\"accounts\".\"id\" is NOT NULL"
|
96
96
|
|
97
|
-
condition = Searchgasm::Condition::
|
97
|
+
condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash["id"])
|
98
98
|
condition.value = "true"
|
99
99
|
assert_equal condition.sanitize, "\"accounts\".\"id\" is NULL"
|
100
100
|
|
101
|
-
condition = Searchgasm::Condition::
|
101
|
+
condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash["id"])
|
102
102
|
condition.value = "false"
|
103
103
|
assert_equal condition.sanitize, "\"accounts\".\"id\" is NOT NULL"
|
104
104
|
|
105
|
-
condition = Searchgasm::Condition::
|
105
|
+
condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash["id"])
|
106
106
|
condition.value = nil
|
107
107
|
assert_equal condition.sanitize, nil
|
108
108
|
|
109
|
-
condition = Searchgasm::Condition::
|
109
|
+
condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash["id"])
|
110
110
|
condition.value = ""
|
111
111
|
assert_equal condition.sanitize, nil
|
112
112
|
|
@@ -22,6 +22,7 @@ class TestConditionsBase < Test::Unit::TestCase
|
|
22
22
|
assert !Searchgasm::Conditions::Base.needed?(User, {})
|
23
23
|
assert !Searchgasm::Conditions::Base.needed?(User, {:first_name => "Ben"})
|
24
24
|
assert Searchgasm::Conditions::Base.needed?(User, {:first_name_contains => "Awesome"})
|
25
|
+
assert !Searchgasm::Conditions::Base.needed?(User, {"orders.id" => 2})
|
25
26
|
end
|
26
27
|
|
27
28
|
def test_initialize
|
data/test/test_search_base.rb
CHANGED
@@ -180,6 +180,10 @@ class TestSearchBase < Test::Unit::TestCase
|
|
180
180
|
assert_equal [Account.find(1)], search.find(:all)
|
181
181
|
assert_equal Account.find(1), search.first
|
182
182
|
assert_equal Account.find(1), search.find(:first)
|
183
|
+
|
184
|
+
search = Account.new_search
|
185
|
+
search.select = "id, name"
|
186
|
+
assert_equal Account.all, search.all
|
183
187
|
end
|
184
188
|
|
185
189
|
def test_calculations
|
@@ -1,6 +1,18 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
2
|
|
3
3
|
class TestSearchOrdering < Test::Unit::TestCase
|
4
|
+
def test_order_to_order_by
|
5
|
+
search = Account.new_search
|
6
|
+
search.order = "name"
|
7
|
+
assert_equal "name", search.order_by
|
8
|
+
search.order = "users.first_name"
|
9
|
+
assert_equal({"users" => "first_name"}, search.order_by)
|
10
|
+
search.order = "\"users\".\"first_name\""
|
11
|
+
assert_equal({"users" => "first_name"}, search.order_by)
|
12
|
+
search.order = "\"users\".\"first_name\", name ASC"
|
13
|
+
assert_equal([{"users" => "first_name"}, "name"], search.order_by)
|
14
|
+
end
|
15
|
+
|
4
16
|
def test_order_by
|
5
17
|
search = Account.new_search
|
6
18
|
assert_equal nil, search.order
|
@@ -55,7 +67,8 @@ class TestSearchOrdering < Test::Unit::TestCase
|
|
55
67
|
search = Account.new_search
|
56
68
|
assert_equal nil, search.order
|
57
69
|
assert_equal nil, search.order_as
|
58
|
-
assert
|
70
|
+
assert search.asc?
|
71
|
+
assert !search.desc?
|
59
72
|
|
60
73
|
search.order_as = "DESC"
|
61
74
|
assert_equal nil, search.order_as
|
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.2.
|
4
|
+
version: 1.2.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-09-
|
12
|
+
date: 2008-09-29 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -52,22 +52,26 @@ extra_rdoc_files:
|
|
52
52
|
- CHANGELOG.rdoc
|
53
53
|
- lib/searchgasm/active_record/associations.rb
|
54
54
|
- lib/searchgasm/active_record/base.rb
|
55
|
+
- lib/searchgasm/active_record/connection_adapters/mysql_adapter.rb
|
56
|
+
- lib/searchgasm/active_record/connection_adapters/postgresql_adapter.rb
|
57
|
+
- lib/searchgasm/active_record/connection_adapters/sqlite_adapter.rb
|
55
58
|
- lib/searchgasm/condition/base.rb
|
56
59
|
- lib/searchgasm/condition/begins_with.rb
|
60
|
+
- lib/searchgasm/condition/blank.rb
|
57
61
|
- lib/searchgasm/condition/child_of.rb
|
58
62
|
- lib/searchgasm/condition/contains.rb
|
59
63
|
- lib/searchgasm/condition/descendant_of.rb
|
60
64
|
- lib/searchgasm/condition/does_not_equal.rb
|
65
|
+
- lib/searchgasm/condition/during_evening.rb
|
61
66
|
- lib/searchgasm/condition/ends_with.rb
|
62
67
|
- lib/searchgasm/condition/equals.rb
|
63
68
|
- lib/searchgasm/condition/greater_than.rb
|
64
69
|
- lib/searchgasm/condition/greater_than_or_equal_to.rb
|
65
70
|
- lib/searchgasm/condition/inclusive_descendant_of.rb
|
66
|
-
- lib/searchgasm/condition/is_blank.rb
|
67
|
-
- lib/searchgasm/condition/is_nil.rb
|
68
71
|
- lib/searchgasm/condition/keywords.rb
|
69
72
|
- lib/searchgasm/condition/less_than.rb
|
70
73
|
- lib/searchgasm/condition/less_than_or_equal_to.rb
|
74
|
+
- lib/searchgasm/condition/nil.rb
|
71
75
|
- lib/searchgasm/condition/sibling_of.rb
|
72
76
|
- lib/searchgasm/condition/tree.rb
|
73
77
|
- lib/searchgasm/conditions/base.rb
|
@@ -93,28 +97,33 @@ extra_rdoc_files:
|
|
93
97
|
- lib/searchgasm/version.rb
|
94
98
|
- lib/searchgasm.rb
|
95
99
|
- README.rdoc
|
100
|
+
- TODO.rdoc
|
96
101
|
files:
|
97
102
|
- CHANGELOG.rdoc
|
98
103
|
- examples/README.rdoc
|
99
104
|
- init.rb
|
100
105
|
- lib/searchgasm/active_record/associations.rb
|
101
106
|
- lib/searchgasm/active_record/base.rb
|
107
|
+
- lib/searchgasm/active_record/connection_adapters/mysql_adapter.rb
|
108
|
+
- lib/searchgasm/active_record/connection_adapters/postgresql_adapter.rb
|
109
|
+
- lib/searchgasm/active_record/connection_adapters/sqlite_adapter.rb
|
102
110
|
- lib/searchgasm/condition/base.rb
|
103
111
|
- lib/searchgasm/condition/begins_with.rb
|
112
|
+
- lib/searchgasm/condition/blank.rb
|
104
113
|
- lib/searchgasm/condition/child_of.rb
|
105
114
|
- lib/searchgasm/condition/contains.rb
|
106
115
|
- lib/searchgasm/condition/descendant_of.rb
|
107
116
|
- lib/searchgasm/condition/does_not_equal.rb
|
117
|
+
- lib/searchgasm/condition/during_evening.rb
|
108
118
|
- lib/searchgasm/condition/ends_with.rb
|
109
119
|
- lib/searchgasm/condition/equals.rb
|
110
120
|
- lib/searchgasm/condition/greater_than.rb
|
111
121
|
- lib/searchgasm/condition/greater_than_or_equal_to.rb
|
112
122
|
- lib/searchgasm/condition/inclusive_descendant_of.rb
|
113
|
-
- lib/searchgasm/condition/is_blank.rb
|
114
|
-
- lib/searchgasm/condition/is_nil.rb
|
115
123
|
- lib/searchgasm/condition/keywords.rb
|
116
124
|
- lib/searchgasm/condition/less_than.rb
|
117
125
|
- lib/searchgasm/condition/less_than_or_equal_to.rb
|
126
|
+
- lib/searchgasm/condition/nil.rb
|
118
127
|
- lib/searchgasm/condition/sibling_of.rb
|
119
128
|
- lib/searchgasm/condition/tree.rb
|
120
129
|
- lib/searchgasm/conditions/base.rb
|
@@ -162,6 +171,7 @@ files:
|
|
162
171
|
- test/test_search_ordering.rb
|
163
172
|
- test/test_search_pagination.rb
|
164
173
|
- test/test_search_protection.rb
|
174
|
+
- TODO.rdoc
|
165
175
|
- searchgasm.gemspec
|
166
176
|
has_rdoc: true
|
167
177
|
homepage: http://github.com/binarylogic/searchgasm
|
@@ -183,7 +193,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
193
|
version:
|
184
194
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
195
|
requirements:
|
186
|
-
- - "
|
196
|
+
- - ">="
|
187
197
|
- !ruby/object:Gem::Version
|
188
198
|
version: "1.2"
|
189
199
|
version:
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Searchgasm
|
2
|
-
module Condition
|
3
|
-
class IsNil < Base
|
4
|
-
self.ignore_blanks = false
|
5
|
-
self.type_cast_value = false
|
6
|
-
|
7
|
-
class << self
|
8
|
-
def aliases_for_column(column)
|
9
|
-
["#{column.name}_nil", "#{column.name}_is_null", "#{column.name}_null"]
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def to_conditions(value)
|
14
|
-
# Some databases handle null values differently, let AR handle this
|
15
|
-
if value == true || value == "true" || value == 1 || value == "1"
|
16
|
-
"#{quoted_table_name}.#{quoted_column_name} is NULL"
|
17
|
-
elsif value == false || value == "false" || value == 0 || value == "0"
|
18
|
-
"#{quoted_table_name}.#{quoted_column_name} is NOT NULL"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|