kazjote-searchlogic 2.1.9.3 → 2.3.4

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.
@@ -1,11 +1,27 @@
1
1
  module Searchlogic
2
2
  module NamedScopes
3
- # Handles dynamically creating named scopes for associations.
3
+ # Handles dynamically creating order named scopes for associations:
4
+ #
5
+ # User.has_many :orders
6
+ # Order.has_many :line_items
7
+ # LineItem
8
+ #
9
+ # User.ascend_by_orders_line_items_id
10
+ #
11
+ # See the README for a more detailed explanation.
4
12
  module AssociationOrdering
13
+ def condition?(name) # :nodoc:
14
+ super || association_ordering_condition?(name)
15
+ end
16
+
5
17
  private
18
+ def association_ordering_condition?(name)
19
+ !association_ordering_condition_details(name).nil?
20
+ end
21
+
6
22
  def method_missing(name, *args, &block)
7
23
  if details = association_ordering_condition_details(name)
8
- create_association_ordering_condition(details[:association], details[:order_as], details[:column], args)
24
+ create_association_ordering_condition(details[:association], details[:order_as], details[:condition], args)
9
25
  send(name, *args)
10
26
  else
11
27
  super
@@ -14,13 +30,13 @@ module Searchlogic
14
30
 
15
31
  def association_ordering_condition_details(name)
16
32
  associations = reflect_on_all_associations.collect { |assoc| assoc.name }
