searchlogic 1.5.3
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 +228 -0
- data/MIT-LICENSE +20 -0
- data/Manifest +123 -0
- data/README.rdoc +383 -0
- data/Rakefile +15 -0
- data/TODO.rdoc +6 -0
- data/examples/README.rdoc +4 -0
- data/init.rb +1 -0
- data/lib/searchlogic.rb +89 -0
- data/lib/searchlogic/active_record/associations.rb +52 -0
- data/lib/searchlogic/active_record/base.rb +218 -0
- data/lib/searchlogic/active_record/connection_adapters/mysql_adapter.rb +172 -0
- data/lib/searchlogic/active_record/connection_adapters/postgresql_adapter.rb +168 -0
- data/lib/searchlogic/active_record/connection_adapters/sqlite_adapter.rb +75 -0
- data/lib/searchlogic/condition/base.rb +159 -0
- data/lib/searchlogic/condition/begins_with.rb +17 -0
- data/lib/searchlogic/condition/blank.rb +21 -0
- data/lib/searchlogic/condition/child_of.rb +11 -0
- data/lib/searchlogic/condition/descendant_of.rb +24 -0
- data/lib/searchlogic/condition/ends_with.rb +17 -0
- data/lib/searchlogic/condition/equals.rb +27 -0
- data/lib/searchlogic/condition/greater_than.rb +15 -0
- data/lib/searchlogic/condition/greater_than_or_equal_to.rb +15 -0
- data/lib/searchlogic/condition/inclusive_descendant_of.rb +11 -0
- data/lib/searchlogic/condition/keywords.rb +47 -0
- data/lib/searchlogic/condition/less_than.rb +15 -0
- data/lib/searchlogic/condition/less_than_or_equal_to.rb +15 -0
- data/lib/searchlogic/condition/like.rb +15 -0
- data/lib/searchlogic/condition/nil.rb +21 -0
- data/lib/searchlogic/condition/not_begin_with.rb +20 -0
- data/lib/searchlogic/condition/not_blank.rb +19 -0
- data/lib/searchlogic/condition/not_end_with.rb +20 -0
- data/lib/searchlogic/condition/not_equal.rb +26 -0
- data/lib/searchlogic/condition/not_have_keywords.rb +20 -0
- data/lib/searchlogic/condition/not_like.rb +20 -0
- data/lib/searchlogic/condition/not_nil.rb +19 -0
- data/lib/searchlogic/condition/sibling_of.rb +14 -0
- data/lib/searchlogic/condition/tree.rb +17 -0
- data/lib/searchlogic/conditions/base.rb +484 -0
- data/lib/searchlogic/conditions/protection.rb +36 -0
- data/lib/searchlogic/config.rb +31 -0
- data/lib/searchlogic/config/helpers.rb +289 -0
- data/lib/searchlogic/config/search.rb +53 -0
- data/lib/searchlogic/core_ext/hash.rb +75 -0
- data/lib/searchlogic/helpers/control_types/link.rb +310 -0
- data/lib/searchlogic/helpers/control_types/links.rb +241 -0
- data/lib/searchlogic/helpers/control_types/remote_link.rb +87 -0
- data/lib/searchlogic/helpers/control_types/remote_links.rb +72 -0
- data/lib/searchlogic/helpers/control_types/remote_select.rb +36 -0
- data/lib/searchlogic/helpers/control_types/select.rb +82 -0
- data/lib/searchlogic/helpers/form.rb +208 -0
- data/lib/searchlogic/helpers/utilities.rb +197 -0
- data/lib/searchlogic/modifiers/absolute.rb +15 -0
- data/lib/searchlogic/modifiers/acos.rb +11 -0
- data/lib/searchlogic/modifiers/asin.rb +11 -0
- data/lib/searchlogic/modifiers/atan.rb +11 -0
- data/lib/searchlogic/modifiers/base.rb +27 -0
- data/lib/searchlogic/modifiers/ceil.rb +15 -0
- data/lib/searchlogic/modifiers/char_length.rb +15 -0
- data/lib/searchlogic/modifiers/cos.rb +15 -0
- data/lib/searchlogic/modifiers/cot.rb +15 -0
- data/lib/searchlogic/modifiers/day_of_month.rb +15 -0
- data/lib/searchlogic/modifiers/day_of_week.rb +15 -0
- data/lib/searchlogic/modifiers/day_of_year.rb +15 -0
- data/lib/searchlogic/modifiers/degrees.rb +11 -0
- data/lib/searchlogic/modifiers/exp.rb +15 -0
- data/lib/searchlogic/modifiers/floor.rb +15 -0
- data/lib/searchlogic/modifiers/hex.rb +11 -0
- data/lib/searchlogic/modifiers/hour.rb +11 -0
- data/lib/searchlogic/modifiers/log.rb +15 -0
- data/lib/searchlogic/modifiers/log10.rb +11 -0
- data/lib/searchlogic/modifiers/log2.rb +11 -0
- data/lib/searchlogic/modifiers/lower.rb +15 -0
- data/lib/searchlogic/modifiers/ltrim.rb +15 -0
- data/lib/searchlogic/modifiers/md5.rb +11 -0
- data/lib/searchlogic/modifiers/microseconds.rb +11 -0
- data/lib/searchlogic/modifiers/milliseconds.rb +11 -0
- data/lib/searchlogic/modifiers/minute.rb +15 -0
- data/lib/searchlogic/modifiers/month.rb +15 -0
- data/lib/searchlogic/modifiers/octal.rb +15 -0
- data/lib/searchlogic/modifiers/radians.rb +11 -0
- data/lib/searchlogic/modifiers/round.rb +11 -0
- data/lib/searchlogic/modifiers/rtrim.rb +15 -0
- data/lib/searchlogic/modifiers/second.rb +15 -0
- data/lib/searchlogic/modifiers/sign.rb +11 -0
- data/lib/searchlogic/modifiers/sin.rb +11 -0
- data/lib/searchlogic/modifiers/square_root.rb +15 -0
- data/lib/searchlogic/modifiers/tan.rb +15 -0
- data/lib/searchlogic/modifiers/trim.rb +15 -0
- data/lib/searchlogic/modifiers/upper.rb +15 -0
- data/lib/searchlogic/modifiers/week.rb +11 -0
- data/lib/searchlogic/modifiers/year.rb +11 -0
- data/lib/searchlogic/search/base.rb +148 -0
- data/lib/searchlogic/search/conditions.rb +53 -0
- data/lib/searchlogic/search/ordering.rb +244 -0
- data/lib/searchlogic/search/pagination.rb +121 -0
- data/lib/searchlogic/search/protection.rb +89 -0
- data/lib/searchlogic/search/searching.rb +31 -0
- data/lib/searchlogic/shared/utilities.rb +50 -0
- data/lib/searchlogic/shared/virtual_classes.rb +39 -0
- data/lib/searchlogic/version.rb +79 -0
- data/searchlogic.gemspec +39 -0
- data/test/fixtures/accounts.yml +15 -0
- data/test/fixtures/cats.yml +3 -0
- data/test/fixtures/dogs.yml +3 -0
- data/test/fixtures/orders.yml +14 -0
- data/test/fixtures/user_groups.yml +13 -0
- data/test/fixtures/users.yml +36 -0
- data/test/test_active_record_associations.rb +81 -0
- data/test/test_active_record_base.rb +93 -0
- data/test/test_condition_base.rb +52 -0
- data/test/test_condition_types.rb +143 -0
- data/test/test_conditions_base.rb +242 -0
- data/test/test_conditions_protection.rb +16 -0
- data/test/test_config.rb +23 -0
- data/test/test_helper.rb +134 -0
- data/test/test_search_base.rb +227 -0
- data/test/test_search_conditions.rb +19 -0
- data/test/test_search_ordering.rb +165 -0
- data/test/test_search_pagination.rb +72 -0
- data/test/test_search_protection.rb +24 -0
- data/test_libs/acts_as_tree.rb +98 -0
- data/test_libs/ordered_hash.rb +9 -0
- data/test_libs/rexml_fix.rb +14 -0
- metadata +317 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class DescendantOf < Tree
|
|
4
|
+
def to_conditions(value)
|
|
5
|
+
# Wish I knew how to do this in SQL
|
|
6
|
+
root = (value.is_a?(klass) ? value : klass.find(value)) rescue return
|
|
7
|
+
strs = []
|
|
8
|
+
subs = []
|
|
9
|
+
all_children_ids(root).each do |child_id|
|
|
10
|
+
strs << "#{quoted_table_name}.#{quote_column_name(klass.primary_key)} = ?"
|
|
11
|
+
subs << child_id
|
|
12
|
+
end
|
|
13
|
+
[strs.join(" OR "), *subs]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
def all_children_ids(record)
|
|
18
|
+
ids = record.children.collect { |child| child.send(klass.primary_key) }
|
|
19
|
+
record.children.each { |child| ids += all_children_ids(child) }
|
|
20
|
+
ids
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class EndsWith < Base
|
|
4
|
+
self.join_arrays_with_or = true
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def condition_names_for_column
|
|
8
|
+
super + ["ew", "ends", "end"]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_conditions(value)
|
|
13
|
+
["#{column_sql} LIKE ?", "%#{value}"]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class Equals < Base
|
|
4
|
+
self.handle_array_value = true
|
|
5
|
+
self.ignore_meaningless_value = false
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def condition_names_for_column
|
|
9
|
+
super + ["", "is"]
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_conditions(value)
|
|
14
|
+
# Let ActiveRecord handle this
|
|
15
|
+
args = []
|
|
16
|
+
case value
|
|
17
|
+
when Range
|
|
18
|
+
args = [value.first, value.last]
|
|
19
|
+
else
|
|
20
|
+
args << value
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
["#{column_sql} #{klass.send(:attribute_condition, value)}", *args]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class GreaterThanOrEqualTo < Base
|
|
4
|
+
class << self
|
|
5
|
+
def condition_names_for_column
|
|
6
|
+
super + ["gte", "at_least", "least"]
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_conditions(value)
|
|
11
|
+
["#{column_sql} >= ?", value]
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class InclusiveDescendantOf < Tree
|
|
4
|
+
def to_conditions(value)
|
|
5
|
+
condition = DescendantOf.new(klass, options)
|
|
6
|
+
condition.value = value
|
|
7
|
+
merge_conditions(["#{quoted_table_name}.#{quote_column_name(klass.primary_key)} = ?", (value.is_a?(klass) ? value.send(klass.primary_key) : value)], condition.sanitize, :any => true)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class Keywords < Base
|
|
4
|
+
# Because be default it joins with AND, so padding an array just gives you more options. Joining with and is no different than combining all of the words.
|
|
5
|
+
self.join_arrays_with_or = true
|
|
6
|
+
|
|
7
|
+
BLACKLISTED_WORDS = ('a'..'z').to_a + ["about", "an", "are", "as", "at", "be", "by", "com", "de", "en", "for", "from", "how", "in", "is", "it", "la", "of", "on", "or", "that", "the", "the", "this", "to", "und", "was", "what", "when", "where", "who", "will", "with", "www"] # from ranks.nl
|
|
8
|
+
FOREIGN_CHARACTERS = 'àáâãäåßéèêëìíîïñòóôõöùúûüýÿ'
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
def condition_names_for_column
|
|
12
|
+
super + ["kwords", "kw"]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_conditions(value)
|
|
17
|
+
strs = []
|
|
18
|
+
subs = []
|
|
19
|
+
|
|
20
|
+
search_parts = value.gsub(/,/, " ").split(/ /)
|
|
21
|
+
replace_non_alnum_characters!(search_parts)
|
|
22
|
+
search_parts.uniq!
|
|
23
|
+
remove_blacklisted_words!(search_parts)
|
|
24
|
+
return if search_parts.blank?
|
|
25
|
+
|
|
26
|
+
search_parts.each do |search_part|
|
|
27
|
+
strs << "#{column_sql} #{like_condition_name} ?"
|
|
28
|
+
subs << "%#{search_part}%"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
[strs.join(" AND "), *subs]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
def replace_non_alnum_characters!(search_parts)
|
|
36
|
+
search_parts.each do |word|
|
|
37
|
+
word.downcase!
|
|
38
|
+
word.gsub!(/[^[:alnum:]#{FOREIGN_CHARACTERS}]/, '')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def remove_blacklisted_words!(search_parts)
|
|
43
|
+
search_parts.delete_if { |word| word.blank? || BLACKLISTED_WORDS.include?(word.downcase) }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class LessThanOrEqualTo < Base
|
|
4
|
+
class << self
|
|
5
|
+
def condition_names_for_column
|
|
6
|
+
super + ["lte", "at_most", "most"]
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_conditions(value)
|
|
11
|
+
["#{column_sql} <= ?", value]
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class Like < Base
|
|
4
|
+
class << self
|
|
5
|
+
def condition_names_for_column
|
|
6
|
+
super + ["contains", "has"]
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_conditions(value)
|
|
11
|
+
["#{column_sql} #{like_condition_name} ?", "%#{value}%"]
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class Nil < Base
|
|
4
|
+
self.value_type = :boolean
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def condition_names_for_column
|
|
8
|
+
super + ["is_nil", "is_null", "null"]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_conditions(value)
|
|
13
|
+
if value == true
|
|
14
|
+
"#{column_sql} IS NULL"
|
|
15
|
+
elsif value == false
|
|
16
|
+
"#{column_sql} IS NOT NULL"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class NotBeginWith < Base
|
|
4
|
+
class << self
|
|
5
|
+
def condition_names_for_column
|
|
6
|
+
super + ["not_bw", "not_sw", "not_start_with", "not_start", "beginning_is_not", "beginning_not"]
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_conditions(value)
|
|
11
|
+
begin_with = BeginWith.new(klass, options)
|
|
12
|
+
begin_with.value = value
|
|
13
|
+
conditions = being_with.sanitize
|
|
14
|
+
return conditions if conditions.blank?
|
|
15
|
+
conditions.first.gsub!(" LIKE ", " NOT LIKE ")
|
|
16
|
+
conditions
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class NotBlank < Base
|
|
4
|
+
self.value_type = :boolean
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def condition_names_for_column
|
|
8
|
+
super + ["is_not_blank"]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_conditions(value)
|
|
13
|
+
blank = Blank.new(klass, options)
|
|
14
|
+
blank.value = !value
|
|
15
|
+
blank.sanitize
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class NotEndWith < Base
|
|
4
|
+
class << self
|
|
5
|
+
def condition_names_for_column
|
|
6
|
+
super + ["not_ew", "not_end", "end_is_not", "end_not"]
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_conditions(value)
|
|
11
|
+
ends_with = EndsWith.new(klass, options)
|
|
12
|
+
ends_with.value = value
|
|
13
|
+
conditions = ends_with.sanitize
|
|
14
|
+
return conditions if conditions.blank?
|
|
15
|
+
conditions.first.gsub!(" LIKE ", " NOT LIKE ")
|
|
16
|
+
conditions
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class NotEqual < Base
|
|
4
|
+
self.handle_array_value = true
|
|
5
|
+
self.ignore_meaningless_value = false
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def condition_names_for_column
|
|
9
|
+
super + ["does_not_equal", "not_equal", "is_not", "not"]
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_conditions(value)
|
|
14
|
+
# Delegate to equals and then change
|
|
15
|
+
condition = Equals.new(klass, options)
|
|
16
|
+
condition.value = value
|
|
17
|
+
conditions_array = condition.sanitize
|
|
18
|
+
conditions_array.first.gsub!(/ IS /, " IS NOT ")
|
|
19
|
+
conditions_array.first.gsub!(/ BETWEEN /, " NOT BETWEEN ")
|
|
20
|
+
conditions_array.first.gsub!(/ IN /, " NOT IN ")
|
|
21
|
+
conditions_array.first.gsub!(/=/, "!=")
|
|
22
|
+
conditions_array
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class NotHaveKeywords < Base
|
|
4
|
+
class << self
|
|
5
|
+
def condition_names_for_column
|
|
6
|
+
super + ["not_have_keywords", "not_keywords", "not_have_kw", "not_kw", "not_have_kwwords", "not_kwwords"]
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_conditions(value)
|
|
11
|
+
keywords = Keywords.new(klass, options)
|
|
12
|
+
keywords.value = value
|
|
13
|
+
conditions = keywords.sanitize
|
|
14
|
+
return conditions if conditions.blank?
|
|
15
|
+
conditions.first.gsub!(" #{like_condition_name} ", " NOT #{like_condition_name} ")
|
|
16
|
+
conditions
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class NotLike < Base
|
|
4
|
+
class << self
|
|
5
|
+
def condition_names_for_column
|
|
6
|
+
super + ["not_contain", "not_have"]
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_conditions(value)
|
|
11
|
+
like = Like.new(klass, options)
|
|
12
|
+
like.value = value
|
|
13
|
+
conditions = like.sanitize
|
|
14
|
+
return conditions if conditions.blank?
|
|
15
|
+
conditions.first.gsub!(" #{like_condition_name} ", " NOT #{like_condition_name} ")
|
|
16
|
+
conditions
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class NotNil < Base
|
|
4
|
+
self.value_type = :boolean
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def condition_names_for_column
|
|
8
|
+
super + ["is_not_nil", "is_not_null", "not_null"]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_conditions(value)
|
|
13
|
+
is_nil = Nil.new(klass, options)
|
|
14
|
+
is_nil.value = !value
|
|
15
|
+
is_nil.sanitize
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class SiblingOf < Tree
|
|
4
|
+
def to_conditions(value)
|
|
5
|
+
parent_association = klass.reflect_on_association(:parent)
|
|
6
|
+
foreign_key_name = (parent_association && parent_association.options[:foreign_key]) || "parent_id"
|
|
7
|
+
parent_id = (value.is_a?(klass) ? value : klass.find(value)).send(foreign_key_name)
|
|
8
|
+
condition = ChildOf.new(klass, options)
|
|
9
|
+
condition.value = parent_id
|
|
10
|
+
merge_conditions(["#{quoted_table_name}.#{quote_column_name(klass.primary_key)} != ?", (value.is_a?(klass) ? value.send(klass.primary_key) : value)], condition.sanitize)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Condition
|
|
3
|
+
class Tree < Base # :nodoc:
|
|
4
|
+
self.join_arrays_with_or = true
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def condition_names_for_column
|
|
8
|
+
[]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def condition_names_for_model(model)
|
|
12
|
+
[condition_type_name]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
module Searchlogic
|
|
2
|
+
module Conditions # :nodoc:
|
|
3
|
+
# = Conditions
|
|
4
|
+
#
|
|
5
|
+
# Represents a collection of conditions and performs various tasks on that collection. For information on each condition see Searchlogic::Condition.
|
|
6
|
+
# Each condition has its own file and class and the source for each condition is pretty self explanatory.
|
|
7
|
+
class Base
|
|
8
|
+
include Shared::Utilities
|
|
9
|
+
include Shared::VirtualClasses
|
|
10
|
+
|
|
11
|
+
attr_accessor :any, :relationship_name
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
attr_accessor :added_klass_conditions, :added_column_equals_conditions, :added_associations
|
|
15
|
+
|
|
16
|
+
def column_details # :nodoc:
|
|
17
|
+
return @column_details if @column_details
|
|
18
|
+
|
|
19
|
+
@column_details = []
|
|
20
|
+
|
|
21
|
+
klass.columns.each do |column|
|
|
22
|
+
column_detail = {:column => column}
|
|
23
|
+
column_detail[:aliases] = case column.type
|
|
24
|
+
when :datetime, :time, :timestamp
|
|
25
|
+
[column.name.gsub(/_at$/, "")]
|
|
26
|
+
when :date
|
|
27
|
+
[column.name.gsub(/_at$/, "")]
|
|
28
|
+
else
|
|
29
|
+
[]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
@column_details << column_detail
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
@column_details
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Registers a condition as an available condition for a column or a class. MySQL supports a "sounds like" function. I want to use it, so let's add it.
|
|
39
|
+
#
|
|
40
|
+
# === Example
|
|
41
|
+
#
|
|
42
|
+
# # config/initializers/searchlogic.rb
|
|
43
|
+
# # Actual function for MySQL databases only
|
|
44
|
+
# class SoundsLike < Searchlogic::Condition::Base
|
|
45
|
+
# # The name of the conditions. By default its the name of the class, if you want alternate or alias conditions just add them on.
|
|
46
|
+
# # If you don't want to add aliases you don't even need to define this method
|
|
47
|
+
# def self.name_for_column(column)
|
|
48
|
+
# super
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# # You can return an array or a string. NOT a hash, because all of these conditions
|
|
52
|
+
# # need to eventually get merged together. The array or string can be anything you would put in
|
|
53
|
+
# # the :conditions option for ActiveRecord::Base.find(). Also notice the column_sql variable. This is essentail
|
|
54
|
+
# # for applying modifiers and should be used in your conditions wherever you want the column.
|
|
55
|
+
# def to_conditions(value)
|
|
56
|
+
# ["#{column_sql} SOUNDS LIKE ?", value]
|
|
57
|
+
# end
|
|
58
|
+
# end
|
|
59
|
+
#
|
|
60
|
+
# Searchlogic::Seearch::Conditions.register_condition(SoundsLike)
|
|
61
|
+
def register_condition(condition_class)
|
|
62
|
+
raise(ArgumentError, "You can only register conditions that extend Searchlogic::Condition::Base") unless condition_class.ancestors.include?(Searchlogic::Condition::Base)
|
|
63
|
+
conditions << condition_class unless conditions.include?(condition_class)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# A list of available condition type classes
|
|
67
|
+
def conditions
|
|
68
|
+
@@conditions ||= []
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Registers a modifier as an available modifier for each column.
|
|
72
|
+
#
|
|
73
|
+
# === Example
|
|
74
|
+
#
|
|
75
|
+
# # config/initializers/searchlogic.rb
|
|
76
|
+
# class Ceil < Searchlogic::Modifiers::Base
|
|
77
|
+
# # The name of the modifier. By default its the name of the class, if you want alternate or alias modifiers just add them on.
|
|
78
|
+
# # If you don't want to add aliases you don't even need to define this method
|
|
79
|
+
# def self.modifier_names
|
|
80
|
+
# super + ["round_up"]
|
|
81
|
+
# end
|
|
82
|
+
#
|
|
83
|
+
# # The name of the method in the connection adapters (see below). By default its the name of your class suffixed with "_sql".
|
|
84
|
+
# # So in this example it would be "ceil_sql". Unless you want to change that you don't need to define this method.
|
|
85
|
+
# def self.adapter_method_name
|
|
86
|
+
# super
|
|
87
|
+
# end
|
|
88
|
+
#
|
|
89
|
+
# # This is the type of value returned from the modifier. This is neccessary for typcasting values for the modifier when
|
|
90
|
+
# # applied to a column
|
|
91
|
+
# def self.return_type
|
|
92
|
+
# :integer
|
|
93
|
+
# end
|
|
94
|
+
# end
|
|
95
|
+
#
|
|
96
|
+
# Searchlogic::Seearch::Conditions.register_modifiers(Ceil)
|
|
97
|
+
#
|
|
98
|
+
# Now here's the fun part, applying this modifier to each connection adapter. Some databases call modifiers differently. If they all apply them the same you can
|
|
99
|
+
# add in the function to ActiveRecord::ConnectionAdapters::AbstractAdapter, otherwise you need to add them to each
|
|
100
|
+
# individually: ActiveRecord::ConnectionAdapters::MysqlAdapter, ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, ActiveRecord::ConnectionAdapters::SQLiteAdapter
|
|
101
|
+
#
|
|
102
|
+
# Do this by includine a model with your method. The name of your method, by default, is: #{modifier_name}_sql. So in the example above it would be "ceil_sql"
|
|
103
|
+
#
|
|
104
|
+
# module CeilAdapterMethod
|
|
105
|
+
# def ceil_sql(column_name)
|
|
106
|
+
# "CEIL(#{column_name})"
|
|
107
|
+
# end
|
|
108
|
+
# end
|
|
109
|
+
#
|
|
110
|
+
# ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:include, CeilAdapterMethod)
|
|
111
|
+
# # ... include for the rest of the adapters
|
|
112
|
+
def register_modifier(modifier_class)
|
|
113
|
+
raise(ArgumentError, "You can only register conditions that extend Searchlogic::Modifiers::Base") unless modifier_class.ancestors.include?(Searchlogic::Modifiers::Base)
|
|
114
|
+
modifiers << modifier_class unless modifiers.include?(modifier_class)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# A list of available modifier classes
|
|
118
|
+
def modifiers
|
|
119
|
+
@@modifiers ||= []
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# A list of all associations created, used for caching and performance
|
|
123
|
+
def association_names
|
|
124
|
+
@association_names ||= []
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# A list of all conditions available, users for caching and performance
|
|
128
|
+
def condition_names
|
|
129
|
+
@condition_names ||= []
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def needed?(model_class, conditions) # :nodoc:
|
|
133
|
+
return false if conditions.blank?
|
|
134
|
+
|
|
135
|
+
if conditions.is_a?(Hash)
|
|
136
|
+
return true if conditions[:any]
|
|
137
|
+
stringified_conditions = conditions.stringify_keys
|
|
138
|
+
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
|
|
139
|
+
|
|
140
|
+
column_names = model_class.column_names
|
|
141
|
+
stringified_conditions.keys.each do |condition|
|
|
142
|
+
return true unless column_names.include?(condition)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
false
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def initialize(init_conditions = {})
|
|
151
|
+
add_associations!
|
|
152
|
+
add_column_equals_conditions!
|
|
153
|
+
self.conditions = init_conditions
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Determines if we should join the conditions with "AND" or "OR".
|
|
157
|
+
#
|
|
158
|
+
# === Examples
|
|
159
|
+
#
|
|
160
|
+
# search.conditions.any = true # will join all conditions with "or", you can also set this to "true", "1", or "yes"
|
|
161
|
+
# search.conditions.any = false # will join all conditions with "and"
|
|
162
|
+
def any=(value)
|
|
163
|
+
associations.each { |name, association| association.any = value }
|
|
164
|
+
@any = value
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def any # :nodoc:
|
|
168
|
+
any?
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Convenience method for determining if we should join the conditions with "AND" or "OR".
|
|
172
|
+
def any?
|
|
173
|
+
@any == true || @any == "true" || @any == "1" || @any == "yes"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# A list of joins to use when searching, includes relationships
|
|
177
|
+
def auto_joins
|
|
178
|
+
j = []
|
|
179
|
+
associations.each do |name, association|
|
|
180
|
+
next if association.conditions.blank?
|
|
181
|
+
association_joins = association.auto_joins
|
|
182
|
+
j << (association_joins.blank? ? name : {name => association_joins})
|
|
183
|
+
end
|
|
184
|
+
j.blank? ? nil : (j.size == 1 ? j.first : j)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def inspect
|
|
188
|
+
"#<#{klass}Conditions#{conditions.blank? ? "" : " #{conditions.inspect}"}>"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Sanitizes the conditions down into conditions that ActiveRecord::Base.find can understand.
|
|
192
|
+
def sanitize
|
|
193
|
+
return @conditions if @conditions
|
|
194
|
+
merge_conditions(*(objects.collect { |name, object| object.sanitize } << {:any => any}))
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Allows you to set the conditions via a hash.
|
|
198
|
+
def conditions=(value)
|
|
199
|
+
case value
|
|
200
|
+
when Hash
|
|
201
|
+
assert_valid_conditions(value)
|
|
202
|
+
remove_conditions_from_protected_assignement(value).each do |condition, condition_value|
|
|
203
|
+
|
|
204
|
+
# delete all blanks from mass assignments, forms submit blanks, blanks are meaningless
|
|
205
|
+
# equals condition thinks everything is meaningful, and arrays can be pased
|
|
206
|
+
new_condition_value = nil
|
|
207
|
+
case condition_value
|
|
208
|
+
when Array
|
|
209
|
+
new_condition_value = []
|
|
210
|
+
condition_value.each { |v| new_condition_value << v unless v == "" }
|
|
211
|
+
next if new_condition_value.size == 0
|
|
212
|
+
new_condition_value = new_condition_value.first if new_condition_value.size == 1
|
|
213
|
+
else
|
|
214
|
+
next if condition_value == ""
|
|
215
|
+
new_condition_value = condition_value
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
send("#{condition}=", new_condition_value)
|
|
219
|
+
end
|
|
220
|
+
else
|
|
221
|
+
reset_objects!
|
|
222
|
+
@conditions = value
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# All of the active conditions (conditions that have been set)
|
|
227
|
+
def conditions
|
|
228
|
+
return @conditions if @conditions
|
|
229
|
+
return if objects.blank?
|
|
230
|
+
|
|
231
|
+
conditions_hash = {}
|
|
232
|
+
objects.each do |name, object|
|
|
233
|
+
if object.class < Searchlogic::Conditions::Base
|
|
234
|
+
relationship_conditions = object.conditions
|
|
235
|
+
next if relationship_conditions.blank?
|
|
236
|
+
conditions_hash[name] = relationship_conditions
|
|
237
|
+
else
|
|
238
|
+
next if object.value_is_meaningless?
|
|
239
|
+
conditions_hash[name] = object.value
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
conditions_hash
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
private
|
|
246
|
+
def add_associations!
|
|
247
|
+
return true if self.class.added_associations
|
|
248
|
+
|
|
249
|
+
klass.reflect_on_all_associations.each do |association|
|
|
250
|
+
self.class.association_names << association.name.to_s
|
|
251
|
+
|
|
252
|
+
self.class.class_eval <<-"end_eval", __FILE__, __LINE__
|
|
253
|
+
def #{association.name}
|
|
254
|
+
if objects[:#{association.name}].nil?
|
|
255
|
+
objects[:#{association.name}] = Searchlogic::Conditions::Base.create_virtual_class(#{association.class_name}).new
|
|
256
|
+
objects[:#{association.name}].relationship_name = "#{association.name}"
|
|
257
|
+
objects[:#{association.name}].protect = protect
|
|
258
|
+
end
|
|
259
|
+
objects[:#{association.name}]
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def #{association.name}=(conditions); @conditions = nil; #{association.name}.conditions = conditions; end
|
|
263
|
+
def reset_#{association.name}!; objects.delete(:#{association.name}); end
|
|
264
|
+
end_eval
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
self.class.added_associations = true
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def add_column_equals_conditions!
|
|
271
|
+
return true if self.class.added_column_equals_conditions
|
|
272
|
+
klass.column_names.each { |name| setup_condition(name) }
|
|
273
|
+
self.class.added_column_equals_conditions = true
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def extract_column_and_condition_from_method_name(name)
|
|
277
|
+
name_parts = name.gsub("=", "").split("_")
|
|
278
|
+
|
|
279
|
+
condition_parts = []
|
|
280
|
+
column = nil
|
|
281
|
+
while column.nil? && name_parts.size > 0
|
|
282
|
+
possible_column_name = name_parts.join("_")
|
|
283
|
+
|
|
284
|
+
self.class.column_details.each do |column_detail|
|
|
285
|
+
if column_detail[:column].name == possible_column_name || column_detail[:aliases].include?(possible_column_name)
|
|
286
|
+
column = column_detail
|
|
287
|
+
break
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
condition_parts << name_parts.pop if !column
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
return if column.nil?
|
|
295
|
+
|
|
296
|
+
condition_name = condition_parts.reverse.join("_")
|
|
297
|
+
condition = nil
|
|
298
|
+
|
|
299
|
+
# Find the real condition
|
|
300
|
+
self.class.conditions.each do |condition_klass|
|
|
301
|
+
if condition_klass.condition_names_for_column.include?(condition_name)
|
|
302
|
+
condition = condition_klass
|
|
303
|
+
break
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
[column, condition]
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def breakdown_method_name(name)
|
|
311
|
+
column_detail, condition_klass = extract_column_and_condition_from_method_name(name)
|
|
312
|
+
if !column_detail.nil? && !condition_klass.nil?
|
|
313
|
+
# There were no modifiers
|
|
314
|
+
return [[], column_detail, condition_klass]
|
|
315
|
+
else
|
|
316
|
+
# There might be modifiers
|
|
317
|
+
name_parts = name.split("_of_")
|
|
318
|
+
column_detail, condition_klass = extract_column_and_condition_from_method_name(name_parts.pop)
|
|
319
|
+
if !column_detail.nil? && !condition_klass.nil?
|
|
320
|
+
# There were modifiers, lets get their real names
|
|
321
|
+
modifier_klasses = []
|
|
322
|
+
name_parts.each do |modifier_name|
|
|
323
|
+
size_before = modifier_klasses.size
|
|
324
|
+
self.class.modifiers.each do |modifier_klass|
|
|
325
|
+
if modifier_klass.modifier_names.include?(modifier_name)
|
|
326
|
+
modifier_klasses << modifier_klass
|
|
327
|
+
break
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
return if modifier_klasses.size == size_before # there was an invalid modifer, return nil for everything and let it act as a nomethoderror
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
return [modifier_klasses, column_detail, condition_klass]
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
nil
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def build_method_name(modifier_klasses, column_name, condition_name)
|
|
341
|
+
modifier_name_parts = []
|
|
342
|
+
modifier_klasses.each { |modifier_klass| modifier_name_parts << modifier_klass.modifier_names.first }
|
|
343
|
+
method_name_parts = []
|
|
344
|
+
method_name_parts << modifier_name_parts.join("_of_") + "_of" unless modifier_name_parts.blank?
|
|
345
|
+
method_name_parts << column_name
|
|
346
|
+
method_name_parts << condition_name unless condition_name.blank?
|
|
347
|
+
method_name_parts.join("_")
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def method_missing(name, *args, &block)
|
|
351
|
+
if setup_condition(name)
|
|
352
|
+
send(name, *args, &block)
|
|
353
|
+
else
|
|
354
|
+
super
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def setup_condition(name)
|
|
359
|
+
modifier_klasses, column_detail, condition_klass = breakdown_method_name(name.to_s)
|
|
360
|
+
if !column_detail.nil? && !condition_klass.nil?
|
|
361
|
+
method_name = build_method_name(modifier_klasses, column_detail[:column].name, condition_klass.condition_names_for_column.first)
|
|
362
|
+
|
|
363
|
+
if !added_condition?(method_name)
|
|
364
|
+
column_type = column_sql = nil
|
|
365
|
+
if !modifier_klasses.blank?
|
|
366
|
+
# Find the column type
|
|
367
|
+
column_type = modifier_klasses.first.return_type
|
|
368
|
+
|
|
369
|
+
# Build the column sql
|
|
370
|
+
column_sql = "{table}.{column}"
|
|
371
|
+
modifier_klasses.each do |modifier_klass|
|
|
372
|
+
next unless klass.connection.respond_to?(modifier_klass.adapter_method_name)
|
|
373
|
+
column_sql = klass.connection.send(modifier_klass.adapter_method_name, column_sql)
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
add_condition!(condition_klass, method_name, :column => column_detail[:column], :column_type => column_type, :column_sql_format => column_sql)
|
|
378
|
+
|
|
379
|
+
([column_detail[:column].name] + column_detail[:aliases]).each do |column_name|
|
|
380
|
+
condition_klass.condition_names_for_column.each do |condition_name|
|
|
381
|
+
alias_method_name = build_method_name(modifier_klasses, column_name, condition_name)
|
|
382
|
+
add_condition_alias!(alias_method_name, method_name) unless added_condition?(alias_method_name)
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
alias_method_name = name.to_s.gsub("=", "")
|
|
388
|
+
add_condition_alias!(alias_method_name, method_name) unless added_condition?(alias_method_name)
|
|
389
|
+
|
|
390
|
+
return true
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
false
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def add_condition!(condition, name, options = {})
|
|
397
|
+
self.class.condition_names << name
|
|
398
|
+
options[:column] = options[:column].name if options[:column].class < ::ActiveRecord::ConnectionAdapters::Column
|
|
399
|
+
|
|
400
|
+
self.class.class_eval <<-"end_eval", __FILE__, __LINE__
|
|
401
|
+
def #{name}_object
|
|
402
|
+
if objects[:#{name}].nil?
|
|
403
|
+
options = {}
|
|
404
|
+
objects[:#{name}] = #{condition.name}.new(klass, #{options.inspect})
|
|
405
|
+
end
|
|
406
|
+
objects[:#{name}]
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def #{name}; #{name}_object.value; end
|
|
410
|
+
|
|
411
|
+
def #{name}=(value)
|
|
412
|
+
@conditions = nil
|
|
413
|
+
|
|
414
|
+
#{name}_object.value = value
|
|
415
|
+
reset_#{name}! if #{name}_object.value_is_meaningless?
|
|
416
|
+
value
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
def reset_#{name}!; objects.delete(:#{name}); end
|
|
420
|
+
end_eval
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def added_condition?(name)
|
|
424
|
+
respond_to?("#{name}_object") && respond_to?(name) && respond_to?("#{name}=") && respond_to?("reset_#{name}!")
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
def add_condition_alias!(alias_name, name)
|
|
428
|
+
self.class.condition_names << alias_name
|
|
429
|
+
|
|
430
|
+
self.class.class_eval do
|
|
431
|
+
alias_method "#{alias_name}_object", "#{name}_object"
|
|
432
|
+
alias_method alias_name, name
|
|
433
|
+
alias_method "#{alias_name}=", "#{name}="
|
|
434
|
+
alias_method "reset_#{alias_name}!", "reset_#{name}!"
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
def assert_valid_conditions(conditions)
|
|
439
|
+
conditions.each do |condition, value|
|
|
440
|
+
next if (self.class.condition_names + self.class.association_names + ["any"]).include?(condition.to_s)
|
|
441
|
+
|
|
442
|
+
go_to_next = false
|
|
443
|
+
self.class.column_details.each do |column_detail|
|
|
444
|
+
if column_detail[:column].name == condition.to_s || column_detail[:aliases].include?(condition.to_s)
|
|
445
|
+
go_to_next = true
|
|
446
|
+
break
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
next if go_to_next
|
|
450
|
+
|
|
451
|
+
next unless respond_to?(condition)
|
|
452
|
+
|
|
453
|
+
raise(ArgumentError, "The #{condition} condition is not a valid condition")
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
def associations
|
|
458
|
+
associations = {}
|
|
459
|
+
objects.each do |name, object|
|
|
460
|
+
associations[name] = object if object.class < ::Searchlogic::Conditions::Base
|
|
461
|
+
end
|
|
462
|
+
associations
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def objects
|
|
466
|
+
@objects ||= {}
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def reset_objects!
|
|
470
|
+
objects.each { |name, object| eval("@#{name} = nil") }
|
|
471
|
+
objects.clear
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
def remove_conditions_from_protected_assignement(conditions)
|
|
475
|
+
return conditions if klass.accessible_conditions.nil? && klass.protected_conditions.nil?
|
|
476
|
+
if klass.accessible_conditions
|
|
477
|
+
conditions.reject { |condition, value| !klass.accessible_conditions.include?(condition.to_s) }
|
|
478
|
+
elsif klass.protected_conditions
|
|
479
|
+
conditions.reject { |condition, value| klass.protected_conditions.include?(condition.to_s) }
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
end
|