Module: TableOnSteroids::TableConcern

Extended by:
ActiveSupport::Concern
Defined in:
app/controllers/concerns/table_on_steroids/table_concern.rb

Instance Method Summary collapse

Instance Method Details

#all_column_search(objects, columns_on_steroid, query, table_on_steroids = nil) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'app/controllers/concerns/table_on_steroids/table_concern.rb', line 119

def all_column_search(objects, columns_on_steroid, query, table_on_steroids = nil)
  global_active_record_search_key = table_on_steroids&.dig(:global_active_record_search_key) || :id
  global_array_search_key_index = table_on_steroids&.dig(:global_array_search_key_index) || 0
  global_search_key = (objects && objects[0].is_a?(Array) ? global_array_search_key_index : global_active_record_search_key)
  global_search_key_params = {}
  matched_object_keys = []

  %i[activerecord array].each do |t|
    columns_on_steroid.each do |_key, value|
      next unless value[t].present? && ((value[t][:search_lambda].present? && !%w[date integer].include?(value[:datatype])) || value[t][:global_search_lambda].present?)

      objects_returned = if value[t][:global_search_lambda].present?
                           value[t][:global_search_lambda].call(objects, query)
                         else
                           value[t][:search_lambda].call(objects, query)
                         end
      objects_returned&.each { |o| matched_object_keys << o[global_search_key] }
    end
  end

  if objects.is_a?(ActiveRecord::Base) || objects.is_a?(ActiveRecord::Relation)
    global_search_key_params[global_active_record_search_key] = matched_object_keys.uniq
    objects = objects.where(global_search_key_params)
  elsif objects.is_a?(Array)
    objects = objects.select { |o| o if matched_object_keys.uniq.include?(o[global_search_key]) }
  end
end

#filter_and_order(objects, columns_on_steroid, global_search = nil, include_counts = false, all_pages = false, table_on_steroids = nil) ⇒ Object



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
# File 'app/controllers/concerns/table_on_steroids/table_concern.rb', line 42

def filter_and_order(objects, columns_on_steroid, global_search = nil, include_counts = false, all_pages = false, table_on_steroids = nil)
  # execute the global search if you have one
  if params[:search].present?
    objects = global_search.call(objects, params[:search]) if global_search
    objects = all_column_search(objects, columns_on_steroid, params[:search], table_on_steroids) unless global_search
  end

  %i[activerecord array].each do |t|
    # column search
    objects = objects_where(objects, columns_on_steroid, t)

    # apply filters
    if params[:filters].present?
      params[:filters].each_pair do |k, v|
        filter = columns_on_steroid[k]
        next unless filter.present? && filter[t].present?

        objects = filter[t][:filter_lambda].call(objects, v)
      end
    end

    #order
    if params&.dig(:knowledge,:order) && (object_order = columns_on_steroid[params[:knowledge][:order]]).present?       
      if(object_order[t] && object_order[t][:order_lambda])
        direction = (params&.dig(:knowledge,:ascending).to_s == 'true') ? 'asc' : 'desc'
        objects = objects.reorder(nil) if(objects.is_a?(ActiveRecord::Base) || objects.is_a?(ActiveRecord::Relation))
        objects = object_order[t][:order_lambda].call(objects, direction)
      end
    elsif object_order = columns_on_steroid[table_on_steroids&.dig(:default_order_column)]
      if(object_order[t] && object_order[t][:order_lambda])
        direction = object_order[t][:default_order_direction] || 'asc'
        objects = objects.reorder(nil) if(objects.is_a?(ActiveRecord::Base) || objects.is_a?(ActiveRecord::Relation))
        objects = object_order[t][:order_lambda].call(objects, direction)
      end
    elsif (object_order = columns_on_steroid.select { |_c, v| v[t] && v[t][:default_order] }.first&.last).present?
      if object_order[t] && object_order[t][:order_lambda]
        objects = objects.reorder(nil) if objects.is_a?(ActiveRecord::Base) || objects.is_a?(ActiveRecord::Relation)
        objects = object_order[t][:order_lambda].call(objects)
      end
    elsif objects.is_a?(ActiveRecord::Base) || objects.is_a?(ActiveRecord::Relation)
      # objects = objects.order('created_at desc')
    end
  end

  # pagination
  return (include_counts ? [objects, 1, objects.count] : objects) if all_pages

  # GO to specific object page
  page = get_page(objects, params, table_on_steroids)

  if objects.is_a?(ActiveRecord::Base) || objects.is_a?(ActiveRecord::Relation)
    objects = objects.page(page).per(OBJECTS_PER_PAGE)
    total_pages = objects.total_pages
    total_count = objects.total_count
  else
    objects = Kaminari.paginate_array(objects).page(page).per(OBJECTS_PER_PAGE)
    total_pages = objects.total_pages
    total_count = objects.total_count
  end
  include_counts ? [objects, total_pages, total_count, page] : objects