17
- if !local_condition?(name) && name.to_s =~ /^(ascend|descend)_by_(#{associations.join("|")})_(\w+)$/
18
- {:order_as => $1, :association => $2, :column => $3}
33
+ if name.to_s =~ /^(ascend|descend)_by_(#{associations.join("|")})_(\w+)$/
34
+ {:order_as => $1, :association => $2, :condition => $3}
19
35
  end
20
36
  end
21
37
 
22
- def create_association_ordering_condition(association_name, order_as, column, args)
23
- named_scope("#{order_as}_by_#{association_name}_#{column}", association_condition_options(association_name, "#{order_as}_by_#{column}", args))
38
+ def create_association_ordering_condition(association, order_as, condition, args)
39
+ named_scope("#{order_as}_by_#{association}_#{condition}", association_condition_options(association, "#{order_as}_by_#{condition}", args))
24
40
  end
25
41
  end
26
42
  end
@@ -1,6 +1,13 @@
1
1
  module Searchlogic
2
2
  module NamedScopes
3
- # Handles dynamically creating named scopes for columns.
3
+ # Handles dynamically creating named scopes for columns. It allows you to do things like:
4
+ #
5
+ # User.first_name_like("ben")
6
+ # User.id_lt(10)
7
+ #
8
+ # Notice the constants in this class, they define which conditions Searchlogic provides.
9
+ #
10
+ # See the README for a more detailed explanation.
4
11
  module Conditions
5
12
  COMPARISON_CONDITIONS = {
6
13
  :equals => [:is, :eq],
@@ -23,11 +30,14 @@ module Searchlogic
23
30
  BOOLEAN_CONDITIONS = {
24
31
  :null => [:nil],
25
32
  :not_null => [:not_nil],
26
- :empty => []
33
+ :empty => [],
34
+ :blank => [],
35
+ :not_blank => [:present]
27
36
  }
28
37
 
29
38
  CONDITIONS = {}
30
39
 
40
+ # Add any / all variations to every comparison and wildcard condition
31
41
  COMPARISON_CONDITIONS.merge(WILDCARD_CONDITIONS).each do |condition, aliases|
32
42
  CONDITIONS[condition] = aliases
33
43
  CONDITIONS["#{condition}_any".to_sym] = aliases.collect { |a| "#{a}_any".to_sym }
@@ -39,112 +49,48 @@ module Searchlogic
39
49
  PRIMARY_CONDITIONS = CONDITIONS.keys
40
50
  ALIAS_CONDITIONS = CONDITIONS.values.flatten
41
51
 
42
- # Retrieves the options passed when creating the respective named scope. Ex:
43
- #
44
- # named_scope :whatever, :conditions => {:column => value}
45
- #
46
- # This method will return:
47
- #
48
- # :conditions => {:column => value}
49
- #
50
- # ActiveRecord hides this internally, so we have to try and pull it out with this
51
- # method.
52
- def named_scope_options(name)
53
- key = scopes.key?(name.to_sym) ? name.to_sym : primary_condition_name(name)
54
-
55
- if key
56
- eval("options", scopes[key])
57
- else
58
- nil
59
- end
60
- end
61
-
62
- # The arity for a named scope's proc is important, because we use the arity
63
- # to determine if the condition should be ignored when calling the search method.
64
- # If the condition is false and the arity is 0, then we skip it all together. Ex:
65
- #
66
- # User.named_scope :age_is_4, :conditions => {:age => 4}
67
- # User.search(:age_is_4 => false) == User.all
68
- # User.search(:age_is_4 => true) == User.all(:conditions => {:age => 4})
69
- #
70
- # We also use it when trying to "copy" the underlying named scope for association
71
- # conditions.
72
- def named_scope_arity(name)
73
- options = named_scope_options(name)
74
- options.respond_to?(:arity) ? options.arity : nil
75
- end
76
-
77
- # Returns the primary condition for the given alias. Ex:
78
- #
79
- # primary_condition(:gt) => :greater_than
80
- def primary_condition(alias_condition)
81
- CONDITIONS.find { |k, v| k == alias_condition.to_sym || v.include?(alias_condition.to_sym) }.first
82
- end
83
-
84
- # Returns the primary name for any condition on a column. You can pass it
85
- # a primary condition, alias condition, etc, and it will return the proper
86
- # primary condition name. This helps simply logic throughout Searchlogic. Ex:
87
- #
88
- # primary_condition_name(:id_gt) => :id_greater_than
89
- # primary_condition_name(:id_greater_than) => :id_greater_than
90
- def primary_condition_name(name)
91
- if primary_condition?(name)
92
- name.to_sym
93
- elsif details = alias_condition_details(name)
94
- "#{details[:column]}_#{primary_condition(details[:condition])}".to_sym
95
- else
96
- nil
97
- end
98
- end
99
-
100
52
  # Is the name of the method a valid condition that can be dynamically created?
101
53
  def condition?(name)
102
54
  local_condition?(name)
103
55
  end
104
56
 
105
- # Is the condition for a local column, not an association
106
- def local_condition?(name)
107
- primary_condition?(name) || alias_condition?(name)
108
- end
109
-
110
- # Is the name of the method a valid condition that can be dynamically created,
111
- # AND is it a primary condition (not an alias). "greater_than" not "gt".
112
- def primary_condition?(name)
113
- !primary_condition_details(name).nil?
114
- end
115
-
116
- # Is the name of the method a valid condition that can be dynamically created,
117
- # AND is it an alias condition. "gt" not "greater_than".
118
- def alias_condition?(name)
119
- !alias_condition_details(name).nil?
120
- end
121
-
122
57
  private
58
+ def local_condition?(name)
59
+ return false if name.blank?
60
+ scope_names = scopes.keys.reject { |k| k == :scoped }
61
+ scope_names.include?(name.to_sym) || !condition_details(name).nil?
62
+ end
63
+
123
64
  def method_missing(name, *args, &block)
124
- if details = primary_condition_details(name)
125
- create_primary_condition(details[:column], details[:condition])
126
- send(name, *args)
127
- elsif details = alias_condition_details(name)
128
- create_alias_condition(details[:column], details[:condition], args)
65
+ if details = condition_details(name)
66
+ create_condition(details[:column], details[:condition], args)
129
67
  send(name, *args)
130
68
  else
131
69
  super
132
70
  end
133
71
  end
134
72
 
135
- def primary_condition_details(name)
136
- if name.to_s =~ /^(#{column_names.join("|")})_(#{PRIMARY_CONDITIONS.join("|")})$/
73
+ def condition_details(name)
74
+ if name.to_s =~ /^(#{column_names.join("|")})_(#{(PRIMARY_CONDITIONS + ALIAS_CONDITIONS).join("|")})$/
137
75
  {:column => $1, :condition => $2}
138
76
  end
139
77
  end
140
78
 
79
+ def create_condition(column, condition, args)
80
+ if PRIMARY_CONDITIONS.include?(condition.to_sym)
81
+ create_primary_condition(column, condition)
82
+ elsif ALIAS_CONDITIONS.include?(condition.to_sym)
83
+ create_alias_condition(column, condition, args)
84
+ end
85
+ end
86
+
141
87
  def create_primary_condition(column, condition)
142
88
  column_type = columns_hash[column.to_s].type
143
- match_keyword = ActiveRecord::Base.connection.adapter_name == "PostgreSQL" ?
144
- "ILIKE" : "LIKE"
89
+ match_keyword = ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" ? "ILIKE" : "LIKE"
90
+
145
91
  scope_options = case condition.to_s
146
92
  when /^equals/
147
- scope_options(condition, column_type, "#{table_name}.#{column} = ?")
93
+ scope_options(condition, column_type, lambda { |a| attribute_condition("#{table_name}.#{column}", a) })
148
94
  when /^does_not_equal/
149
95
  scope_options(condition, column_type, "#{table_name}.#{column} != ?")
150
96
  when /^less_than_or_equal_to/
@@ -173,6 +119,10 @@ module Searchlogic
173
119
  {:conditions => "#{table_name}.#{column} IS NOT NULL"}
174
120
  when "empty"
175
121
  {:conditions => "#{table_name}.#{column} = ''"}
122
+ when "blank"
123
+ {:conditions => "#{table_name}.#{column} = '' OR #{table_name}.#{column} IS NULL"}
124
+ when "not_blank"
125
+ {:conditions => "#{table_name}.#{column} != '' AND #{table_name}.#{column} IS NOT NULL"}
176
126
  end
177
127
 
178
128
  named_scope("#{column}_#{condition}".to_sym, scope_options)
@@ -186,20 +136,22 @@ module Searchlogic
186
136
  when /_(any|all)$/
187
137
  searchlogic_lambda(column_type) { |*values|
188
138
  return {} if values.empty?
189
- values = values.flatten
190
-
191
- values_to_sub = nil
192
- if value_modifier.nil?
193
- values_to_sub = values
194
- else
195
- values_to_sub = values.collect { |value| value_with_modifier(value, value_modifier) }
196
- end
139
+ values.flatten!
140
+ values.collect! { |value| value_with_modifier(value, value_modifier) }
197
141
 
198
142
  join = $1 == "any" ? " OR " : " AND "
199
- {:conditions => [values.collect { |value| sql }.join(join), *values_to_sub]}
143
+ scope_sql = values.collect { |value| sql.is_a?(Proc) ? sql.call(value) : sql }.join(join)
144
+
145
+ {:conditions => [scope_sql, *expand_range_bind_variables(values)]}
200
146
  }
201
147
  else
202
- searchlogic_lambda(column_type) { |value| {:conditions => [sql, value_with_modifier(value, value_modifier)]} }
148
+ searchlogic_lambda(column_type) { |*values|
149
+ values.collect! { |value| value_with_modifier(value, value_modifier) }
150
+
151
+ scope_sql = sql.is_a?(Proc) ? sql.call(*values) : sql
152
+
153
+ {:conditions => [scope_sql, *expand_range_bind_variables(values)]}
154
+ }
203
155
  end
204
156
  end
205
157
 
@@ -216,12 +168,6 @@ module Searchlogic
216
168
  end
217
169
  end
218
170
 
219
- def alias_condition_details(name)
220
- if name.to_s =~ /^(#{column_names.join("|")})_(#{ALIAS_CONDITIONS.join("|")})$/
221
- {:column => $1, :condition => $2}
222
- end
223
- end
224
-
225
171
  def create_alias_condition(column, condition, args)
226
172
  primary_condition = primary_condition(condition)
227
173
  alias_name = "#{column}_#{condition}"
@@ -229,6 +175,31 @@ module Searchlogic
229
175
  send(primary_name, *args) # go back to method_missing and make sure we create the method
230
176
  (class << self; self; end).class_eval { alias_method alias_name, primary_name }
231
177
  end
178
+
179
+ # Returns the primary condition for the given alias. Ex:
180
+ #
181
+ # primary_condition(:gt) => :greater_than
182
+ def primary_condition(alias_condition)
183
+ CONDITIONS.find { |k, v| k == alias_condition.to_sym || v.include?(alias_condition.to_sym) }.first
184
+ end
185
+
186
+ # Returns the primary name for any condition on a column. You can pass it
187
+ # a primary condition, alias condition, etc, and it will return the proper
188
+ # primary condition name. This helps simply logic throughout Searchlogic. Ex:
189
+ #
190
+ # primary_condition_name(:id_gt) => :id_greater_than
191
+ # primary_condition_name(:id_greater_than) => :id_greater_than
192
+ def primary_condition_name(name)
193
+ if details = condition_details(name)
194
+ if PRIMARY_CONDITIONS.include?(name.to_sym)
195
+ name
196
+ else
197
+ "#{details[:column]}_#{primary_condition(details[:condition])}".to_sym
198
+ end
199
+ else
200
+ nil
201
+ end
202
+ end
232
203
  end
233
204
  end
234
205
  end
@@ -0,0 +1,116 @@
1
+ module Searchlogic
2
+ module NamedScopes
3
+ # Handles dynamically creating named scopes for 'OR' conditions. Please see the README for a more
4
+ # detailed explanation.
5
+ module OrConditions
6
+ class NoConditionSpecifiedError < StandardError; end
7
+ class UnknownConditionError < StandardError; end
8
+
9
+ def condition?(name) # :nodoc:
10
+ super || or_condition?(name)
11
+ end
12
+
13
+ private
14
+ def or_condition?(name)
15
+ !or_conditions(name).nil?
16
+ end
17
+
18
+ def method_missing(name, *args, &block)
19
+ if conditions = or_conditions(name)
20
+ create_or_condition(conditions, args)
21
+ (class << self; self; end).class_eval { alias_method name, conditions.join("_or_") } if !respond_to?(name)
22
+ send(name, *args)
23
+ else
24
+ super
25
+ end
26
+ end
27
+
28
+ def or_conditions(name)
29
+ # First determine if we should even work on the name, we want to be as quick as possible
30
+ # with this.
31
+ if (parts = split_or_condition(name)).size > 1
32
+ conditions = interpolate_or_conditions(parts)
33
+ if conditions.any?
34
+ conditions
35
+ else
36
+ nil
37
+ end
38
+ end
39
+ end
40
+
41
+ def split_or_condition(name)
42
+ parts = name.to_s.split("_or_")
43
+ new_parts = []
44
+ parts.each do |part|
45
+ if part =~ /^equal_to(_any|_all)?$/
46
+ new_parts << new_parts.pop + "_or_equal_to"
47
+ else
48
+ new_parts << part
49
+ end
50
+ end
51
+ new_parts
52
+ end
53
+
54
+ # The purpose of this method is to convert the method name parts into actual condition names.
55
+ #
56
+ # Example:
57
+ #
58
+ # ["first_name", "last_name_like"]
59
+ # => ["first_name_like", "last_name_like"]
60
+ #
61
+ # ["id_gt", "first_name_begins_with", "last_name", "middle_name_like"]
62
+ # => ["id_gt", "first_name_begins_with", "last_name_like", "middle_name_like"]
63
+ #
64
+ # Basically if a column is specified without a condition the next condition in the list
65
+ # is what will be used. Once we are able to get a consistent list of conditions we can easily
66
+ # create a scope for it.
67
+ def interpolate_or_conditions(parts)
68
+ conditions = []
69
+ last_condition = nil
70
+
71
+ parts.reverse.each do |part|
72
+ if details = condition_details(part)
73
+ # We are a searchlogic defined scope
74
+ conditions << "#{details[:column]}_#{details[:condition]}"
75
+ last_condition = details[:condition]
76
+ elsif details = association_condition_details(part)
77
+ # pending, need to find the last condition
78
+ elsif local_condition?(part)
79
+ # We are a custom scope
80
+ conditions << part
81
+ elsif column_names.include?(part)
82
+ # we are a column, use the last condition
83
+ if last_condition.nil?
84
+ raise NoConditionSpecifiedError.new("The '#{part}' column doesn't know which condition to use, if you use an exact column " +
85
+ "name you need to specify a condition sometime after (ex: id_or_created_at_lt), where id would use the 'lt' condition.")
86
+ end
87
+
88
+ conditions << "#{part}_#{last_condition}"
89
+ else
90
+ raise UnknownConditionError.new("The condition '#{part}' is not a valid condition, we could not find any scopes that match this.")
91
+ end
92
+ end
93
+
94
+ conditions
95
+ end
96
+
97
+ def create_or_condition(scopes, args)
98
+ named_scope scopes.join("_or_"), lambda { |*args|
99
+ merge_scopes_with_or(scopes.collect { |scope| [scope, *args] })
100
+ }
101
+ end
102
+
103
+ def merge_scopes_with_or(scopes)
104
+ scopes_options = scopes.collect { |scope, *args| send(scope, *args).proxy_options }
105
+ conditions = scopes_options.reject { |o| o[:conditions].nil? }.collect { |o| sanitize_sql(o[:conditions]) }
106
+
107
+ scope = scopes.inject(scoped({})) do |scope, info|
108
+ scope_name, *args = info
109
+ scope.send(scope_name, *args)
110
+ end
111
+
112
+ scope.scope(:find).merge(:conditions => "(" + conditions.join(") OR (") + ")")
113
+ end
114
+ end
115
+ end
116
+ end
@@ -1,42 +1,37 @@
1
1
  module Searchlogic
2
2
  module NamedScopes
3
- # Handles dynamically creating named scopes for orderin by columns.
3
+ # Handles dynamically creating named scopes for ordering by columns. Example:
4
+ #
5
+ # User.ascend_by_id
6
+ # User.descend_by_username
7
+ #
8
+ # See the README for a more detailed explanation.
4
9
  module Ordering
5
- def local_condition?(name) # :nodoc:
6
- super || order_condition?(name)
7
- end
8
-
9
- def primary_condition_name(name) # :nodoc
10
- if result = super
11
- result
12
- elsif order_condition?(name)
13
- name.to_sym
14
- else
15
- nil
16
- end
17
- end
18
-
19
- def order_condition?(name) # :nodoc:
20
- !order_condition_details(name).nil?
10
+ def condition?(name) # :nodoc:
11
+ super || ordering_condition?(name)
21
12
  end
22
13
 
23
14
  private
15
+ def ordering_condition?(name) # :nodoc:
16
+ !ordering_condition_details(name).nil?
17
+ end
18
+
24
19
  def method_missing(name, *args, &block)
25
20
  if name == :order
26
21
  named_scope name, lambda { |scope_name|
27
- return {} if !order_condition?(scope_name)
22
+ return {} if !condition?(scope_name)
28
23
  send(scope_name).proxy_options
29
24
  }
30
25
  send(name, *args)
31
- elsif details = order_condition_details(name)
32
- create_order_conditions(details[:column])
26
+ elsif details = ordering_condition_details(name)
27
+ create_ordering_conditions(details[:column])
33
28
  send(name, *args)
34
29
  else
35
30
  super
36
31
  end
37
32
  end
38
33
 
39
- def order_condition_details(name)
34
+ def ordering_condition_details(name)
40
35
  if name.to_s =~ /^(ascend|descend)_by_(#{column_names.join("|")})$/
41
36
  {:order_as => $1, :column => $2}
42
37
  elsif name.to_s =~ /^order$/
@@ -44,7 +39,7 @@ module Searchlogic
44
39
  end
45
40
  end
46
41
 
47
- def create_order_conditions(column)
42
+ def create_ordering_conditions(column)
48
43
  named_scope("ascend_by_#{column}".to_sym, {:order => "#{table_name}.#{column} ASC"})
49
44
  named_scope("descend_by_#{column}".to_sym, {:order => "#{table_name}.#{column} DESC"})
50
45
  end
@@ -17,10 +17,14 @@ module Searchlogic
17
17
  # * <tt>:as</tt> - the text used in the link, defaults to whatever is passed to :by
18
18
  # * <tt>:ascend_scope</tt> - what scope to call for ascending the data, defaults to "ascend_by_:by"
19
19
  # * <tt>:descend_scope</tt> - what scope to call for descending the data, defaults to "descend_by_:by"
20
+ # * <tt>:params</tt> - hash with additional params which will be added to generated url
20
21
  # * <tt>:params_scope</tt> - the name of the params key to scope the order condition by, defaults to :search
21
22
  def order(search, options = {}, html_options = {})
22
23
  options[:params_scope] ||= :search
23
- options[:as] ||= options[:by].to_s.humanize
24
+ if !options[:as]
25
+ id = options[:by].to_s.downcase == "id"
26
+ options[:as] = id ? options[:by].to_s.upcase : options[:by].to_s.humanize
27
+ end
24
28
  options[:ascend_scope] ||= "ascend_by_#{options[:by]}"
25
29
  options[:descend_scope] ||= "descend_by_#{options[:by]}"
26
30
  ascending = search.order.to_s == options[:ascend_scope]
@@ -17,7 +17,7 @@ module Searchlogic
17
17
  class Search
18
18
  # Responsible for adding a "search" method into your models.
19
19
  module Implementation
20
- # Additional method, gets aliases as "search" if that method
20
+ # Additional method, gets aliased as "search" if that method
21
21
  # is available. A lot of other libraries like to use "search"
22
22
  # as well, so if you have a conflict like this, you can use
23
23
  # this method directly.
@@ -25,7 +25,7 @@ module Searchlogic
25
25
  Search.new(self, scope(:find), conditions)
26
26
  end
27
27
  end
28
-
28
+
29
29
  # Is an invalid condition is used this error will be raised. Ex:
30
30
  #
31
31
  # User.search(:unkown => true)
@@ -37,28 +37,32 @@ module Searchlogic
37
37
  super(msg)
38
38
  end
39
39
  end
40
-
41
- attr_accessor :klass, :current_scope, :conditions
40
+
41
+ attr_accessor :klass, :current_scope, :conditions, :default_order
42
42
  undef :id if respond_to?(:id)
43
-
43
+
44
44
  # Creates a new search object for the given class. Ex:
45
45
  #
46
46
  # Searchlogic::Search.new(User, {}, {:username_like => "bjohnson"})
47
47
  def initialize(klass, current_scope, conditions = {})
48
48
  self.klass = klass
49
- self.current_scope = current_scope
49
+ if current_scope
50
+ current_scope = current_scope.dup
51
+ self.default_order = current_scope.delete(:order)
52
+ self.current_scope = current_scope
53
+ end
50
54
  self.conditions = conditions if conditions.is_a?(Hash)
51
55
  end
52
-
56
+
53
57
  def clone
54
58
  self.class.new(klass, current_scope && current_scope.clone, conditions.clone)
55
59
  end
56
-
60
+
57
61
  # Returns a hash of the current conditions set.
58
62
  def conditions
59
63
  @conditions ||= {}
60
64
  end
61
-
65
+
62
66
  # Accepts a hash of conditions.
63
67
  def conditions=(values)
64
68
  values.each do |condition, value|
@@ -67,7 +71,7 @@ module Searchlogic
67
71
  send("#{condition}=", value)
68
72
  end
69
73
  end
70
-
74
+
71
75
  # Delete a condition from the search. Since conditions map to named scopes,
72
76
  # if a named scope accepts a parameter there is no way to actually delete
73
77
  # the scope if you do not want it anymore. A nil value might be meaningful
@@ -76,23 +80,24 @@ module Searchlogic
76
80
  names.each { |name| @conditions.delete(name.to_sym) }
77
81
  self
78
82
  end
79
-
83
+
80
84
  private
81
85
  def method_missing(name, *args, &block)
82
- if name.to_s =~ /(\w+)=$/
83
- condition = $1.to_sym
84
- scope_name = normalize_scope_name($1)
86
+ condition_name = condition_name(name)
87
+ scope_name = scope_name(condition_name)
88
+
89
+ if setter?(name)
85
90
  if scope?(scope_name)
86
- conditions[condition] = type_cast(args.first, cast_type(scope_name))
91
+ conditions[condition_name] = type_cast(args.first, cast_type(scope_name))
87
92
  else
88
- raise UnknownConditionError.new(name)
93
+ raise UnknownConditionError.new(condition_name)
89
94
  end
90
- elsif scope?(normalize_scope_name(name))
95
+ elsif scope?(scope_name)
91
96
  if args.size > 0
92
- send("#{name}=", *args)
97
+ send("#{condition_name}=", *args)
93
98
  self
94
99
  else
95
- conditions[name]
100
+ conditions[condition_name]
96
101
  end
97
102
  else
98
103
  scope = conditions.inject(klass.scoped(current_scope)) do |scope, condition|
@@ -100,7 +105,7 @@ module Searchlogic
100
105
  scope_name = normalize_scope_name(scope_name)
101
106
  klass.send(scope_name, value) if !klass.respond_to?(scope_name)
102
107
  arity = klass.named_scope_arity(scope_name)
103
-
108
+
104
109
  if !arity || arity == 0
105
110
  if value == true
106
111
  scope.send(scope_name)
@@ -111,18 +116,33 @@ module Searchlogic
111
116
  scope.send(scope_name, value)
112
117
  end
113
118
  end
119
+ scope = scope.scoped(:order => default_order) if
120
+ default_order && !scope.proxy_options.has_key?(:order)
114
121
  scope.send(name, *args, &block)
115
122
  end
116
123
  end
117
-
124
+
118
125
  def normalize_scope_name(scope_name)
119
126
  klass.column_names.include?(scope_name.to_s) ? "#{scope_name}_equals".to_sym : scope_name.to_sym
120
127
  end
121
-
128
+
129
+ def setter?(name)
130
+ !(name.to_s =~ /=$/).nil?
131
+ end
132
+
133
+ def condition_name(name)
134
+ condition = name.to_s.match(/(\w+)=?$/)[1]
135
+ condition ? condition.to_sym : nil
136
+ end
137
+
138
+ def scope_name(condition_name)
139
+ condition_name && normalize_scope_name(condition_name)
140
+ end
141
+
122
142
  def scope?(scope_name)
123
143
  klass.scopes.key?(scope_name) || klass.condition?(scope_name)
124
144
  end
125
-
145
+
126
146
  def cast_type(name)
127
147
  klass.send(name, nil) if !klass.respond_to?(name) # We need to set up the named scope if it doesn't exist, so we can get a value for named_ssope_options
128
148
  named_scope_options = klass.named_scope_options(name)
@@ -133,7 +153,7 @@ module Searchlogic
133
153
  named_scope_options.respond_to?(:searchlogic_arg_type) ? named_scope_options.searchlogic_arg_type : :string
134
154
  end
135
155
  end
136
-
156
+
137
157
  def type_cast(value, type)
138
158
  case value
139
159
  when Array
@@ -141,11 +161,12 @@ module Searchlogic
141
161
  else
142
162
  # Let's leverage ActiveRecord's type casting, so that casting is consistent
143
163
  # with the other models.
144
- column_for_type_cast = ActiveRecord::ConnectionAdapters::Column.new("", nil)
164
+ column_for_type_cast = ::ActiveRecord::ConnectionAdapters::Column.new("", nil)
145
165
  column_for_type_cast.instance_variable_set(:@type, type)
146
166
  value = column_for_type_cast.type_cast(value)
147
167
  Time.zone && value.is_a?(Time) ? value.in_time_zone : value
148
168
  end
149
169
  end
150
170
  end
151
- end
171
+ end
172
+