searchlogic 2.4.32 → 2.5.0

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/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 2
3
- :minor: 4
4
- :patch: 32
3
+ :minor: 5
4
+ :patch: 0
5
5
  :build:
@@ -10,7 +10,7 @@ module Searchlogic
10
10
  alias_method_chain :merge_joins, :merged_duplicates
11
11
  end
12
12
  end
13
-
13
+
14
14
  # In AR multiple joins are sometimes in a single join query, and other times they
15
15
  # are not. The merge_joins method in AR should account for this, but it doesn't.
16
16
  # This fixes that problem. This way there is one join per string, which allows
@@ -19,7 +19,7 @@ module Searchlogic
19
19
  joins = merge_joins_without_singularity(*args)
20
20
  joins.collect { |j| j.is_a?(String) ? j.split(" ") : j }.flatten.uniq
21
21
  end
22
-
22
+
23
23
  # This method ensures that the order of the conditions in the joins are the same.
24
24
  # The strings of the joins MUST be exactly the same for AR to remove the duplicates.
25
25
  # AR is not consistent in this approach, resulting in duplicate joins errors when
@@ -38,8 +38,8 @@ module Searchlogic
38
38
  end
39
39
  end.uniq
40
40
  end
41
-
42
-
41
+
42
+
43
43
  def merge_joins_with_merged_duplicates(*args)
44
44
  args << "" if !Thread.current["searchlogic_delegation"]
45
45
  joins = merge_joins_without_merged_duplicates(*args)
@@ -14,14 +14,14 @@ module Searchlogic
14
14
  # method.
15
15
  def named_scope_options(name)
16
16
  key = scopes.key?(name.to_sym) ? name.to_sym : condition_scope_name(name)
17
-
18
- if key
17
+
18
+ if key && scopes[key]
19
19
  eval("options", scopes[key].binding)
20
20
  else
21
21
  nil
22
22
  end
23
23
  end
24
-
24
+
25
25
  # The arity for a named scope's proc is important, because we use the arity
26
26
  # to determine if the condition should be ignored when calling the search method.
27
27
  # If the condition is false and the arity is 0, then we skip it all together. Ex:
@@ -37,7 +37,7 @@ module Searchlogic
37
37
  options = named_scope_options(name)
38
38
  options.respond_to?(:arity) ? options.arity : nil
39
39
  end
40
-
40
+
41
41
  # When searchlogic calls a named_scope on a foreigh model it will execute that scope and then call scope(:find).
42
42
  # When we get these options we want this to be in an exclusive scope, especially if we are calling a condition on
43
43
  # the same originating model:
@@ -58,7 +58,7 @@ module Searchlogic
58
58
  with_exclusive_scope(&block)
59
59
  Thread.current["searchlogic_delegation"] = old
60
60
  end
61
-
61
+
62
62
  # A convenience method for creating inner join sql to that your inner joins
63
63
  # are consistent with how Active Record creates them. Basically a tool for
64
64
  # you to use when writing your own named scopes. This way you know for sure
@@ -71,7 +71,7 @@ module Searchlogic
71
71
  def inner_joins(association_name)
72
72
  ::ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, association_name, nil).join_associations.collect { |assoc| assoc.association_join }
73
73
  end
74
-
74
+
75
75
  # A convenience methods to create a join on a polymorphic associations target.
76
76
  # Ex:
77
77
  #
@@ -91,7 +91,7 @@ module Searchlogic
91
91
  "INNER JOIN #{options[:target_table]} ON #{options[:target_table]}.id = #{options[:on_table_name]}.#{options[:as]}_id AND " +
92
92
  "#{options[:on_table_name]}.#{options[:as]}_type = #{postgres ? "E" : ""}'#{target.to_s.camelize}'"
93
93
  end
94
-
94
+
95
95
  # See inner_joins. Does the same thing except creates LEFT OUTER joins.
96
96
  def left_outer_joins(association_name)
97
97
  ::ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, association_name, nil).join_associations.collect { |assoc| assoc.association_join }
@@ -0,0 +1,22 @@
1
+ module Searchlogic
2
+ module ActiveRecord
3
+ # The internals to ActiveRecord like to do scopes.include?(scope_name). And this is how they check for the existence
4
+ # of scopes, which is terrible. The problem is that searchlogic scopes are dynamically created. So the only solution
5
+ # is to override the include? method for the scopes hash, try to create the named scope, and then check it again.
6
+ # This shouldn't effect performance because once its created it never gets called again. I also cache failed names
7
+ # so we don't try to create them again.
8
+ module Scope
9
+ def scopes
10
+ read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {}.tap do |h|
11
+ h.instance_eval <<-eval
12
+ def include?(key)
13
+ result = super
14
+ return result if result
15
+ super
16
+ end
17
+ eval
18
+ end)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -4,7 +4,7 @@ module Searchlogic
4
4
  def self.included(klass)
