LoginSignup
13
11

More than 5 years have passed since last update.

Railsのcontroller,routesの書き方とについて考えてみた。

Posted at

初めに

こんな記事を読みました。

DHHはどのようにRailsのコントローラを書くのか
https://postd.cc/how-dhh-organizes-his-rails-controllers/

この記事の引用なのですがまとめると

「コントローラはデフォルトのCRUDアクションindex、show、new、edit、create、update、destroyのみを使うべき」

とDHHという人は考えているとのこと。

これについて記事の筆者は意見を言っていて気になる人は見に行ってほしいのですが

とりあえずcontrollerを細かく分けで基本的にcrudを書くようなやり方を実践してみました。

またコントローラーが増えることによって逆にわかりづらくなるのを防ぐために

userに関係するものは

users/***_controller.rb

みたいに保存しました。

実装

まず

rails new app
rails g model user name
rails g controller users

とします。

これでroutes.rbに

resources :users

とかけばusersにかんして

crudの設定が終わります。

userにstatusを付ける

次にuserにstatusカラムを追加してそこにactive,stopという属性をenumを使って実装します

rails g migration add_status_to_users

としてマイグレーションファイルに

add_column :users, :status, :integer, default: 0

とします。

またモデルファイルに

user.rb
enum status: { active: 0, stop: 1}

これを追加

これでuserを作成するとstatusがactiveのuserが作成できます。

ここでactive userとstop userの表示をusers_controllerで実装するのではなくほかにコントローラーを作って実装します。

この時に

rails g controller actives 

とするのではなく

rails g controller users::actives

としました。

これでcontrollers/users以下にactives_controller.rbが作成されます。

同じように

rails g controller users:stops

としました。

次にroutes.rbですが

resources :users do 
  resources :actives, only: [:index, :create]
  resources :stops,   only: [:index, :create]
end 

このようにするとcontrollers/以下のstops_controller.rbを探しに行ってしまします。

controllers/users/以下のファイルを探しに行ってくれるようにするために

resources :users do 
   scope module: :users do 
     resources :actives, only: [:index, :create]
     resources :stops,   only: [:index, :create]
   end 
end 

とすることでちゃんとcontrollers/users以下のファイルへのroutesを作成できました。

actives_controller.rb,stops_controller.rbの中身はこんな感じ

actives_controller.rb
class Users::ActivesController < ApplicationController

    def index
        @users = User.active 
    end 

    def create 
        user = User.find params[:user_id]
        user.active!
        redirect_to users_path
    end 
end

stops_controller.rb
class Users::StopsController < ApplicationController

    def index 
        @users = User.stop
    end 

    def create 
        user = User.find params[:user_id]
        user.stop!
        redirect_to users_path
    end 
end

実際に呼び出す際にネストさせたroutesのurlヘルパーの書き方は

users/index.html.erbに

<% @users.each do |user| %>
    <p><%= user.name %></p>
    <p><%= user.status %></p>
    <%= link_to "stop_user", user_stops_path(user), method: :post %>
    <%= link_to "active_user", user_actives_path(user), method: :post %>
<% end %>

みたいにすればOKです。

上の場合はstops#create,actives#createへのroutesですがネストさせた場合

params[:id]

ではなく

params[:user_id]

のように取得するようになります。

follow機能

followみたいな機能に関してもuserに関係するものなのでusers以下にcontroller.rbが作成されたほうが良いのかと思いました。

なので

rails g model follow user_id:integer follow_id:integer

同じデータが複数保存されないように

models/follow.rbに

    validate :already_follow

    def already_follow
        if Follow.exists?(user_id: user_id, follow_id: follow_id)
            errors.add(:user_id, "すでにフォローしています")
        end 
    end 

としました。

そして

rails g controller users::follows

follows_controller.rbに

class Users::FollowsController < ApplicationController

    def index 
        @follow_users = Follow.where(follow_id: session[:user_id]) 
    end 

    def create 
        if session[:user_id]
            follow = Follow.new(follow_id: session[:user_id], user_id: params[:user_id])
            follow.save 
            redirect_to users_path
        else 
            redirect_to users_path
        end 
    end 
end

とすればフォロー機能が作成できました。

結果

これでuserのstatusを変更したりuserをfollowしたりする機能をcontrollerごとに分けて作ってみました。

結果として

controllers/users以下のコントローラーはuserに関係するものだとすぐにわかるし

一つ一つのコントローラーの中身がかなりシンプルのなりました。

逆に普通に

rails g controller follows
rails g controller actives
rails g controller stops

みたいにしてコントローラーを細かく作っていくと逆に何が何だか分からなくなるかもしれないので

コントローラーにcrudしか書かないのであればネストさせるのは必須なのかなと思いました。

おわり:sunny:

13
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
11