【Rails】CRUDを一発で生成するconcern

公開日:2019-04-15
最終更新:2019-04-15

概要

過去CRUD APIを爆速で量産するために作ったcrudable concernを備忘録代わりにメモ。

コード

module Crudable  
  extend ActiveSupport::Concern  
  included do  
    rescue_from ActiveRecord::RecordNotUnique do  
      render json: { error: "#{model.model_name.human}がすでに存在しています。" }, status: :conflict  
    end  

    rescue_from ActiveRecord::RecordNotFound do  
      render json: { error: "#{model.model_name.human}が存在しません。" }, status: :not_found  
    end  

    rescue_from ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved do |e|  
      render_error e.record  
    end  
  end  

  class_methods do  
    define_method :index do |**options|  
      define_method(:index) { render options.merge(json: model.all) }  
    end  

    define_method :show do |**options|  
      define_method(:show) { render options.merge(json: resource) }  
    end  

    define_method :create do |**options|  
      define_method(:create) do  
        render options.merge(json: model.create!(permitted_params(options)), status: :created)  
      end  
    end  

    define_method :update do |**options|  
      define_method(:update) do  
        resource.update!(permitted_params(options))  
        render options.merge(json: resource)  
      end  
    end  

    define_method :destroy do |**options|  
      define_method(:destroy) do  
        resource.destroy!  
        render options.merge(json: resource)  
      end  
    end  
  end  

  private  

  def model  
    @model ||= controller_name.classify.constantize  
  end  

  def resource  
    @resource ||= model.find(params[:id])  
  end  

  def nested_attributes(model)  
    (model.attribute_names - %w[deleted_at updated_at created_at] + [:_destroy]).push(  
      model.nested_attributes_options.map do |options|  
        { options[0] => nested_attributes(options[0].to_s.classify.constantize) }  
      end  
    )  
  end  

  def format_keys(array, current_model)  
    current_model.nested_attributes_options.map do |options|  
      child_model = options[0]  
      next unless array[child_model]  
      array[child_model] = format_keys(array[child_model], child_model.to_s.classify.constantize)  
      array["#{child_model}_attributes".to_sym] = array.delete child_model  
    end  
    array  
  end  

  def permitted_params(options)  
    options[:params]&.call(params) ||  
      params.require(model.model_name.i18n_key).permit(nested_attributes(model)).tap do |params|  
        format_keys(params, model)  
      end.permit!  
  end  
end  

使用例

class UsersController < ApplicationController  
  include Crudable  

  index fields: %i[name email], include: %w[user_role user_profile]  
  show  
  create params: ->(params) { params.permit(:name, :email, :password) }  
  update  
  destroy  
end  
記事が少しでもいいなと思ったらクラップを送ってみよう!
0
+1
@zd2JVKCd8JyW6MUgの技術ブログ

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする