

例えばですが、以下のように  
アクションごとに変数名を変更しないのはなぜでしょうか？

@a,@b,@c,@dのところがおなじ@messageという変数を使う  
メリットについて教えて下さい。

[code]

    class MessagesController < ApplicationController
      def index
        @a= Message.all
      end
    
      def show
        @b = Message.find(params[:id]) 
      end
    
      def new
        @c = Message.new
      end
    
      def create
        @d = Message.new(message_params)
        
        if @d.save
          flash[:success] = 'Messageが投稿されました'
          redirect_to @d
        else
          flash.now[:danger] = 'Messageが投稿されませんでした'
          render :new
        end
      end
    
      def edit
      end
    
      def update
      end
    
      def destroy
      end
    
      private
    
      def message_params
        params.require(:message).permit(:content)
      end
    end
    
[/code]


CC BY-SA 4.0
2021-01-19T08:39:56.263
73406
2021-02-14T08:51:12.450
34234
question
ruby-on-rails ruby
Ruby on Rails アクションごとの変数名が同じ理由について


自由な変数名を使って良いです。

チーム開発をする場合はMessageクラスの変数名に別の名前をつけると他に意味があるか考えてしまったりするので中身を説明する変数名をつけることが良い習慣とされています

[code]

    # 悪い例: 犬のクラスなのに猫？
    @cat = Dog.find(params[:id])
    
[/code]

また今回例示頂いたような短い変数名は小さな関数の中では読み間違うことはほぼないため、利用して良いと思います(RailsだとViewで利用するので見かけよりでかかったりしますが）

[code]

    # Messageのインスタンス変数なので頭文字のm
    def show
      @m = Message.find(...)
    end
    
[/code]

なぜ`@message`を使うかを書いてみます。

Railsは規約に従うことコード量を少なくシンプルな記述で書けます。ルールに沿って書くことでコードを書く際に考えることが少なくできるわけです。つまりMessageモデルを扱うコントローラやビューでは`@message`や`@messages`の変数名とすることで考えることが減ります。プログラムを書くときに変数名を何とするか迷うことはとても多いので、パターンが決まってると時間短縮になり、あとあと自分で読む場合や他人が読む場合も変に疑うことがなくなります。

思いついたままに書きましたが参考になれば幸いです

* * *

補足ですがコレクションを扱う `index` アクションでは一般的に複数形の @messages になります。

[code]

    def index
      @messages = Message.all
    end
    
[/code]


CC BY-SA 4.0
2021-01-19T16:06:06.240
73418
2021-01-21T15:40:22.657
2021-01-21T15:40:22.657
298
298
73406
answer


各actionで変数名を揃えている理由ですが、理由の1つとして各アクション間でviewテンプレートの共有が行われるからだと思います。

例えばメッセージの表示をするテンプレートは`show`以外にも`create`や`edit`が成功した後に使われたりしますし、メッセージの編集フォームは`create`、`edit`で使われます。  
ここで、表示対象となるメッセージの変数がバラバラだと困ったことになります。  
ということで、このような処理がある場合はaction間で変数を統一しておくことがあります。


CC BY-SA 4.0
2021-01-20T10:22:45.470
73441
2021-01-20T10:22:45.470
42137
73406
answer


@message を使う理由は、その方が分かりやすいし効率が良いからです。  
結果的にプログラミングがとても楽になります。

@message という名前ならこの変数で何を扱っているか分かりやすいですし、異なるアクションで同じ @message
を使えば処理を共通化しやすくなります。

このMessageに関する処理をScaffoldを使って生成するとわかりやすいのではないかと思います。

[code]

    $> rails g scaffold message body:text
    
[/code]

MessagesController はこんな感じになると思います（Ralsのバージョンにより若干の差異があります）。

[code]

    class MessagesController < ApplicationController
      before_action :set_message, only: [:show, :edit, :update, :destroy]
    
      # GET /messages
      def index
        @messages = Message.all
      end
    
      # GET /messages/1
      def show
      end
    
      # GET /messages/new
      def new
        @message = Message.new
      end
    
      # GET /messages/1/edit
      def edit
      end
    
      # POST /messages
      def create
        @message = Message.new(message_params)
    
        if @message.save
          redirect_to @message, notice: 'Message was successfully created.'
        else
          render :new
        end
      end
    
      # PATCH/PUT /messages/1
      def update
        if @message.update(message_params)
          redirect_to @message, notice: 'Message was successfully updated.'
        else
          render :edit
        end
      end
    
      # DELETE /messages/1
      def destroy
        @message.destroy
        redirect_to messages_url, notice: 'Message was successfully destroyed.'
      end
    
      private
        # Use callbacks to share common setup or constraints between actions.
        def set_message
          @message = Message.find(params[:id])
        end
    
        # Only allow a trusted parameter "white list" through.
        def message_params
          params.require(:message).permit(:body)
        end
    end
    
[/code]

このコントローラを見て分かるのは、同じ @message を使うことでメッセージをIDを元に取得する処理を `set_message`
という形で共通化できることです。  
アクションごとに処理は独立しているので、@message の値がアクション間で共有されることはありませんが、処理を共通化できるのは大きなメリットです。

この共通化はコントローラだけでなく、ビューでも行われます。  
newアクションとeditアクションではそれぞれメッセージの新規作成と更新を行うためのフォームを表示しますが、これを共通化することができます。  
`_form.html.erb` というファイルがそれです。  
このフォームは当然ながらアクションから渡された @messageの内容を登録・更新するためのもので、`new.html.erb` や
`edit.html.erb` から呼び出されるようになっています。  
この場合も異なる変数名を使うより、同じ変数名を使った方がスムーズに共通部品である `_form.html.erb`を利用できて便利です。

Scaffoldはあくまで基本的な処理を自動生成してくれるだけなんですが、このメッセージ機能を拡張していくとその後共通部品を作ることは増えてきて、同じ変数名を使うメリットはどんどん大きくなってきます。

こう言った理由があるので、「敢えて異なる変数をアクションごとに使う必要がない」んですね。

まとめると、

  * 変数名は扱うモノが何なのか見てすぐわかるもので命名した方がいい（Rubyだけでなくプログラミング全般に言われること）
  * 同じ変数名を使えば、共通部品を作った場合も同じ変数を使えるので便利（これもプログラミング全般に言われること）
  * Railsのコントローラに関しては割とに通った構造になりやすいので、Railsの流儀に従った方がコードを読む人にも意味が伝わりやすい。言語に関わらずプログラムは分かりやすい方がいいので、敢えて異なる構造にすると分かりにくくなり、不親切になってしまう。

という理由です。すでに回答済みのお二方とほぼ同じことを言っているだけなのですが、うまく伝わるでしょうか。


CC BY-SA 4.0
2021-01-21T14:33:39.533
73475
2021-01-21T14:33:39.533
43354
73406
answer


Rails は、リクエストごとに Controller を new しています。

参考:
<https://github.com/rails/rails/blob/130c128eae233bf71231c73b9c3c3b3f3ede918b/actionpack/lib/action_controller/metal.rb#L254>

なので、毎回呼ばれる controller instance
は別ものなので、そのインスタンス変数がメソッド(リクエスト)を超えて被っていても、問題になることはありません。

結果、インスタンス変数はリクエスト単位でユニークに人間に分かりやすいものであれば良く、そうすると必然、 CRUD
の中で利用される変数名は似通ってきたりします。


CC BY-SA 4.0
2021-02-14T08:44:40.933
73987
2021-02-14T08:51:12.450
2021-02-14T08:51:12.450
754
754
73406
answer