5
5
  klass.class_eval do
6
6
  attr_accessor :searchlogic_options
7
-
7
+
8
8
  def searchlogic_options
9
9
  @searchlogic_options ||= {}
10
10
  @searchlogic_options[:type] ||= :string
@@ -45,23 +45,24 @@ module Searchlogic
45
45
  end
46
46
  end
47
47
  alias_method :scope_procedure, :alias_scope
48
-
49
- def alias_scopes # :nodoc:
50
- read_inheritable_attribute(:alias_scopes) || write_inheritable_attribute(:alias_scopes, {})
51
- end
52
-
53
- def alias_scope?(name) # :nodoc:
54
- return false if name.blank?
55
- alias_scopes.key?(name.to_sym)
56
- end
57
-
48
+
58
49
  def condition?(name) # :nodoc:
59
50
  super || alias_scope?(name)
60
51
  end
61
-
52
+
62
53
  def named_scope_options(name) # :nodoc:
63
54
  super || alias_scopes[name.to_sym]
64
55
  end
56
+
57
+ private
58
+ def alias_scopes # :nodoc:
59
+ read_inheritable_attribute(:alias_scopes) || write_inheritable_attribute(:alias_scopes, {})
60
+ end
61
+
62
+ def alias_scope?(name) # :nodoc:
63
+ return false if name.blank?
64
+ alias_scopes.key?(name.to_sym)
65
+ end
65
66
  end
66
67
  end
67
68
  end
@@ -11,12 +11,13 @@ module Searchlogic
11
11
  !association_condition_details(name).nil? unless name.to_s.downcase.match("_or_")
12
12
  end
13
13
 
14
- def method_missing(name, *args, &block)
15
- if !local_condition?(name) && details = association_condition_details(name)
16
- create_association_condition(details[:association], details[:condition], args, details[:poly_class])
17
- send(name, *args)
18
- else
19
- super
14
+ # We need to try and create other conditions first so that we give priority to conflicting names.
15
+ # Such as having a column names the exact same name as an association condition.
16
+ def create_condition(name)
17
+ if result = super
18
+ result
19
+ elsif details = association_condition_details(name)
20
+ create_association_condition(details[:association], details[:condition], details[:poly_class])
20
21
  end
21
22
  end
22
23
 
@@ -51,27 +52,27 @@ module Searchlogic
51
52
  end
52
53
  end
53
54
 
54
- def create_association_condition(association, condition_name, args, poly_class = nil)
55
+ def create_association_condition(association, condition_name, poly_class = nil)
55
56
  name = [association.name, poly_class && "#{poly_class.name.underscore}_type", condition_name].compact.join("_")
56
- named_scope(name, association_condition_options(association, condition_name, args, poly_class))
57
+ named_scope(name, association_condition_options(association, condition_name, poly_class))
57
58
  end
58
59
 
59
- def association_condition_options(association, association_condition, args, poly_class = nil)
60
+ def association_condition_options(association, association_condition, poly_class = nil)
60
61
  klass = poly_class ? poly_class : association.klass
61
- scope = klass.send(association_condition, *args)
62
- scope_options = klass.named_scope_options(association_condition)
62
+ raise ArgumentError.new("The #{klass} class does not respond to the #{association_condition} scope") if !klass.respond_to?(association_condition)
63
63
  arity = klass.named_scope_arity(association_condition)
64
64
 
65
65
  if !arity || arity == 0
66
66
  # The underlying condition doesn't require any parameters, so let's just create a simple
67
67
  # named scope that is based on a hash.
68
68
  options = {}
69
- in_searchlogic_delegation { options = scope.scope(:find) }
69
+ in_searchlogic_delegation { options = klass.send(association_condition).scope(:find) }
70
70
  prepare_named_scope_options(options, association, poly_class)
71
71
  options
72
72
  else
73
- proc_args = arity_args(arity)
73
+ scope_options = klass.named_scope_options(association_condition)
74
74
  scope_options = scope_options.respond_to?(:searchlogic_options) ? scope_options.searchlogic_options.clone : {}
75
+ proc_args = arity_args(arity)
75
76
  arg_type = scope_options.delete(:type) || :string
