Class: S2P::Search

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Validations
Defined in:
lib/s2p/search.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params = {}) ⇒ Search

Returns a new instance of Search.



181
182
183
184
185
186
187
188
189
190
# File 'lib/s2p/search.rb', line 181

def initialize(params={})
  @params     = params.symbolize_keys
  @conditions = self.class.conditions.select { |k,v| @params[k].present? }

  @sort_by_key = @params.fetch(:order_by, self.class.sort_by_default_key).to_sym
  @sort_order  = @params.fetch(:sort_order, self.class.sort_order_defaults[@sort_by_key]).to_sym

  # FIXME: Should this be a validation instead?
  setup(**params) if respond_to?(:setup)
end

Class Attribute Details

.fromObject (readonly)

Returns the value of attribute from.



176
177
178
# File 'lib/s2p/search.rb', line 176

def from
  @from
end

Instance Attribute Details

#conditionsObject (readonly)

Returns the value of attribute conditions.



179
180
181
# File 'lib/s2p/search.rb', line 179

def conditions
  @conditions
end

#paramsObject (readonly)

Returns the value of attribute params.



179
180
181
# File 'lib/s2p/search.rb', line 179

def params
  @params
end

#resultsObject (readonly)

Returns the value of attribute results.



179
180
181
# File 'lib/s2p/search.rb', line 179

def results
  @results
end

#scopesObject (readonly)

Returns the value of attribute scopes.



179
180
181
# File 'lib/s2p/search.rb', line 179

def scopes
  @scopes
end

Class Method Details

.additional_search_params(*keys) ⇒ Object



18
19
20
# File 'lib/s2p/search.rb', line 18

def additional_search_params(*keys)
  @additional_search_params = keys
end

.cond(key, &scope) ⇒ Object



89
90
91
# File 'lib/s2p/search.rb', line 89

def cond(key, &scope)
  conditions[key] = scope
end

.cond_cont(*keys) ⇒ Object



170
171
172
173
174
# File 'lib/s2p/search.rb', line 170

def cond_cont(*keys)
  keys.each do |key|
    cond(key) { |s,v| s.where("#{from.table_name}.#{key} like ?", "%#{v}%") }
  end
end

.cond_eq(*keys) ⇒ Object



97
98
99
100
101
# File 'lib/s2p/search.rb', line 97

def cond_eq(*keys)
  keys.each do |key|
    cond_eq!(key, key)
  end
end

.cond_eq!(key, column) ⇒ Object



103
104
105
# File 'lib/s2p/search.rb', line 103

def cond_eq!(key, column)
  cond(key) { |s,v| s.where(column => v) }
end

.cond_gt(*keys) ⇒ Object



153
154
155
156
157
# File 'lib/s2p/search.rb', line 153

def cond_gt(*keys)
  keys.each do |key|
    cond(key) { |s,v| s.where("#{from.table_name}.#{key} > ?", v) }
  end
end

.cond_gte(*keys) ⇒ Object



143
144
145
146
147
# File 'lib/s2p/search.rb', line 143

def cond_gte(*keys)
  keys.each do |key|
    cond_gte!(key, "#{from.table_name}.#{key}")
  end
end

.cond_gte!(key, column) ⇒ Object



149
150
151
# File 'lib/s2p/search.rb', line 149

def cond_gte!(key, column)
  cond(key) { |s,v| s.where("#{column} >= ?", v) }
end

.cond_like(*keys) ⇒ Object



117
118
119
120
121
# File 'lib/s2p/search.rb', line 117

def cond_like(*keys)
  keys.each do |key|
    cond_like!(key, "#{from.table_name}.#{key}")
  end
end

.cond_like!(key, column) ⇒ Object



123
124
125
# File 'lib/s2p/search.rb', line 123

def cond_like!(key, column)
  cond(key) { |s,v| s.where("#{column} like ?", "%#{v}%") }
end

.cond_lt(*keys) ⇒ Object



127
128
129
130
131
# File 'lib/s2p/search.rb', line 127

def cond_lt(*keys)
  keys.each do |key|
    cond(key) { |s,v| s.where("#{from.table_name}.#{key} < ?", v) }
  end
end

.cond_lte(*keys) ⇒ Object



133
134
135
136
137
# File 'lib/s2p/search.rb', line 133

def cond_lte(*keys)
  keys.each do |key|
    cond_lte!(key, "#{from.table_name}.#{key}")
  end
end

.cond_lte!(key, column) ⇒ Object



139
140
141
# File 'lib/s2p/search.rb', line 139

def cond_lte!(key, column)
  cond(key) { |s,v| s.where("#{column} <= ?", v) }
end

.cond_range(*ranges) ⇒ Object



159
160
161
162
163
# File 'lib/s2p/search.rb', line 159

def cond_range(*ranges)
  ranges.each do |start_key, end_key, column|
    cond_range!(start_key, end_key, column)
  end
end

.cond_range!(start_key, end_key, column) ⇒ Object



165
166
167
168
# File 'lib/s2p/search.rb', line 165

