tab/app/controllers/concerns/data_table.rb

103 lines
2.5 KiB
Ruby
Raw Normal View History

2015-09-10 18:12:12 +00:00
class DataTable
def initialize user, params
@user = user
@params = sanitize_params(params)
@transactions = TransactionsQuery.new(@user)
@table = @transactions.arel_table
end
2015-09-10 19:09:57 +00:00
def json
2015-09-11 10:00:49 +00:00
{
draw: @params[:draw],
recordsTotal: @user.transactions.count,
recordsFiltered: count,
data: data
}
2015-09-10 19:09:57 +00:00
end
2015-09-11 10:00:49 +00:00
private
2015-09-10 19:09:57 +00:00
def data
2015-09-11 12:10:47 +00:00
run_query(paginated_query.project(Arel.star)).map do |record|
record.reject! {|k,v| k.is_a? Numeric} # Remove unneeded query results
end
2015-09-11 10:00:49 +00:00
end
def count
run_query(query.project(Arel.star.count)).first[0]
end
def paginated_query
query.skip(@params[:start]).take(@params[:length])
2015-09-10 19:09:57 +00:00
end
2015-09-10 18:12:12 +00:00
def query
2015-09-11 10:07:39 +00:00
q = @transactions.query
q.where(predicate) if predicate
q
2015-09-10 18:12:12 +00:00
end
2015-09-11 10:00:49 +00:00
def predicate
@predicate ||= [
*range_predicates(:amount),
2015-09-10 19:09:57 +00:00
*range_predicates(:time),
eq_predicate(:peer),
eq_predicate(:issuer),
like_predicate(:message)
].compact.inject { |l, r| l.and(r) }
2015-09-10 18:12:12 +00:00
end
def range_predicates name
col = @params[:columns][name]
[
2015-09-11 08:46:03 +00:00
(@table[name].gteq(col[:lower]) if col[:lower]),
(@table[name].lteq(col[:upper]) if col[:upper])
2015-09-10 18:12:12 +00:00
]
end
2015-09-10 19:09:57 +00:00
def eq_predicate name
2015-09-11 08:46:03 +00:00
value = @params[:columns][name][:value]
@table[name].eq(value) if value
2015-09-10 19:09:57 +00:00
end
2015-09-10 17:41:47 +00:00
2015-09-10 19:09:57 +00:00
def like_predicate name
2015-09-11 08:46:03 +00:00
value = @params[:columns][name][:value]
@table[name].matches("%#{value}%") if value
end
2015-09-11 10:00:49 +00:00
def run_query query
ActiveRecord::Base.connection.execute(query.to_sql)
end
def sanitize_params(params)
# Parsing according to https://datatables.net/manual/server-side
clean = {
draw: params.require(:draw).to_i,
start: params.require(:start).to_i,
length: params.require(:length).to_i,
columns: Hash.new
}
params.require(:columns).each do |i, column|
2015-09-11 09:55:26 +00:00
type, *values = column.require(:search)[:value].split(':')
value = values.join(':') unless values.empty?
h = clean[:columns][column.require(:data).to_sym] = {
name: column[:name],
searchable: column[:searchable] == 'true',
orderable: column[:orderable] == 'true',
type: type
}
if type == 'number-range'
2015-09-11 09:55:26 +00:00
h[:lower], h[:upper] = value.split('~').map do |euros|
(euros.to_f * 100).to_i rescue nil
end
elsif type == 'date-range'
2015-09-11 09:55:26 +00:00
h[:lower], h[:upper] = value.split('~').map do |string|
string.to_datetime rescue nil
end
else
h[:value] = value
end
end
return clean
end
end