76
77
 
77
78
  eval <<-"end_eval"
@@ -83,7 +84,6 @@ module Searchlogic
83
84
  options = scope.scope(:find) if scope
84
85
  end
85
86
 
86
-
87
87
  prepare_named_scope_options(options, association, poly_class)
88
88
  options
89
89
  }
@@ -13,21 +13,20 @@ module Searchlogic
13
13
  def condition?(name) # :nodoc:
14
14
  super || association_ordering_condition?(name)
15
15
  end
16
-
16
+
17
17
  private
18
18
  def association_ordering_condition?(name)
19
19
  !association_ordering_condition_details(name).nil?
20
20
  end
21
-
22
- def method_missing(name, *args, &block)
21
+
22
+ def create_condition(name)
23
23
  if details = association_ordering_condition_details(name)
24
- create_association_ordering_condition(details[:association], details[:order_as], details[:condition], args)
25
- send(name, *args)
24
+ create_association_ordering_condition(details[:association], details[:order_as], details[:condition])
26
25
  else
27
26
  super
28
27
  end
29
28
  end
30
-
29
+
31
30
  def association_ordering_condition_details(name)
32
31
  associations = reflect_on_all_associations
33
32
  association_names = associations.collect { |assoc| assoc.name }
@@ -35,8 +34,8 @@ module Searchlogic
35
34
  {:order_as => $1, :association => associations.find { |a| a.name == $2.to_sym }, :condition => $3}
36
35
  end
37
36
  end
38
-
39
- def create_association_ordering_condition(association, order_as, condition, args)
37
+
38
+ def create_association_ordering_condition(association, order_as, condition)
40
39
  cond = condition
41
40
  poly_class = nil
42
41
  if condition =~ /^(\w+)_type_(\w+)$/
@@ -44,7 +43,7 @@ module Searchlogic
44
43
  cond = $2
45
44
  poly_class = poly_type.camelcase.constantize if poly_type
46
45
  end
47
- named_scope("#{order_as}_by_#{association.name}_#{condition}", association_condition_options(association, "#{order_as}_by_#{cond}", args, poly_class))
46
+ named_scope("#{order_as}_by_#{association.name}_#{condition}", association_condition_options(association, "#{order_as}_by_#{cond}", poly_class))
48
47
  end
49
48
  end
50
49
  end
@@ -0,0 +1,16 @@
1
+ module Searchlogic
2
+ module NamedScopes
3
+ module Base
4
+ def condition?(name)
5
+ existing_condition?(name)
6
+ end
7
+
8
+ private
9
+ def existing_condition?(name)
10
+ return false if name.blank?
11
+ @valid_scope_names ||= scopes.keys.reject { |k| k == :scoped }
12
+ @valid_scope_names.include?(name.to_sym)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -8,7 +8,7 @@ module Searchlogic
8
8
  # Notice the constants in this class, they define which conditions Searchlogic provides.
9
9
  #
10
10
  # See the README for a more detailed explanation.
