A plugin for Administrate to use Ransack for filtering resources.
Features:
gem 'administrate_ransack'
(and execute bundle
)prepend AdministrateRansack::Searchable
bin/rails generate administrate:views:index Post
):<%= render('administrate_ransack/filters') %>
class Post < ApplicationRecord
# ...
class << self
def ransackable_attributes(_auth_object = nil)
%w[title description]
end
def ransackable_associations(_auth_object = nil)
%w[author]
end
end
end
attribute_labels
: hash used to override the field labels, ex. { title: "The title" }
attribute_types
: hash used to specify the filter fields, ex. { title: Administrate::Field::String }
search_path
: the path to use for searching (form URL)namespace
: the namespace used by Administrate, ex. :supervisor
admin_label
method to the target model which returns a string while the collection can by filtered with admin_scope
. Example:# Sample post model
class Post < ApplicationRecord
scope :admin_scope, -> { where(published: true) }
def admin_label
title.upcase
end
end
<!-- Set options for an association named: tags -->
<%= render('administrate_ransack/filters', options: { tags: 'select' } ) %>
ransackable_scopes
in the model, example:# Sample post model
class Post < ApplicationRecord
scope :recents, ->(dt = 1.month.ago) { where('dt > ?', dt).order(dt: :desc) }
scope :by_category, ->(category) { where(category: category) }
class << self
def ransackable_scopes(_auth_object = nil)
%i[by_category recents]
end
end
end
<!-- Sample index view -->
<%= render(
'administrate_ransack/filters',
attribute_types: { recents: Administrate::Field::DateTime, by_category: Administrate::Field::String }
) %>
show_search_bar?
in the controller or removing the bar from the view)datetime_field
method which produces a datetime-local
input field, at the moment this type of element is not broadly supported, a workaround is to include flatpickr datetime library.
flatpickr
function is available in the global scope and applies it to the datetime-local
filter inputs; <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr@4.5.7/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr@4.5.7/dist/flatpickr.min.js"></script>
<script>
// optionally change the flatpikr options:
window.flatpickr_filters_options = { dateFormat: "Y-m-d" };
</script>
ransack_options
method in the controller, example:module Admin
class PostsController < Admin::ApplicationController
prepend AdministrateRansack::Searchable
def ransack_options
# raises an exception on unknown parameters
{ ignore_unknown_conditions: false }
end
end
end
<%
# In alternative prepare an hash in the dashboard like RANSACK_TYPES = {}
attribute_types = {
title: Administrate::Field::String,
author: Administrate::Field::BelongsTo,
category: Administrate::Field::Select.with_options(collection: Post.categories.to_a),
published: Administrate::Field::Boolean
}
attribute_labels = {
author: 'Written by',
title: nil
}
%>
<%= render(
'administrate_ransack/filters',
attribute_types: attribute_types,
attribute_labels: attribute_labels,
search_path: admin_root_path
) %>
RANSACK_TYPES
):<%= render('administrate_ransack/filters', attribute_types: @dashboard.class::RANSACK_TYPES) %>
.main-content__body {
display: inline-block;
width: calc(100% - 320px);
vertical-align: top;
}
[data-administrate-ransack-filters] {
display: inline-block;
padding-left: 10px;
padding-top: 10px;
width: 300px;
}
[data-administrate-ransack-filters] .filter {
margin-bottom: 10px;
}
[data-administrate-ransack-filters] .filters-buttons {
margin-top: 30px;
}
Screenshot:
[data-administrate-ransack-filters] {
border: 1px solid #ddd;
padding: 10px;
text-align: center;
}
[data-administrate-ransack-filters] .filters {
display: inline-block;
}
[data-administrate-ransack-filters] .filter, [data-administrate-ransack-filters] .filter > label {
display: inline-block;
}
[data-administrate-ransack-filters] .filter > input {
display: inline-block;
width: auto;
}
[data-administrate-ransack-filters] .filters-buttons {
display: inline-block;
margin-left: 20px;
}
Screenshot:
AdministrateRansack::Searchable
) and create your own search query in a controller (but you need to assign the Ransack search object to @ransack_results
for the filters partial), for example: def scoped_resource
@ransack_results = super.ransack(params[:q])
@ransack_results.result(distinct: true)
end
jsonb
field adding to a Post model: ransacker :keywords do
Arel.sql("posts.metadata ->> 'keywords'")
end
<%= link_to("Tag's posts", admin_posts_path('q[tags_id_in][]': page.resource.id), class: "button") %>
If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
Or consider offering me a coffee, it's a small thing but it is greatly appreciated: about me.
The gem is available as open source under the terms of the MIT License.