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.
Files changed (125) hide show
  1. data/CHANGELOG.rdoc +228 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Manifest +123 -0
  4. data/README.rdoc +383 -0
  5. data/Rakefile +15 -0
  6. data/TODO.rdoc +6 -0
  7. data/examples/README.rdoc +4 -0
  8. data/init.rb +1 -0
  9. data/lib/searchlogic.rb +89 -0
  10. data/lib/searchlogic/active_record/associations.rb +52 -0
  11. data/lib/searchlogic/active_record/base.rb +218 -0
  12. data/lib/searchlogic/active_record/connection_adapters/mysql_adapter.rb +172 -0
  13. data/lib/searchlogic/active_record/connection_adapters/postgresql_adapter.rb +168 -0
  14. data/lib/searchlogic/active_record/connection_adapters/sqlite_adapter.rb +75 -0
  15. data/lib/searchlogic/condition/base.rb +159 -0
  16. data/lib/searchlogic/condition/begins_with.rb +17 -0
  17. data/lib/searchlogic/condition/blank.rb +21 -0
  18. data/lib/searchlogic/condition/child_of.rb +11 -0
  19. data/lib/searchlogic/condition/descendant_of.rb +24 -0
  20. data/lib/searchlogic/condition/ends_with.rb +17 -0
  21. data/lib/searchlogic/condition/equals.rb +27 -0
  22. data/lib/searchlogic/condition/greater_than.rb +15 -0
  23. data/lib/searchlogic/condition/greater_than_or_equal_to.rb +15 -0
  24. data/lib/searchlogic/condition/inclusive_descendant_of.rb +11 -0
  25. data/lib/searchlogic/condition/keywords.rb +47 -0
  26. data/lib/searchlogic/condition/less_than.rb +15 -0
  27. data/lib/searchlogic/condition/less_than_or_equal_to.rb +15 -0
  28. data/lib/searchlogic/condition/like.rb +15 -0
  29. data/lib/searchlogic/condition/nil.rb +21 -0
  30. data/lib/searchlogic/condition/not_begin_with.rb +20 -0
  31. data/lib/searchlogic/condition/not_blank.rb +19 -0
  32. data/lib/searchlogic/condition/not_end_with.rb +20 -0
  33. data/lib/searchlogic/condition/not_equal.rb +26 -0
  34. data/lib/searchlogic/condition/not_have_keywords.rb +20 -0
  35. data/lib/searchlogic/condition/not_like.rb +20 -0
  36. data/lib/searchlogic/condition/not_nil.rb +19 -0
  37. data/lib/searchlogic/condition/sibling_of.rb +14 -0
  38. data/lib/searchlogic/condition/tree.rb +17 -0
  39. data/lib/searchlogic/conditions/base.rb +484 -0
  40. data/lib/searchlogic/conditions/protection.rb +36 -0
  41. data/lib/searchlogic/config.rb +31 -0
  42. data/lib/searchlogic/config/helpers.rb +289 -0
  43. data/lib/searchlogic/config/search.rb +53 -0
  44. data/lib/searchlogic/core_ext/hash.rb +75 -0
  45. data/lib/searchlogic/helpers/control_types/link.rb +310 -0
  46. data/lib/searchlogic/helpers/control_types/links.rb +241 -0
  47. data/lib/searchlogic/helpers/control_types/remote_link.rb +87 -0
  48. data/lib/searchlogic/helpers/control_types/remote_links.rb +72 -0
  49. data/lib/searchlogic/helpers/control_types/remote_select.rb +36 -0
  50. data/lib/searchlogic/helpers/control_types/select.rb +82 -0
  51. data/lib/searchlogic/helpers/form.rb +208 -0
  52. data/lib/searchlogic/helpers/utilities.rb +197 -0
  53. data/lib/searchlogic/modifiers/absolute.rb +15 -0
  54. data/lib/searchlogic/modifiers/acos.rb +11 -0
  55. data/lib/searchlogic/modifiers/asin.rb +11 -0
  56. data/lib/searchlogic/modifiers/atan.rb +11 -0
  57. data/lib/searchlogic/modifiers/base.rb +27 -0
  58. data/lib/searchlogic/modifiers/ceil.rb +15 -0
  59. data/lib/searchlogic/modifiers/char_length.rb +15 -0
  60. data/lib/searchlogic/modifiers/cos.rb +15 -0
  61. data/lib/searchlogic/modifiers/cot.rb +15 -0
  62. data/lib/searchlogic/modifiers/day_of_month.rb +15 -0
  63. data/lib/searchlogic/modifiers/day_of_week.rb +15 -0
  64. data/lib/searchlogic/modifiers/day_of_year.rb +15 -0
  65. data/lib/searchlogic/modifiers/degrees.rb +11 -0
  66. data/lib/searchlogic/modifiers/exp.rb +15 -0
  67. data/lib/searchlogic/modifiers/floor.rb +15 -0
  68. data/lib/searchlogic/modifiers/hex.rb +11 -0
  69. data/lib/searchlogic/modifiers/hour.rb +11 -0
  70. data/lib/searchlogic/modifiers/log.rb +15 -0
  71. data/lib/searchlogic/modifiers/log10.rb +11 -0
  72. data/lib/searchlogic/modifiers/log2.rb +11 -0
  73. data/lib/searchlogic/modifiers/lower.rb +15 -0
  74. data/lib/searchlogic/modifiers/ltrim.rb +15 -0
  75. data/lib/searchlogic/modifiers/md5.rb +11 -0
  76. data/lib/searchlogic/modifiers/microseconds.rb +11 -0
  77. data/lib/searchlogic/modifiers/milliseconds.rb +11 -0
  78. data/lib/searchlogic/modifiers/minute.rb +15 -0
  79. data/lib/searchlogic/modifiers/month.rb +15 -0
  80. data/lib/searchlogic/modifiers/octal.rb +15 -0
  81. data/lib/searchlogic/modifiers/radians.rb +11 -0
  82. data/lib/searchlogic/modifiers/round.rb +11 -0
  83. data/lib/searchlogic/modifiers/rtrim.rb +15 -0
  84. data/lib/searchlogic/modifiers/second.rb +15 -0
  85. data/lib/searchlogic/modifiers/sign.rb +11 -0
  86. data/lib/searchlogic/modifiers/sin.rb +11 -0
  87. data/lib/searchlogic/modifiers/square_root.rb +15 -0
  88. data/lib/searchlogic/modifiers/tan.rb +15 -0
  89. data/lib/searchlogic/modifiers/trim.rb +15 -0
  90. data/lib/searchlogic/modifiers/upper.rb +15 -0
  91. data/lib/searchlogic/modifiers/week.rb +11 -0
  92. data/lib/searchlogic/modifiers/year.rb +11 -0
  93. data/lib/searchlogic/search/base.rb +148 -0
  94. data/lib/searchlogic/search/conditions.rb +53 -0
  95. data/lib/searchlogic/search/ordering.rb +244 -0
  96. data/lib/searchlogic/search/pagination.rb +121 -0
  97. data/lib/searchlogic/search/protection.rb +89 -0
  98. data/lib/searchlogic/search/searching.rb +31 -0
  99. data/lib/searchlogic/shared/utilities.rb +50 -0
  100. data/lib/searchlogic/shared/virtual_classes.rb +39 -0
  101. data/lib/searchlogic/version.rb +79 -0
  102. data/searchlogic.gemspec +39 -0
  103. data/test/fixtures/accounts.yml +15 -0
  104. data/test/fixtures/cats.yml +3 -0
  105. data/test/fixtures/dogs.yml +3 -0
  106. data/test/fixtures/orders.yml +14 -0
  107. data/test/fixtures/user_groups.yml +13 -0
  108. data/test/fixtures/users.yml +36 -0
  109. data/test/test_active_record_associations.rb +81 -0
  110. data/test/test_active_record_base.rb +93 -0
  111. data/test/test_condition_base.rb +52 -0
  112. data/test/test_condition_types.rb +143 -0
  113. data/test/test_conditions_base.rb +242 -0
  114. data/test/test_conditions_protection.rb +16 -0
  115. data/test/test_config.rb +23 -0
  116. data/test/test_helper.rb +134 -0
  117. data/test/test_search_base.rb +227 -0
  118. data/test/test_search_conditions.rb +19 -0
  119. data/test/test_search_ordering.rb +165 -0
  120. data/test/test_search_pagination.rb +72 -0
  121. data/test/test_search_protection.rb +24 -0
  122. data/test_libs/acts_as_tree.rb +98 -0
  123. data/test_libs/ordered_hash.rb +9 -0
  124. data/test_libs/rexml_fix.rb +14 -0
  125. metadata +317 -0
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Hex < Base
4
+ class << self
5
+ def return_type
6
+ :string
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Hour < Base
4
+ class << self
5
+ def return_type
6
+ :integer
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Log < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["ln"]
7
+ end
8
+
9
+ def return_type
10
+ :float
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Log10 < Base
4
+ class << self
5
+ def return_type
6
+ :float
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Log2 < Base
4
+ class << self
5
+ def return_type
6
+ :float
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Lower < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["downcase", "lcase"]
7
+ end
8
+
9
+ def return_type
10
+ :string
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Ltrim < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["lstrip"]
7
+ end
8
+
9
+ def return_type
10
+ :string
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Md5 < Base
4
+ class << self
5
+ def return_type
6
+ :string
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Microseconds < Base
4
+ class << self
5
+ def return_type
6
+ :integer
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Milliseconds < Base
4
+ class << self
5
+ def return_type
6
+ :integer
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Minute < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["min"]
7
+ end
8
+
9
+ def return_type
10
+ :integer
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Month < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["mon"]
7
+ end
8
+
9
+ def return_type
10
+ :integer
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Octal < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["oct"]
7
+ end
8
+
9
+ def return_type
10
+ :float
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Radians < Base
4
+ class << self
5
+ def return_type
6
+ :float
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Round < Base
4
+ class << self
5
+ def return_type
6
+ :integer
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Rtrim < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["rstrip"]
7
+ end
8
+
9
+ def return_type
10
+ :string
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Second < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["sec"]
7
+ end
8
+
9
+ def return_type
10
+ :integer
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Sign < Base
4
+ class << self
5
+ def return_type
6
+ :float
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Sin < Base
4
+ class << self
5
+ def return_type
6
+ :float
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class SquareRoot < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["sqrt", "sq_rt"]
7
+ end
8
+
9
+ def return_type
10
+ :float
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Tan < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["tangent"]
7
+ end
8
+
9
+ def return_type
10
+ :float
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Trim < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["strip"]
7
+ end
8
+
9
+ def return_type
10
+ :string
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Upper < Base
4
+ class << self
5
+ def modifier_names
6
+ super + ["upcase", "ucase"]
7
+ end
8
+
9
+ def return_type
10
+ :string
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Week < Base
4
+ class << self
5
+ def return_type
6
+ :integer
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Searchlogic
2
+ module Modifiers
3
+ class Year < Base
4
+ class << self
5
+ def return_type
6
+ :integer
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,148 @@
1
+ module Searchlogic #:nodoc:
2
+ module Search #:nodoc:
3
+ # = Searchlogic
4
+ #
5
+ # Please refer the README.rdoc for usage, examples, and installation.
6
+ class Base
7
+ include Searchlogic::Shared::Utilities
8
+ include Searchlogic::Shared::VirtualClasses
9
+
10
+ # Options ActiveRecord allows when searching
11
+ AR_FIND_OPTIONS = ::ActiveRecord::Base.valid_find_options
12
+
13
+ # Options ActiveRecord allows when performing calculations
14
+ AR_CALCULATIONS_OPTIONS = (::ActiveRecord::Base.valid_calculations_options - [:select, :limit, :offset, :order, :group])
15
+
16
+ AR_OPTIONS = (AR_FIND_OPTIONS + AR_CALCULATIONS_OPTIONS).uniq
17
+
18
+ # Options that ActiveRecord doesn't suppport, but Searchlogic does
19
+ SPECIAL_FIND_OPTIONS = [:order_by, :order_as, :page, :per_page, :priority_order, :priority_order_by, :priority_order_as]
20
+
21
+ # Valid options you can use when searching
22
+ OPTIONS = SPECIAL_FIND_OPTIONS + AR_OPTIONS # the order is very important, these options get set in this order
23
+
24
+ attr_accessor *AR_OPTIONS
25
+ attr_writer :scope
26
+
27
+ class << self
28
+ # Used in the ActiveRecord methods to determine if Searchlogic should get involved or not.
29
+ # This keeps Searchlogic out of the way unless it is needed.
30
+ def needed?(model_class, options)
31
+ return false if options.blank?
32
+
33
+ SPECIAL_FIND_OPTIONS.each do |option|
34
+ return true if options.symbolize_keys.keys.include?(option)
35
+ end
36
+
37
+ Searchlogic::Conditions::Base.needed?(model_class, options[:conditions])
38
+ end
39
+ end
40
+
41
+ def initialize(init_options = {})
42
+ self.options = init_options
43
+ end
44
+
45
+ # Flag to determine if searchlogic is acting as a filter for the ActiveRecord search methods.
46
+ # By filter it means that searchlogic is being used on the default ActiveRecord search methods, like all, count, find(:all), first, etc.
47
+ def acting_as_filter=(value)
48
+ @acting_as_filter = value
49
+ end
50
+
51
+ # See acting_as_filter=
52
+ def acting_as_filter?
53
+ @acting_as_filter == true
54
+ end
55
+
56
+ # Specific implementation of cloning
57
+ def clone
58
+ options = {}
59
+ (AR_OPTIONS - [:conditions]).each { |option| options[option] = instance_variable_get("@#{option}") }
60
+ options[:conditions] = conditions.conditions
61
+ SPECIAL_FIND_OPTIONS.each { |option| options[option] = send(option) }
62
+ obj = self.class.new(options)
63
+ obj.protect = protected?
64
+ obj.scope = scope
65
+ obj
66
+ end
67
+ alias_method :dup, :clone
68
+
69
+ # Makes using searchlogic in the console less annoying and keeps the output meaningful and useful
70
+ def inspect
71
+ current_find_options = {}
72
+ (AR_OPTIONS - [:conditions]).each do |option|
73
+ value = send(option)
74
+ next if value.nil?
75
+ current_find_options[option] = value
76
+ end
77
+ conditions_value = conditions.conditions
78
+ current_find_options[:conditions] = conditions_value unless conditions_value.blank?
79
+ current_find_options[:scope] = scope unless scope.blank?
80
+ "#<#{klass}Search #{current_find_options.inspect}>"
81
+ end
82
+
83
+ # Merges all joins together, including the scopes joins for
84
+ def joins
85
+ all_joins = (safe_to_array(conditions.auto_joins) + safe_to_array(order_by_auto_joins) + safe_to_array(priority_order_by_auto_joins) + safe_to_array(@joins)).uniq
86
+ all_joins.size <= 1 ? all_joins.first : all_joins
87
+ end
88
+
89
+ def limit=(value)
90
+ @set_limit = true
91
+ @limit = value.blank? || value == 0 ? nil : value.to_i
92
+ end
93
+
94
+ def limit
95
+ @limit ||= Config.search.per_page if !acting_as_filter? && !@set_limit
96
+ @limit
97
+ end
98
+
99
+ def offset=(value)
100
+ @offset = value.blank? ? nil : value.to_i
101
+ end
102
+
103
+ def options=(values)
104
+ return unless values.is_a?(Hash)
105
+ values.symbolize_keys.fast_assert_valid_keys(OPTIONS)
106
+ values.each { |key, value| send("#{key}=", value) }
107
+ end
108
+
109
+ # Sanitizes everything down into options ActiveRecord::Base.find can understand
110
+ def sanitize(searching = true)
111
+ find_options = {}
112
+
113
+ (searching ? AR_FIND_OPTIONS : AR_CALCULATIONS_OPTIONS).each do |find_option|
114
+ value = send(find_option)
115
+ next if value.blank?
116
+ find_options[find_option] = value
117
+ end
118
+
119
+ find_options
120
+ end
121
+
122
+ def select
123
+ @select ||= "DISTINCT #{klass.connection.quote_table_name(klass.table_name)}.*" if !joins.blank? && Config.search.remove_duplicates?
124
+ @select
125
+ end
126
+
127
+ def scope
128
+ @scope ||= {}
129
+ end
130
+
131
+ private
132
+ def safe_to_array(o)
133
+ case o
134
+ when NilClass
135
+ []
136
+ when Array
137
+ o
138
+ else
139
+ [o]
140
+ end
141
+ end
142
+
143
+ def array_of_strings?(o)
144
+ o.is_a?(Array) && o.all?{|obj| obj.is_a?(String)}
145
+ end
146
+ end
147
+ end
148
+ end