11
- module Conditions
11
+ module ColumnConditions
12
12
  COMPARISON_CONDITIONS = {
13
13
  :equals => [:is, :eq],
14
14
  :does_not_equal => [:not_equal_to, :is_not, :not, :ne],
@@ -54,14 +54,19 @@ module Searchlogic
54
54
 
55
55
  # Is the name of the method a valid condition that can be dynamically created?
56
56
  def condition?(name)
57
- local_condition?(name)
57
+ super || column_condition?(name)
58
+ end
59
+
60
+ # We want to return true for any conditions that can be called, and while we're at it. We might as well
61
+ # create the condition so we don't have to do it again.
62
+ def respond_to?(*args)
63
+ super || (self != ::ActiveRecord::Base && !create_condition(args.first).blank?)
58
64
  end
59
65
 
60
66
  private
61
- def local_condition?(name)
67
+ def column_condition?(name)
62
68
  return false if name.blank?
63
- scope_names = scopes.keys.reject { |k| k == :scoped }
64
- scope_names.include?(name.to_sym) || !condition_details(name).nil? || boolean_condition?(name)
69
+ !condition_details(name).nil? || boolean_condition?(name)
65
70
  end
66
71
 
67
72
  def boolean_condition?(name)
@@ -70,13 +75,8 @@ module Searchlogic
70
75
  end
71
76
 
72
77
  def method_missing(name, *args, &block)
73
- if details = condition_details(name)
74
- create_condition(details[:column], details[:condition], args)
75
- send(name, *args)
76
- elsif boolean_condition?(name)
77
- column = name.to_s.gsub(/^not_/, "")
78
- named_scope name, :conditions => {column => (name.to_s =~ /^not_/).nil?}
79
- send(name)
78
+ if create_condition(name)
79
+ send(name, *args, &block)
80
80
  else
81
81
  super
82
82
  end
@@ -91,11 +91,21 @@ module Searchlogic
91
91
  end
92
92
  end
93
93
 
94
- def create_condition(column_name, condition, args)
95
- if PRIMARY_CONDITIONS.include?(condition.to_sym)
96
- create_primary_condition(column_name, condition)
97
- elsif ALIAS_CONDITIONS.include?(condition.to_sym)
98
- create_alias_condition(column_name, condition, args)
94
+ def create_condition(name)
95
+ @conditions_already_tried ||= []
96
+ return nil if @conditions_already_tried.include?(name.to_s)
97
+ @conditions_already_tried << name.to_s
98
+
99
+ if details = condition_details(name)
100
+ if PRIMARY_CONDITIONS.include?(details[:condition].to_sym)
101
+ create_primary_condition(details[:column], details[:condition])
102
+ elsif ALIAS_CONDITIONS.include?(details[:condition].to_sym)
103
+ create_alias_condition(details[:column], details[:condition])
104
+ end
105
+
106
+ elsif boolean_condition?(name)
107
+ column = name.to_s.gsub(/^not_/, "")
108
+ named_scope name, :conditions => {column => (name.to_s =~ /^not_/).nil?}
99
109
  end
100
110
  end
101
111
 
@@ -107,7 +117,7 @@ module Searchlogic
107
117
 
108
118
  scope_options = case condition.to_s
109
119
  when /^equals/
110
- scope_options(condition, column, lambda { |a| attribute_condition("#{table_name}.#{column.name}", a) }, :skip_conversion => skip_conversion)
120
+ scope_options(condition, column, "#{table_name}.#{column.name} = ?", :skip_conversion => skip_conversion)
111
121
  when /^does_not_equal/
112
122
  scope_options(condition, column, "#{table_name}.#{column.name} != ?", :skip_conversion => skip_conversion)
113
123
  when /^less_than_or_equal_to/
@@ -172,9 +182,9 @@ module Searchlogic
172
182
  values.flatten!
173
183
  values.collect! { |value| value_with_modifier(value, options[:value_modifier]) }
174
184
 
175
- scope_sql = values.collect { |value| sql.is_a?(Proc) ? sql.call(value) : sql }.join(join_word)
185
+ scope_sql = values.collect { |value| sql }.join(join_word)
176
186
 
177
- {:conditions => [scope_sql, *expand_range_bind_variables(values)]}
187
+ {:conditions => [scope_sql, *values]}
178
188
  end
179
189
  else
180
190
  {}
@@ -184,9 +194,7 @@ module Searchlogic
184
194
  searchlogic_lambda(column.type, :skip_conversion => options[:skip_conversion]) { |*values|
185
195
  values.collect! { |value| value_with_modifier(value, options[:value_modifier]) }
186
196
 
187
- scope_sql = sql.is_a?(Proc) ? sql.call(*values) : sql
188
-
189
- {:conditions => [scope_sql, *expand_range_bind_variables(values)]}
197
+ {:conditions => [sql, *values]}
190
198
  }
191
199
  end
192
200
  end
@@ -204,12 +212,13 @@ module Searchlogic
204
212
  end
205
213
  end
206
214
 
207
- def create_alias_condition(column_name, condition, args)
215
+ def create_alias_condition(column_name, condition)
208
216
  primary_condition = primary_condition(condition)
209
217
  alias_name = "#{column_name}_#{condition}"
210
218
  primary_name = "#{column_name}_#{primary_condition}"
211
- send(primary_name, *args) # go back to method_missing and make sure we create the method
212
- (class << self; self; end).class_eval { alias_method alias_name, primary_name }
219
+ if respond_to?(primary_name)
220
+ (class << self; self; end).class_eval { alias_method alias_name, primary_name }
221
+ end
213
222
  end
214
223
 
215
224
  # Returns the primary condition for the given alias. Ex:
@@ -5,30 +5,30 @@ module Searchlogic
5
5
  module OrConditions
6
6
  class NoConditionSpecifiedError < StandardError; end
7
7
  class UnknownConditionError < StandardError; end
8
-
8
+
9
9
  def condition?(name) # :nodoc:
10
10
  super || or_condition?(name)
11
11
  end
12
-
12
+
13
13
  def named_scope_options(name) # :nodoc:
14
14
  super || super(or_conditions(name).try(:join, "_or_"))
15
15
  end
16
-
16
+
17
17
  private
18
18
  def or_condition?(name)
19
19
  !or_conditions(name).nil?
20
20
  end
21
-
22
- def method_missing(name, *args, &block)
21
+
22
+ def create_condition(name)
23
23
  if conditions = or_conditions(name)
24
- create_or_condition(conditions, args)
25
- (class << self; self; end).class_eval { alias_method name, conditions.join("_or_") } if !respond_to?(name)
26
- send(name, *args)
24
+ create_or_condition(conditions)
25
+ alias_name = conditions.join("_or_")
26
+ (class << self; self; end).class_eval { alias_method name, conditions.join("_or_") } if name != alias_name
27
27
  else
28
28
  super
29
29
  end
30
30
  end
31
-
31
+
32
32
  def or_conditions(name)
33
33
  # First determine if we should even work on the name, we want to be as quick as possible
34
34
  # with this.
@@ -41,7 +41,7 @@ module Searchlogic
41
41
  end
42
42
  end
43
43
  end
44
-
44
+
45
45
  def split_or_condition(name)
46
46
  parts = name.to_s.split("_or_")
47
47
  new_parts = []
@@ -54,7 +54,7 @@ module Searchlogic
54
54
  end
55
55
  new_parts
56
56
  end
57
-
57
+
58
58
  # The purpose of this method is to convert the method name parts into actual condition names.
59
59
  #
60
60
  # Example:
@@ -81,7 +81,7 @@ module Searchlogic
81
81
  path = full_association_path(part, last_condition, association_details[:association])
82
82
  conditions << "#{path[:path].join("_").to_sym}_#{path[:column]}_#{path[:condition]}"
83
83
  last_condition = path[:condition] || nil
84
- elsif local_condition?(part)
84
+ elsif column_condition?(part)
85
85
  # We are a custom scope
86
86
  conditions << part
87
87
  elsif column_names.include?(part)
@@ -90,13 +90,13 @@ module Searchlogic
90
90
  raise NoConditionSpecifiedError.new("The '#{part}' column doesn't know which condition to use, if you use an exact column " +
91
91
  "name you need to specify a condition sometime after (ex: id_or_created_at_lt), where id would use the 'lt' condition.")
92
92
  end
93
-
93
+
94
94
  conditions << "#{part}_#{last_condition}"
95
95
  else
96
96
  raise UnknownConditionError.new("The condition '#{part}' is not a valid condition, we could not find any scopes that match this.")
97
97
  end
98
98
  end
99
-
99
+
100
100
  conditions.reverse
101
101
  end
102
102
 
@@ -116,8 +116,8 @@ module Searchlogic
116
116
  end
117
117
  { :path => path, :column => part, :condition => last_condition }
118
118
  end
119
-
120
- def create_or_condition(scopes, args)
119
+
120
+ def create_or_condition(scopes)
121
121
  scopes_options = scopes.collect { |scope, *args| send(scope, *args).proxy_options }
122
122
  # We're using first scope to determine column's type
123
123
  scope = named_scope_options(scopes.first)
@@ -126,7 +126,7 @@ module Searchlogic
126
126
  merge_scopes_with_or(scopes.collect { |scope| clone.send(scope, *args) })
127
127
  }
