Skip to content

Instantly share code, notes, and snippets.

@kossoff
Last active September 18, 2025 12:08
Show Gist options
  • Save kossoff/48db6928a7a187d12987f1bb51c236ba to your computer and use it in GitHub Desktop.
Save kossoff/48db6928a7a187d12987f1bb51c236ba to your computer and use it in GitHub Desktop.
jQuery DataTables & RoR
# frozen_string_literal: true
# put it in app/controllers/concerns
# Backend for jQuery DataTables, https://datatables.net/
module DataTables
include Pagy::Backend
private
def datatables_data(model)
@model = model
@objects = current_objects
@total_objects = model.where(conditions).count
end
def current_objects
current_page = (params[:start].to_i / params[:length].to_i) + 1
_pagy, objects = pagy_countless(@model.where(conditions)
.order(order(params[:order])),
countless_minimal: true,
page: current_page,
limit: params[:length])
objects
end
def datatable_columns(column_id)
@model.arel_table[%w[id title][column_id.to_i]]
end
def order(order_hash)
return if order_hash.blank?
order_hash.to_unsafe_h
.map { |o| datatable_columns(params[:order][o.first][:column]).send(params[:order][o.first][:dir]) }
end
def conditions
@search_string = params[:search][:value].downcase.gsub("'", "''")
end
end
= check_box_tag :some_filter, 0, @some_filter
= label_tag :some_filter, 'Some Filter'
table#model
javascript:
$(document).on('turbo:load.model', function () {
var dataTable = $("#model").DataTable({
ajax: {
url: '#{model_path}',
data: function(d){
d.some_filter = $('#some_filter').is(':checked');
},
},
processing: true,
serverSide: true,
destroy: true,
columns: [
{ data: 'id', title: 'ID' },
{ data: 'title', title: 'Title' },
{ data: 'another_col', title: 'Another columns', orderable: false },
],
searching: true,
order: [[0, 'desc']],
createdRow: function(row, data, dataIndex) {
$(row).attr('data-href', data.id);
}
});
$('.dataTable').on('click', 'tbody tr', function() {
document.location = "#{model_path}/" + $(this).data('href');
});
document.addEventListener("turbo:before-cache", function() {
if (dataTable !== null) {
dataTable.destroy();
dataTable = null;
}
});
$('#some_filter').on('change', function(e){
dataTable.ajax.reload();
});
});
$(document).on('turbo:before-render', function() {
$(document).off('turbo:load.model');
});
# frozen_string_literal: true
json.draw params[:draw] || 1
json.recordsTotal @total_objects
json.recordsFiltered @total_objects
json.data @objects do |object|
json.id object.id
json.title object.title
json.another_col object.another_col
end
# frozen_string_literal: true
class ModelController < ApplicationController
include DataTables
def index
cookies.permanent[:some_filter] ||= false
cookies.permanent[:some_filter] = params[:some_filter] if params[:some_filter].present?
@some_filter = ActiveModel::Type::Boolean.new.cast(cookies[:some_filter])
respond_to do |format|
format.html
format.json do
where_condition = ''
'model.column = true' if @some_filter == true
datatables_data(Model.where(where_condition))
render layout: false
end
end
end
private
# <- ajax DataTables
def conditions
super
# some sql for search in table
Arel.sql "(LOWER(UNACCENT(model.title)) LIKE UNACCENT('%#{@search_string}%')"
end
# for columns ordering
def datatable_columns(column_id)
Arel.sql(%w[table.id table.title table.another_col][column_id.to_i])
end
# ajax DataTables -->
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment