stiig
5/18/2017 - 10:26 AM

Ruby on Rails default controller + pundit

Ruby on Rails default controller + pundit

module DefaultController
  extend ActiveSupport::Concern

  included do
    before_action :load_collection,      only: [:index]
    before_action :generate_model,       only: [:new]
    before_action :create_model,         only: [:create]
    before_action :load_model,           only: %i[edit update show destroy]
    before_action :alias_variable_model, only: %i[index new create show edit update destroy]
  end

  def index; end

  def new; end

  def edit; end

  def show; end

  def create
    if @model.save
      flash_message :success, t('.success')
      before_redirect_create if respond_to?(:before_redirect_create)
      redirect_to redirect_options[:create]
    else
      render :new
    end
  end

  def update
    if @model.update(model_params)
      flash_message :success, t('.success')
      before_redirect_update if respond_to?(:before_redirect_update)
      redirect_to redirect_options[:update]
    else
      render :edit
    end
  end

  def destroy
    if @model.destroy
      flash_message :success, t('.success')
      before_redirect_destroy if respond_to?(:before_redirect_destroy)
      redirect_to redirect_options[:destroy]
    else
      render :edit
    end
  end

  private

  def load_collection
    @collection = respond_to?(:collection) ? collection : class_model.page(params[:page])
  end

  def generate_model
    @model = class_model.new
  end

  def create_model
    model_params = respond_to?(:model_params) ? self.model_params : nil
    @model = class_model.new(model_params)
  end

  def load_model
    @model = class_model.find(params[:id])
  end

  def class_model
    raise 'Not implemented'
  end

  def model_params
    raise 'Not implemented'
  end

  def redirect_options
    raise 'Not implemented'
  end

  def filter_params
    params.require(:filter).permit(filter_fields)
  end

  def alias_variable_model
    # Pundit
    # autopolicy @collection || @model
    new_model_name = @collection ? @collection.model_name.collection : @model.model_name.element
    instance_variable_set("@#{new_model_name}", @collection || @model)
  end
  
  ### Pundit ###

  # def autopolicy(record)
  #   authorize module_name ? [module_name, record] : record
  # end

  # def module_name
  #   name = self.class.parent.name.underscore
  #   name == 'object' ? nil : name.to_sym
  # end
end


Example:

class CompaniesController < ApplicationController
  include DefaultController
  
  def class_model
    Company
  end

  def load_model
    @model = class_model.find(params[:id])
  end

  def redirect_options
    {
      create:  company_root_url(subdomain: @company.subdomain),
      update:  url_for(:companies),
      destroy: url_for(:companies)
    }
  end

  def before_redirect_create
    current_user.create_role :manager, @company
  end

  def model_params
    params.require(:company).permit(:name, :subdomain)
  end
end