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 +2 -2
- data/lib/searchlogic/active_record/consistency.rb +4 -4
- data/lib/searchlogic/active_record/named_scope_tools.rb +7 -7
- data/lib/searchlogic/active_record/scope.rb +22 -0
- data/lib/searchlogic/core_ext/proc.rb +1 -1
- data/lib/searchlogic/named_scopes/alias_scope.rb +12 -11
- data/lib/searchlogic/named_scopes/association_conditions.rb +14 -14
- data/lib/searchlogic/named_scopes/association_ordering.rb +8 -9
- data/lib/searchlogic/named_scopes/base.rb +16 -0
- data/lib/searchlogic/named_scopes/{conditions.rb → column_conditions.rb} +35 -26
- data/lib/searchlogic/named_scopes/or_conditions.rb +17 -17
- data/lib/searchlogic/named_scopes/ordering.rb +5 -7
- data/lib/searchlogic/search/conditions.rb +3 -3
- data/lib/searchlogic/search/to_yaml.rb +2 -2
- data/lib/searchlogic.rb +6 -9
- data/searchlogic.gemspec +6 -5
- data/spec/searchlogic/named_scopes/alias_scope_spec.rb +1 -1
- data/spec/searchlogic/named_scopes/association_conditions_spec.rb +8 -1
- data/spec/searchlogic/named_scopes/{conditions_spec.rb → column_conditions_spec.rb} +6 -4
- data/spec/searchlogic/named_scopes/ordering_spec.rb +0 -6
- metadata +7 -6
- data/lib/searchlogic/active_record/association_proxy.rb +0 -20
data/VERSION.yml
CHANGED
@@ -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
|
@@ -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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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,
|
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,
|
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,
|
60
|
+
def association_condition_options(association, association_condition, poly_class = nil)
|
60
61
|
klass = poly_class ? poly_class : association.klass
|
61
|
-
scope
|
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 =
|
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
|
-
|
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
|
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]
|
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
|
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}",
|
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
|
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
|
-
|
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
|
67
|
+
def column_condition?(name)
|
62
68
|
return false if name.blank?
|
63
|
-
|
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
|
74
|
-
|
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(
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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,
|
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
|
185
|
+
scope_sql = values.collect { |value| sql }.join(join_word)
|
176
186
|
|
177
|
-
{:conditions => [scope_sql, *
|
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
|
-
|
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
|
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
|
-
|
212
|
-
|
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
|
21
|
+
|
22
|
+
def create_condition(name)
|
23
23
|
if conditions = or_conditions(name)
|
24
|
-
create_or_condition(conditions
|
25
|
-
|
26
|
-
|
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
|
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
|
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
|
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/
|
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::
|
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.
|
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/
|
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/
|
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/
|
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",
|
@@ -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::
|
3
|
+
describe Searchlogic::NamedScopes::ColumnConditions do
|
4
4
|
it "should be dynamically created and then cached" do
|
5
|
-
User.
|
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.
|
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/
|
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/
|
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: -
|
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/
|
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
|