128
128
  end
129
-
129
+
130
130
  def merge_scopes_with_or(scopes)
131
131
  scopes_options = scopes.collect { |scope| scope.scope(:find) }
132
132
  conditions = scopes_options.reject { |o| o[:conditions].nil? }.collect { |o| sanitize_sql(o[:conditions]) }
@@ -10,27 +10,25 @@ module Searchlogic
10
10
  def condition?(name) # :nodoc:
11
11
  super || ordering_condition?(name)
12
12
  end
13
-
13
+
14
14
  private
15
15
  def ordering_condition?(name) # :nodoc:
16
16
  !ordering_condition_details(name).nil?
17
17
  end
18
-
19
- def method_missing(name, *args, &block)
18
+
19
+ def create_condition(name)
20
20
  if name == :order
21
21
  named_scope name, lambda { |scope_name|
22
22
  return {} if !condition?(scope_name)
23
23
  send(scope_name).proxy_options
24
24
  }
25
- send(name, *args)
26
25
  elsif details = ordering_condition_details(name)
27
26
  create_ordering_conditions(details[:column])
28
- send(name, *args)
29
27
  else
30
28
  super
31
29
  end
32
30
  end
33
-
31
+
34
32
  def ordering_condition_details(name)
35
33
  if name.to_s =~ /^(ascend|descend)_by_(#{column_names.join("|")})$/
36
34
  {:order_as => $1, :column => $2}
@@ -38,7 +36,7 @@ module Searchlogic
38
36
  {}
39
37
  end
40
38
  end
41
-
39
+
42
40
  def create_ordering_conditions(column)
43
41
  named_scope("ascend_by_#{column}".to_sym, {:order => "#{table_name}.#{column} ASC"})
44
42
  named_scope("descend_by_#{column}".to_sym, {:order => "#{table_name}.#{column} DESC"})
@@ -31,13 +31,13 @@ module Searchlogic
31
31
  end
32
32
  self
33
33
  end
34
-
34
+
35
35
  private
36
36
  # This is here as a hook to allow people to modify the order in which the conditions are called, for whatever reason.
37
37
  def conditions_array
38
38
  @conditions.to_a
39
39
  end
40
-
40
+
41
41
  def write_condition(name, value)
42
42
  @conditions[name] = value
43
43
  end
@@ -49,7 +49,7 @@ module Searchlogic
49
49
  def mass_conditions
50
50
  @mass_conditions ||= {}
51
51
  end
52
-
52
+
53
53
  def ignore_value?(value)
54
54
  (value.is_a?(String) && value.blank?) || (value.is_a?(Array) && value.empty?)
55
55
  end
@@ -7,7 +7,7 @@ module Searchlogic
7
7
  include InstanceMethods
8
8
  end
9
9
  end
10
-
10
+
11
11
  module InstanceMethods
12
12
  def to_yaml( opts = {} )
13
13
  YAML::quick_emit( self, opts ) do |out|
@@ -18,7 +18,7 @@ module Searchlogic
18
18
  end
19
19
  end
20
20
  end
21
-
21
+
22
22
  def yaml_initialize(taguri, attributes = {})
23
23
  self.klass = attributes["class_name"].constantize
24
24
  self.current_scope = attributes["current_scope"]
data/lib/searchlogic.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  require "searchlogic/core_ext/proc"
2
2
  require "searchlogic/core_ext/object"
3
- require "searchlogic/active_record/association_proxy"
4
3
  require "searchlogic/active_record/consistency"
5
4
  require "searchlogic/active_record/named_scope_tools"
6
- require "searchlogic/named_scopes/conditions"
5
+ require "searchlogic/active_record/scope"
6
+ require "searchlogic/named_scopes/base"
7
+ require "searchlogic/named_scopes/column_conditions"
7
8
  require "searchlogic/named_scopes/ordering"
8
9
  require "searchlogic/named_scopes/association_conditions"
9
10
  require "searchlogic/named_scopes/association_ordering"
@@ -24,19 +25,15 @@ Proc.send(:include, Searchlogic::CoreExt::Proc)
24
25
  Object.send(:include, Searchlogic::CoreExt::Object)
25
26
 
26
27
  module ActiveRecord # :nodoc: all
27
- module Associations
28
- class AssociationProxy
29
- include Searchlogic::ActiveRecord::AssociationProxy
30
- end
31
- end
32
-
33
28
  class Base
34
29
  class << self; include Searchlogic::ActiveRecord::Consistency; end
35
30
  end
36
31
  end
37
32
 
33
+ ActiveRecord::Base.extend(Searchlogic::ActiveRecord::Scope)
38
34
  ActiveRecord::Base.extend(Searchlogic::ActiveRecord::NamedScopeTools)
39
- ActiveRecord::Base.extend(Searchlogic::NamedScopes::Conditions)
35
+ ActiveRecord::Base.extend(Searchlogic::NamedScopes::Base)
36
+ ActiveRecord::Base.extend(Searchlogic::NamedScopes::ColumnConditions)
40
37
  ActiveRecord::Base.extend(Searchlogic::NamedScopes::AssociationConditions)
41
38
  ActiveRecord::Base.extend(Searchlogic::NamedScopes::AssociationOrdering)
42
39
  ActiveRecord::Base.extend(Searchlogic::NamedScopes::Ordering)
data/searchlogic.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{searchlogic}
8
- s.version = "2.4.32"
8
+ s.version = "2.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ben Johnson of Binary Logic"]
@@ -25,15 +25,16 @@ Gem::Specification.new do |s|
25
25
  "VERSION.yml",
