SimpleCrud
Table of contents
Description
Simple Crud is a gem for Rails that simplifies writing standard CRUD actions, while also adding tools so it's not needed to write tests for them. Its main objective is replacing generally copy-pasted code like generic paginated, authenticated index methods for simple lines such as
simple_crud_for :index
It includes support for index, create, destroy, update and show, and options to specify whether it should apply pagination, authorization and if a particular serializer should be used. Keep in mind, though, that the idea is not to replace writing methods in controllers altogether, but only to replace most standard cases.
Installation
Add the following line to your application's Gemfile. The gem is named wor-simple_crud, but the require path is simple_crud, so tell Bundler where to find it:
gem 'wor-simple_crud', require: 'simple_crud'
And then execute:
$ bundle
Or install it yourself as:
$ gem install wor-simple_crud
simple_crud only depends on Rails itself. Authorization (Pundit by default) and pagination (wor-paginate by default) are opt-in: add whichever libraries you actually use to your own Gemfile too.
gem 'pundit'
gem 'wor-paginate'
See Paginate and Authorize below for the other supported libraries, or to skip either feature (authorize: false / paginate: false) and depend on neither.
Usage
Setup
Application controller
Before SimpleCrud can be used, some boilerplate is needed. Add the following to your ApplicationController (or every controller in case you don't want it included in all controllers)
include Pundit::Authorization
include Wor::Paginate
extend SimpleCrud
before_action :set_params
def set_params
SimpleCrudController.params = params
end
(Skip include Pundit::Authorization / include Wor::Paginate if you're using a different adapter, or authorize: false / paginate: false everywhere.)
Each controller
In case you need either update or create, create a method with the valid input params using standard rails:
def
params.permit(:first_name, :email, :last_name, :institution, :role)
end
For the actual crud methods, just use the lines you need
simple_crud_for :update
simple_crud_for :show
simple_crud_for :index
simple_crud_for :create
simple_crud_for :destroy
Each method supports different options, as in:
simple_crud_for :index, paginate: false, authorize: false, serializer: CustomSerializer
- Paginate: whether it should paginate or not.
truepaginates via the configured pagination adapter (wor-paginate by default),falsedoesn't paginate - Authorize: whether it should check authorization via the configured authorization adapter (Pundit by default)
- Authenticate: whether it should use Devise to check for a current_user
- Serializer: specify a particular serializer you should use
You'll need a few things so they work correctly:
Options
Paginate
Pagination defaults to wor-paginate and needs no extra options. Check its docs if you want to customize the output.
Three other pagination libraries have adapters built in too:
# Kaminari (https://github.com/kaminari/kaminari)
require 'simple_crud/pagination/kaminari_adapter'
SimpleCrud.configure { |config| config.pagination_adapter = SimpleCrud::Pagination::KaminariAdapter.new }
# will_paginate (https://github.com/mislav/will_paginate)
require 'simple_crud/pagination/will_paginate_adapter'
SimpleCrud.configure { |config| config.pagination_adapter = SimpleCrud::Pagination::WillPaginateAdapter.new }
# Pagy (https://github.com/ddnexus/pagy) -- requires `include Pagy::Method` in your ApplicationController
require 'simple_crud/pagination/pagy_adapter'
SimpleCrud.configure { |config| config.pagination_adapter = SimpleCrud::Pagination::PagyAdapter.new }
They render a plain JSON array rather than wor-paginate's {page:, count:, total_pages:, ...} envelope. None of the four pagination gems is installed automatically, so add whichever one you pick to your own Gemfile.
Want something else, or nothing at all? Write your own SimpleCrud::Pagination::Adapter:
class MyPaginationAdapter
include SimpleCrud::Pagination::Adapter
# Called from inside the generated index action when paginate: true.
# Must render the response itself.
def paginate(controller, klass, )
records = klass.some_pagination_method(controller.params[:page])
controller.render({ json: records }.merge())
end
end
SimpleCrud.configure { |config| config.pagination_adapter = MyPaginationAdapter.new }
Authorize
Authorization checks go through Pundit by default. Name the policy after the model plus Policy, e.g. AuthorPolicy, written as a regular Pundit policy:
class AuthorPolicy
attr_reader :user, :author
def initialize(user, )
@user = user
@author =
end
def show?
user.present?
end
end
Prefer CanCanCan or Action Policy instead? Both have adapters ready to go:
# CanCanCan (https://github.com/CanCanCommunity/cancancan)
require 'simple_crud/authorization/can_can_can_adapter'
SimpleCrud.configure do |config|
config. = SimpleCrud::Authorization::CanCanCanAdapter.new
end
# Action Policy (https://github.com/palkan/action_policy)
require 'simple_crud/authorization/action_policy_adapter'
SimpleCrud.configure do |config|
config. = SimpleCrud::Authorization::ActionPolicyAdapter.new
end
As with pagination, simple_crud ships the adapter code but not the library itself. Add cancancan or action_policy to your own Gemfile, whichever you pick.
Using something else, or skipping authorization entirely? Write your own SimpleCrud::Authorization::Adapter:
class MyAuthorizationAdapter
include SimpleCrud::Authorization::Adapter
# Called from inside a generated CRUD action. Raise (or otherwise halt
# the request) when the current user may not act on +record+.
def (controller, record)
controller.(record)
end
# Called once, when simple_crud_for is invoked, to fail fast if the
# given model has no authorization rules defined at all.
def policy_defined?(model_class)
Kernel.const_defined?("#{model_class}Policy")
end
end
SimpleCrud.configure do |config|
config. = MyAuthorizationAdapter.new
end
Authenticate
SimpleCrud will assume a current_user method. Future versions will support a custom model. Defining a current_user method in ApplicationController should work if you're using a different model, as of now.
Serializer
The name of the serializer, by default, is the name of the model followed by Serializer, as is the standard for ActiveModelSerializers. It's possible to just pass a custom serializer class though. As for the serializer itself, it's a standard serializer, with the gotcha that you need to include :id for the SimpleCrud examples to work.
class AuthorSerializer < ActiveModel::Serializer
attributes :email, :first_name, :last_name, :institution, :role, :id
end
Shared examples
While optional, using the included shared examples saves you from writing the standard test cases for the methods. You can even use them if you didn't use simple_crud_for, as a set of basic tests. To include them, just add require 'simple_crud/rspec' to your rails_helper.rb file and add the lines you need to your *_spec.rb files:
require 'rails_helper'
describe V1::Backoffice::AuthorsController do
include_examples 'simple crud for update'
include_examples 'simple crud for show'
include_examples 'simple crud for create'
include_examples 'simple crud for index'
include_examples 'simple crud for destroy'
end
It's not needed to specify paginate: true and such, since the shared examples will use the configuration that was originally passed to simple_crud_for
Contributing
- Fork it
- Run
bundle install && bundle exec appraisal generateonce, to install dependencies and generate the per-Rails-version gemfiles (gemfiles/rails_*.gemfile) used for testing - Run
bundle exec overcommit --installonce, to enable the pre-push hook (runs RuboCop and the full spec suite automatically on everygit push) - Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Run RuboCop lint (
bundle exec rubocop lib spec --format simple) - Run rspec tests (
BUNDLE_GEMFILE=gemfiles/rails_8.1.gemfile bundle exec rspec) - Push your branch (
git push origin my-new-feature). The pre-push hook re-verifies both automatically - Create a new Pull Request to
mainbranch
Releases
📢 See what's changed in a recent version
About
The current maintainer of this gem is:
This project was developed by:
Originally at Wolox
License
simple-crud is available under the MIT license.
Copyright (c) 2017 Wolox
Copyright (c) 2026 Ignacio Coluccio
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.