end

#get_page(objects, params, table_on_steroids) ⇒ Object



224
225
226
227
228
229
230
231
232
233
234
# File 'app/controllers/concerns/table_on_steroids/table_concern.rb', line 224

def get_page(objects, params, table_on_steroids)
  active_record_object_fetch_opts = table_on_steroids&.dig(:active_record_object_fetch_opts)
  key_lambda = table_on_steroids&.dig(:key_lambda)
  return params[:page] unless active_record_object_fetch_opts && key_lambda

  object = objects.where(active_record_object_fetch_opts).first
  return params[:page] unless object

  index = objects.index { |o| key_lambda.call(o) == key_lambda.call(object) }
  index ? index / OBJECTS_PER_PAGE + 1 : params[:page]
end

#object_where_integer(integer, operator, value) ⇒ Object



183
184
185
186
187
188
189
190
191
192
# File 'app/controllers/concerns/table_on_steroids/table_concern.rb', line 183

def object_where_integer(integer, operator, value)
  case operator
  when '<', '>='
    integer.to_f < value.to_f
  when '='
    integer.to_f == value.to_f
  when '>'
    integer.to_f > value.to_f
  end
end

#objects_where(objects, columns_on_steroid, t) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
# File 'app/controllers/concerns/table_on_steroids/table_concern.rb', line 147

def objects_where(objects, columns_on_steroid, t)
  columns_on_steroid.select do |_c, v|
    v[t] && v[t][:search_lambda].present?
  end .each do |c, v|
    if params['search_operator_' + c] # (v[:datatype].present? && ['date','integer'].include?(v[:datatype]))
      objects = v[t][:search_lambda].call(objects, params['search_' + c], params['search_operator_' + c]) if params['search_' + c] && !params['search_' + c].blank?
    else
      objects = v[t][:search_lambda].call(objects, params['search_' + c]) if params['search_' + c] && !params['search_' + c].blank?
    end
  end
  objects
end

#objects_where_date(objects, column, value, operator) ⇒ Object



160
161
162
163
164
165
166
167
168
169
# File 'app/controllers/concerns/table_on_steroids/table_concern.rb', line 160

def objects_where_date(objects, column, value, operator)
  case operator
  when '<', '>='
    objects.where((column + ' ' + operator + ' ?'), (value + ' 00:00:00'))
  when '>', '<='
    objects.where((column + ' ' + operator + ' ?'), (value + ' 23:59:59'))
  when '='
    objects.where((column + ' between ? and ?'), (value + ' 00:00:00'), (value + ' 23:59:59'))
  end
end

#objects_where_or(objects, columns_on_steroid) ⇒ Object

save for later



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'app/controllers/concerns/table_on_steroids/table_concern.rb', line 195

def objects_where_or(objects, columns_on_steroid)
  where_sql = ''
  values = []

  # search all columns
  unless query.blank?
    where_sql += columns_on_steroid.select do |_c, v|
                   v[:or_where_sql].present?
                 end .map do |_c, v|
      v[:or_where_sql].map do |w|
        w[:where]
      end .join(' or ')
    end .join(' or ')

    columns_on_steroid.select do |_c, v|
      v[:or_where_sql].present?
    end .map do |_c, v|
      v[:or_where_sql].each do |w|
        values << (w[:value] || ('%' + query + '%'))
      end
    end

    where_sql = ('(' + where_sql + ')') unless where_sql.blank?

    objects = objects.where(where_sql, *values)
  end
  objects
end

#objects_where_ruby_date(object, column, value, operator) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
# File 'app/controllers/concerns/table_on_steroids/table_concern.rb', line 171

def objects_where_ruby_date(object, column, value, operator)
  value = Date.strptime(value, '%m/%d/%Y').midnight
  case operator
  when '<'
    return object.send(column) < value
  when '>'
    return object.send(column) > value + 1.days - 1.seconds
  when '='
    return ((object.send(column) > value) && (object.send(column) < (value + 1.days - 1.seconds)))
  end
end

#table_csv(objects, columns_on_steroid) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'app/controllers/concerns/table_on_steroids/table_concern.rb', line 104

def table_csv(objects, columns_on_steroid)
  titles = []
  csvs = CSV.generate do |csv|
    columns_on_steroid.select { |_c, v| v[:download_value_lambda].present? }.each { |_c, v| (v[:download_label].present? ? titles.push(*v[:download_label]) : titles << v[:label]) }
    csv << titles
    objects.each do |o|
      vals = []
      columns_on_steroid.select { |_c, v| v[:download_value_lambda].present? }.each do |_c, v|
        vals.push(*v[:download_value_lambda].call(o))
      end
      csv << vals
    end
  end
end