26
26
  "init.rb",
27
27
  "lib/searchlogic.rb",
28
- "lib/searchlogic/active_record/association_proxy.rb",
29
28
  "lib/searchlogic/active_record/consistency.rb",
30
29
  "lib/searchlogic/active_record/named_scope_tools.rb",
30
+ "lib/searchlogic/active_record/scope.rb",
31
31
  "lib/searchlogic/core_ext/object.rb",
32
32
  "lib/searchlogic/core_ext/proc.rb",
33
33
  "lib/searchlogic/named_scopes/alias_scope.rb",
34
34
  "lib/searchlogic/named_scopes/association_conditions.rb",
35
35
  "lib/searchlogic/named_scopes/association_ordering.rb",
36
- "lib/searchlogic/named_scopes/conditions.rb",
36
+ "lib/searchlogic/named_scopes/base.rb",
37
+ "lib/searchlogic/named_scopes/column_conditions.rb",
37
38
  "lib/searchlogic/named_scopes/or_conditions.rb",
38
39
  "lib/searchlogic/named_scopes/ordering.rb",
39
40
  "lib/searchlogic/rails_helpers.rb",
@@ -56,7 +57,7 @@ Gem::Specification.new do |s|
56
57
  "spec/searchlogic/named_scopes/alias_scope_spec.rb",
