Crudable Rails

crudable-rails is a Ruby on Rails gem that provides a set of helpers and modules to simplify the implementation of CRUD operations in Rails controllers.

It uses the following gems to enhance the functionality:

  • Pundit for authorization
  • Kaminari for pagination
  • FriendlyId for friendly finders
  • HasScope for filtering
  • Discard for soft deletion

Installation

Add this line to your application's Gemfile:

gem "crudable-rails"

And then execute:

$ bundle install

Or install it yourself as:

$ gem install crudable-rails

Usage

Controller Setup

To use crudable-rails in your controllers, call the crudable method.

Customizing CRUD Actions

You can override the default behavior of CRUD actions by defining the following methods in your controller:

  • before_authorize_create
  • after_authorize_create
  • on_successful_create
  • on_successful_create_render
  • on_failed_create_setup
  • on_failed_create_render
  • before_authorize_update
  • after_authorize_update
  • on_successful_update
  • on_successful_update_render
  • on_failed_update_setup
  • on_failed_update_render
  • on_successful_destroy_render
  • on_failed_destroy_render

For example:

class ProductsController < ApplicationController
  include Crudable::Rails::Controller

  crudable

  def on_successful_create
    # Custom behavior on successful create
  end

  def on_failed_create_render
    respond_to do |format|
      format.html { render :new, status: :unprocessable_entity }
    end
  end
end

By default, Turbo Streams are supported for create, update, and destroy actions. If Turbo Streams are not available, the gem will fallback to rendering HTML responses. If you require support for other formats, you can override the default behavior by defining the appropriate methods in your controller.

Required Private Methods

permitted_params

This method should return the permitted parameters for the resource as an array. It's required to be defined on all controllers.

Optional Private Methods

The following private methods are available for use in your controllers:

after_create_redirect_path

This method should return the path to redirect to after a successful create. By default this will redirect to the namespaced index of the resource being created.

after_create_notice

This method should return the notice to display after a successful create. By default this will return a success message via i18n.

after_update_redirect_path

This method should return the path to redirect to after a successful update. By default this will redirect to the namespaced show path of the resource being updated.

after_update_notice

This method should return the notice to display after a successful update. By default this will return a success message via i18n.

after_destroy_redirect_path

This method should return the path to redirect to after a successful destroy. By default this will redirect to the namespaced index of the resource being destroyed.

after_failed_destroy_redirect_path

This method should return the path to redirect to after a failed destroy. Default: after_destroy_redirect_path.

after_destroy_notice

This method should return the notice to display after a successful destroy. By default this will return a success message via i18n.

after_failed_destroy_alert

This method should return the alert to display after a failed destroy. By default this will return an error message via i18n.

discard?

This method should return a boolean value to determine if the resource should be discarded. If it returns false the resource will be destroyed. Default: false.

singleton?

This method should return a boolean value to determine if the resource is a singleton. Default: false.

use_parent_as_scope?

This method should return a boolean value to determine if the resource should be found using the nested parent. Default: true.

parent_id_param

When using nested routes, this determines which *_id param is treated as the parent id. If multiple *_id params are present (multi-level nesting), Crudable will default to the deepest/last *_id from the route path parameters.

finder_param

This method should return the parameter used to find the resource. Default: :id.

paginate_resource?

This method should return a boolean value to determine if the resource should be paginated. Default: true if Kaminari is available, otherwise false.

friendly_finders?

This method should return a boolean value to determine if the resource should be found using friendly finders.

Default: true when FriendlyId is available and the model responds to .friendly, otherwise false.

parent_friendly_finders?

When using nested routes (e.g. /:parent_id/:id), this method controls whether the parent should be found using FriendlyId.

Default: friendly_finders? (and additionally requires FriendlyId to be defined and the parent model to respond to .friendly).

skip_initialize_create?

This method should return a boolean value to determine if the resource should be initialized on create. Default: false.

authorize_with_pundit?

This method controls whether Pundit authorization should be performed. By default, it returns true when Pundit is defined. You can override this method to customize authorization behavior based on feature flags, user roles, or other conditions.

For example:

class ProductsController < ApplicationController
  crudable

  private

  def authorize_with_pundit?
    super && current_user.present? && feature_enabled?(:authorization)
  end
end

(create|update)_params

These methods should return the permitted parameters for the resource as an array. They are optional and can be defined if create and update methods need different parameters allowed.

Overriding authorizable_resource with a Namespace

The authorizable_resource method can be overridden to customize the resource authorization logic, especially when dealing with namespaced resources. This method should return the resource that needs to be authorized.

For example, if you have a namespaced controller:

module Admin
  class ProductsController < ApplicationController
    crudable

    private

    def authorizable_resource
      [:admin, @product]
    end
  end
end

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/your-username/crudable-rails. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.