def cond_range!(start_key, end_key, column)
  cond_gte!(start_key, column)
  cond_lte!(end_key, column)
end

.cond_start(*keys) ⇒ Object



107
108
109
110
111
# File 'lib/s2p/search.rb', line 107

def cond_start(*keys)
  keys.each do |key|
    cond_start!(key, "#{from.table_name}.#{key}")
  end
end

.cond_start!(key, column) ⇒ Object



113
114
115
# File 'lib/s2p/search.rb', line 113

def cond_start!(key, column)
  cond(key) { |s,v| s.where("#{column} like ?", "#{v}%") }
end

.conditionsObject



93
94
95
# File 'lib/s2p/search.rb', line 93

def conditions
  @conditions ||= {}
end

.create(params = {}) ⇒ Object



22
23
24
# File 'lib/s2p/search.rb', line 22

def create(params={})
  new(params).tap(&:save)
end

.default_sort_order(params) ⇒ Object



81
82
83
# File 'lib/s2p/search.rb', line 81

def default_sort_order(params)
  sort_order_defaults.update(params).symbolize_keys!
end

.scopeObject



10
11
12
# File 'lib/s2p/search.rb', line 10

def scope
  @before_callback.present? ? @before_callback[from] : from
end

.search_keysObject



14
15
16
# File 'lib/s2p/search.rb', line 14

def search_keys
  [:page, :sort_order, :order_by] + conditions.keys + (@additional_search_params || [])
end

.searches(from) ⇒ Object



26
27
28
# File 'lib/s2p/search.rb', line 26

def searches(from)
  @from ||= from
end

.setup(&conds) ⇒ Object



6
7
8
# File 'lib/s2p/search.rb', line 6

def setup(&conds)
  @before_callback = conds
end

.sort_by_default(key) ⇒ Object



73
74
75
# File 'lib/s2p/search.rb', line 73

def sort_by_default(key)
  @sort_by_default_key = key
end

.sort_by_default_keyObject



77
78
79
# File 'lib/s2p/search.rb', line 77

def sort_by_default_key
  @sort_by_default_key || :id
end

.sort_by_filtersObject

FIXME: Consider introducing a SortFilter object of some sort?



65
66
67
68
69
70
71
# File 'lib/s2p/search.rb', line 65

def sort_by_filters
  @sort_by_filters ||= Hash.new { |h,k| h[k] = {} }
  @sort_by_filters[:id][:asc]  ||= ->(s) { s.reorder(id: :asc) }
  @sort_by_filters[:id][:desc] ||= ->(s) { s.reorder(id: :desc) }

  @sort_by_filters
end

.sort_order_defaultsObject



85
86
87
# File 'lib/s2p/search.rb', line 85

def sort_order_defaults
  @sort_order_defaults ||=  Hash.new { |h,k| h[k] = :asc }
end

.sortable_by(*names, table_name: self.from.table_name) ⇒ Object



30
31
32
33
34
35
36
37
# File 'lib/s2p/search.rb', line 30

def sortable_by(*names, table_name: self.from.table_name)
  names.each do |name|
    sortable_by!(name,
      asc: ->(s) { s.reorder("#{table_name}.#{name} asc")  },
      desc: ->(s) { s.reorder("#{table_name}.#{name} desc") }
    )
  end
end

.sortable_by!(name, asc:, desc:) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/s2p/search.rb', line 46

def sortable_by!(name, asc:, desc:)
  name = name.to_sym

  case asc
  when String
    sort_by_filters[name][:asc] = ->(s) { s.reorder(asc) }
  when Proc
    sort_by_filters[name][:asc] = asc
  end

  case desc
  when String
    sort_by_filters[name][:desc] = ->(s) { s.reorder(desc) }
  when Proc
    sort_by_filters[name][:desc] = desc
  end
end

.sortable_by_alias(sort_alias, sort_condition) ⇒ Object



39
40
41
42
43
44
# File 'lib/s2p/search.rb', line 39

def sortable_by_alias(sort_alias, sort_condition)
  sortable_by!(sort_alias,
    asc:  ->(s) { s.reorder("#{sort_condition} asc")  },
    desc: ->(s) { s.reorder("#{sort_condition} desc") }
  )
end

Instance Method Details

#saveObject



192
193
194
195
196
197
198
199
200
# File 'lib/s2p/search.rb', line 192

def save
  if valid?
    @results = @conditions.inject(self.class.scope) { |relation, (key, scope)|
      scope.call(relation, @params[key], @params)
    }

    @results = sorted(@results)
  end
end

#sorted(relation) ⇒ Object



202
203
204
# File 'lib/s2p/search.rb', line 202

def sorted(relation)
  self.class.sort_by_filters[@sort_by_key][@sort_order][relation]
end

#to_sObject



206
207
208
# File 'lib/s2p/search.rb', line 206

def to_s
  @params.select { |k,v| v.present? }.map { |k,v| "<strong>#{k.to_s.humanize}</strong>: #{v}" }.join(" + ")
end