/
base.rb
124 lines (101 loc) · 4.11 KB
/
base.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
module Searchgasm #:nodoc:
module Search #:nodoc:
# = Searchgasm
#
# Please refer the README.rdoc for usage, examples, and installation.
class Base
include Searchgasm::Shared::Utilities
include Searchgasm::Shared::VirtualClasses
# Options ActiveRecord allows when searching
AR_FIND_OPTIONS = ::ActiveRecord::Base.valid_find_options
# Options ActiveRecord allows when performing calculations
AR_CALCULATIONS_OPTIONS = (::ActiveRecord::Base.valid_calculations_options - [:select, :limit, :offset, :order, :group])
AR_OPTIONS = (AR_FIND_OPTIONS + AR_CALCULATIONS_OPTIONS).uniq
# Options that ActiveRecord doesn't suppport, but Searchgasm does
SPECIAL_FIND_OPTIONS = [:order_by, :order_as, :page, :per_page, :priority_order, :priority_order_by, :priority_order_as]
# Valid options you can use when searching
OPTIONS = SPECIAL_FIND_OPTIONS + AR_OPTIONS # the order is very important, these options get set in this order
attr_accessor *AR_OPTIONS
attr_reader :auto_joins
class << self
# Used in the ActiveRecord methods to determine if Searchgasm should get involved or not.
# This keeps Searchgasm out of the way unless it is needed.
def needed?(model_class, options)
return false if options.blank?
SPECIAL_FIND_OPTIONS.each do |option|
return true if options.symbolize_keys.keys.include?(option)
end
Searchgasm::Conditions::Base.needed?(model_class, options[:conditions])
end
end
def initialize(init_options = {})
self.options = init_options
end
# Flag to determine if searchgasm is acting as a filter for the ActiveRecord search methods.
# The purpose of this is to determine if Config.per_page should be implemented.
def acting_as_filter=(value)
@acting_as_filter = value
end
# See acting_as_filter=
def acting_as_filter?
@acting_as_filter == true
end
# Specific implementation of cloning
def clone
options = {}
(OPTIONS - [:conditions]).each { |option| options[option] = send(option) }
options[:conditions] = conditions.conditions
obj = self.class.new(options)
obj.protect = protected?
obj.scope = scope
obj
end
alias_method :dup, :clone
# Makes using searchgasm in the console less annoying and keeps the output meaningful and useful
def inspect
current_find_options = {}
(AR_OPTIONS - [:conditions]).each do |option|
value = send(option)
next if value.nil?
current_find_options[option] = value
end
conditions_value = conditions.conditions
current_find_options[:conditions] = conditions_value unless conditions_value.blank?
current_find_options[:scope] = scope unless scope.blank?
"#<#{klass}Search #{current_find_options.inspect}>"
end
def joins
merge_joins(@joins, auto_joins)
end
def limit=(value)
@set_limit = true
@limit = value.blank? || value == 0 ? nil : value.to_i
end
def limit
@limit ||= Config.per_page if !acting_as_filter? && !@set_limit
@limit
end
def offset=(value)
@offset = value.blank? ? nil : value.to_i
end
def options=(values)
return unless values.is_a?(Hash)
values.symbolize_keys.fast_assert_valid_keys(OPTIONS)
values.each { |key, value| send("#{key}=", value) }
end
# Sanitizes everything down into options ActiveRecord::Base.find can understand
def sanitize(searching = true)
find_options = {}
(searching ? AR_FIND_OPTIONS : AR_CALCULATIONS_OPTIONS).each do |find_option|
value = send(find_option)
next if value.blank?
find_options[find_option] = value
end
find_options
end
def scope
@scope ||= {}
end
end
end
end