57
58
  "spec/searchlogic/named_scopes/association_conditions_spec.rb",
58
59
  "spec/searchlogic/named_scopes/association_ordering_spec.rb",
59
- "spec/searchlogic/named_scopes/conditions_spec.rb",
60
+ "spec/searchlogic/named_scopes/column_conditions_spec.rb",
60
61
  "spec/searchlogic/named_scopes/or_conditions_spec.rb",
61
62
  "spec/searchlogic/named_scopes/ordering_spec.rb",
62
63
  "spec/searchlogic/search_spec.rb",
@@ -74,7 +75,7 @@ Gem::Specification.new do |s|
74
75
  "spec/searchlogic/named_scopes/alias_scope_spec.rb",
75
76
  "spec/searchlogic/named_scopes/association_conditions_spec.rb",
76
77
  "spec/searchlogic/named_scopes/association_ordering_spec.rb",
77
- "spec/searchlogic/named_scopes/conditions_spec.rb",
78
+ "spec/searchlogic/named_scopes/column_conditions_spec.rb",
78
79
  "spec/searchlogic/named_scopes/or_conditions_spec.rb",
79
80
  "spec/searchlogic/named_scopes/ordering_spec.rb",
80
81
  "spec/searchlogic/search_spec.rb",
@@ -18,6 +18,6 @@ describe Searchlogic::NamedScopes::AliasScope do
18
18
  end
19
19
 
20
20
  it "should inherit alias scopes from superclasses" do
21
- Class.new(User).alias_scope?("username_has").should be_true
21
+ Class.new(User).condition?("username_has").should be_true
22
22
  end
23
23
  end
@@ -209,5 +209,12 @@ describe Searchlogic::NamedScopes::AssociationConditions do
209
209
  user.orders.count.should == 1
210
210
  user.orders.shipped_on_not_null.shipped_on_greater_than(2.days.ago).count.should == 1
211
211
  end
212
-
212
+
213
+ it "should allow chained dynamic scopes without losing association scope conditions" do
214
+ user = User.create
215
+ order1 = Order.create :user => user, :shipped_on => Time.now, :total => 2
216
+ order2 = Order.create :shipped_on => Time.now, :total => 2
217
+ user.orders.id_equals(order1.id).count.should == 1
218
+ user.orders.id_equals(order1.id).total_equals(2).count.should == 1
219
+ end
213
220
  end
@@ -1,9 +1,13 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
2
 
3
- describe Searchlogic::NamedScopes::Conditions do
3
+ describe Searchlogic::NamedScopes::ColumnConditions do
4
4
  it "should be dynamically created and then cached" do
5
- User.should_not respond_to(:age_less_than)
5
+ User.scopes.key?(:age_less_than).should == false
6
6
  User.age_less_than(5)
7
+ User.scopes.key?(:age_less_than).should == true
8
+ end
9
+
10
+ it "should respond to the scope" do
7
11
  User.should respond_to(:age_less_than)
8
12
  end
9
13
 
@@ -15,8 +19,6 @@ describe Searchlogic::NamedScopes::Conditions do
15
19
  it "should have equals" do
16
20
  (5..7).each { |age| User.create(:age => age) }
17
21
  User.age_equals(6).all.should == User.find_all_by_age(6)
18
- User.age_equals(5..6).all.should == User.find_all_by_age(5..6)
19
- User.age_equals([5, 7]).all.should == User.find_all_by_age([5, 7])
20
22
  end
21
23
 
22
24
  it "should have does not equal" do
@@ -1,12 +1,6 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
2
 
3
3
  describe Searchlogic::NamedScopes::Ordering do
4
- it "should be dynamically created and then cached" do
5
- User.should_not respond_to(:ascend_by_username)
6
- User.ascend_by_username
7
- User.should respond_to(:ascend_by_username)
8
- end
9
-
10
4
  it "should have ascending" do
11
5
  %w(bjohnson thunt).each { |username| User.create(:username => username) }
12
6
  User.ascend_by_username.all.should == User.all(:order => "username ASC")
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: searchlogic
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 2.4.32
5
+ version: 2.5.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Ben Johnson of Binary Logic
@@ -53,15 +53,16 @@ files:
53
53
  - VERSION.yml
54
54
  - init.rb
55
55
  - lib/searchlogic.rb
56
- - lib/searchlogic/active_record/association_proxy.rb
57
56
  - lib/searchlogic/active_record/consistency.rb
58
57
  - lib/searchlogic/active_record/named_scope_tools.rb
58
+ - lib/searchlogic/active_record/scope.rb
59
59
  - lib/searchlogic/core_ext/object.rb
60
60
  - lib/searchlogic/core_ext/proc.rb
61
61
  - lib/searchlogic/named_scopes/alias_scope.rb
62
62
  - lib/searchlogic/named_scopes/association_conditions.rb
63
63
  - lib/searchlogic/named_scopes/association_ordering.rb
64
- - lib/searchlogic/named_scopes/conditions.rb
64
+ - lib/searchlogic/named_scopes/base.rb
65
+ - lib/searchlogic/named_scopes/column_conditions.rb
65
66
  - lib/searchlogic/named_scopes/or_conditions.rb
66
67
  - lib/searchlogic/named_scopes/ordering.rb
67
68
  - lib/searchlogic/rails_helpers.rb
@@ -84,7 +85,7 @@ files:
84
85
  - spec/searchlogic/named_scopes/alias_scope_spec.rb
85
86
  - spec/searchlogic/named_scopes/association_conditions_spec.rb
86
87
  - spec/searchlogic/named_scopes/association_ordering_spec.rb
87
- - spec/searchlogic/named_scopes/conditions_spec.rb
88
+ - spec/searchlogic/named_scopes/column_conditions_spec.rb
88
89
  - spec/searchlogic/named_scopes/or_conditions_spec.rb
89
90
  - spec/searchlogic/named_scopes/ordering_spec.rb
90
91
  - spec/searchlogic/search_spec.rb
@@ -103,7 +104,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
104
  requirements:
104
105
  - - ">="
105
106
  - !ruby/object:Gem::Version
106
- hash: -3829860769572842136
107
+ hash: -2184682576118207105
107
108
  segments:
108
109
  - 0
109
110
  version: "0"
@@ -128,7 +129,7 @@ test_files:
128
129
  - spec/searchlogic/named_scopes/alias_scope_spec.rb
129
130
  - spec/searchlogic/named_scopes/association_conditions_spec.rb
130
131
  - spec/searchlogic/named_scopes/association_ordering_spec.rb
131
- - spec/searchlogic/named_scopes/conditions_spec.rb
132
+ - spec/searchlogic/named_scopes/column_conditions_spec.rb
132
133
  - spec/searchlogic/named_scopes/or_conditions_spec.rb
133
134
  - spec/searchlogic/named_scopes/ordering_spec.rb
134
135
  - spec/searchlogic/search_spec.rb
@@ -1,20 +0,0 @@
1
- module Searchlogic
2
- module ActiveRecord
3
- module AssociationProxy
4
- def self.included(klass)
5
- klass.class_eval do
6
- alias_method_chain :send, :searchlogic
7
- end
8
- end
9
-
10
- def send_with_searchlogic(method, *args, &block)
11
- # create the scope if it doesn't exist yet, then delegate back to the original method
12
- if !proxy_respond_to?(method) && proxy_reflection.macro != :belongs_to && !proxy_reflection.options[:polymorphic] && proxy_reflection.klass.condition?(method)
13
- proxy_reflection.klass.send(method, *args, &block)
14
- end
15
-
16
- send_without_searchlogic(method, *args, &block)
17
- end
18
- end
19
- end
20
- end