コントローラー
Ruby on Rails
アクション・params・before_action・レスポンス
コントローラーの基本
アクション・params・strong parameters・レスポンス
class PostsController < ApplicationController
before_action :authenticate_user!
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authorize_post!, only: [:edit, :update, :destroy]
def index
@posts = Post.published.recent
.includes(:user, :tags)
.page(params[:page]).per(params[:per] || 20)
respond_to do |format|
format.html
format.json { render json: @posts }
end
end
def show
@comment = @post.comments.build # フォーム用
end
def new
@post = current_user.posts.build
end
def create
@post = current_user.posts.build(post_params)
if @post.save
redirect_to @post, notice: '投稿しました'
else
render :new, status: :unprocessable_entity
end
end
def update
if @post.update(post_params)
redirect_to @post, notice: '更新しました'
else
render :edit, status: :unprocessable_entity
end
end
def destroy
@post.destroy!
redirect_to posts_path, notice: '削除しました', status: :see_other
end
private
def set_post
@post = Post.find(params[:id])
end
# Strong Parameters
def post_params
params.require(:post).permit(:title, :body, :status, tag_ids: [])
end
def authorize_post!
redirect_to root_path, alert: '権限がありません' unless @post.user == current_user
end
endフィルターとコンサーン
before_action・ApplicationController・Concern
class ApplicationController < ActionController::Base
include Authenticatable
include Paginatable
# 例外ハンドリング
rescue_from ActiveRecord::RecordNotFound do |e|
respond_to do |format|
format.html { render 'errors/not_found', status: :not_found }
format.json { render json: { error: e.message }, status: :not_found }
end
end
rescue_from ActionPolicy::Unauthorized do
render json: { error: '権限がありません' }, status: :forbidden
end
private
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
def authenticate_user!
redirect_to login_path unless current_user
end
end
# Concern(共通処理の分離)
module Authenticatable
extend ActiveSupport::Concern
included do
helper_method :current_user, :logged_in?
end
def logged_in?
current_user.present?
end
def require_admin!
render json: { error: 'forbidden' }, status: :forbidden unless current_user&.admin?
end
endパラメーターとレスポンス
params・flash・redirect・render・ステータスコード
# params の操作
params[:id] # URL パラメーター
params[:user][:name] # ネストしたパラメーター
params.require(:user).permit(:name, :email) # Strong Parameters
params.permit! # 全許可(非推奨)
# Strong Parameters の詳細
def user_params
params.require(:user).permit(
:name, :email, :password,
:avatar, # ファイルアップロード
preferences: [:theme, :lang], # ネストしたハッシュ
role_ids: [], # 配列
address_attributes: [:street, :city, :_destroy] # nested attributes
)
end
# レスポンス
render :show # ビューを描画
render 'posts/show'
render template: 'posts/show'
render partial: 'form', locals: { post: @post }
render json: @post
render json: @post, status: :created
render json: { error: 'Not found' }, status: :not_found
render nothing: true, status: :no_content
head :ok # ボディなし
head :not_found
# redirect
redirect_to @post
redirect_to posts_path
redirect_to posts_path, notice: '作成しました'
redirect_to posts_path, alert: 'エラーが発生しました'
redirect_back fallback_location: root_path
redirect_to @post, status: :see_other # POST→GETのリダイレクト(303)
# flash
flash[:notice] = '作成しました'
flash[:alert] = 'エラーが発生しました'
flash.now[:notice] = '現在のリクエストのみ' # redirect しない場合
# HTTPステータスコード(シンボルで指定可)
# :ok(200) :created(201) :no_content(204)
# :not_modified(304) :see_other(303)
# :bad_request(400) :unauthorized(401) :forbidden(403) :not_found(404)
# :unprocessable_entity(422) :too_many_requests(429)
# :internal_server_error(500)