LoginSignup
1
0

More than 1 year has passed since last update.

Rails初級者が一ヶ月研修を受けて得た学びをまとめた~Rails~

Last updated at Posted at 2022-09-03

この記事は「Rails初級者が一ヶ月研修を受けて得た学びをまとめた - Qiita」のRailsに関する項目を切り出した分割記事です
概要などについては親記事を参照してください。

Rubyの文法など基本的なこと

配列の種類

  • %i:シンボル配列。メソッド名、変数名などの配列を作るときに

Hashは省略記法が使える

pp pp puts printの使い分け

enumの挙動に注意

  • key,valueどちらを渡してもsaveは成功する

  • Rails5でenum定義したカラムの元の値を取得 - Qiita

  • DBにはvalueで保存される

    ActiveRecord上ではenumのkey名として保持して、DBに保存する時に数値で変換して保存してくれます

  • Task.status{ yet: 0, ongoing: 1, complete: 2 }のようになっていた場合、Task.ongoingTask.where(status: 'ongoing')と同じことが実行さる。

  • このようなカラムにnumericality: { only_integer: true }などのvalidationをつけるとkey名でsaveできなくなるので注意

  • 付与するvalidationもpresence: true程度で良い

    なので独自に追加するのは presence: true 程度で良いかと思います。
    記事とかだと inclusionを指定しているようなものもありますが、上記通りRails側で指定したenumのkey / value以外をしてしようとするとエラー発生してくれるのでinclusionも必要ありません。

  • この仕様がわかっておらず騒いでいる初心者のアホ→railsのenum型で沼

  • enumについてはここが参考になった 【Rails】5ステップでイケてる enum を作る(翻訳) - Qiita

Rails実装に関すること

Gemfile内でのgroup指定

現在アプリ側で利用されているDB設定を確認する

ユーザビリティー・インターフェイス

errorメッセージが日本語で出るようにi18nを適応させる

  • ユーザーフレンドリーなのでやっておこう

enumはi18nとgemで日本語化できる

created_at/updated_atのRailsが自動付与カラムはユーザー向けには使わない

  • 手動データ修正した際にずれる可能性が高い。
  • 日付けソートなどの機能を提供したい場合は専用の別カラムを用意した方が良い。

APIのパラメータは使い手に理解しやすく

  • Rails側でしかわからないことは含ませない=内部実装は隠す
  • 理解しやすいインターフェイスに
  • これま同じメンバーが実装するフロントでコールするAPIしか設計してこなかったため、この辺りの意識が足りていなかった
    • スマホアプリ開発チーム側で使われるAPIを設計していくことになるのでしっかり意識する必要がある

メソッド

controller内で利用する定数はprivate_constantつけとくとよい

  • あと、定数はアッパーケースで
  • 例えばtasks_controller内のメソッドで利用する定数の場合このように書いておくと良い
    class TasksController < ApplicationController
      ...
    
      SORTABLE_COLUMN = {
        name: 'task_name',
        detail: 'detail',
        limit: 'date_limit',
        status: 'status',
        priority: 'priority'
      }.freeze
    
      private_constant :SORTABLE_COLUMN
    
    
  • 他殻も参照できてしまうのでできるだけスコープは狭く
  • 定数定義の仕方は色々あるみたい

methodの説明などのコメントはYARD記法で

method名にsetget,hasは使わないようにする

  • factory_botに怒られる

動的にwhereをつけたい時はcompactを使うと良い

  • 例えばクエリパラメータにstatus=lowが含まれている場合だけTask.where(status: params[:status])を付与したい…
     # bad
     @tasks = params[:status] ? @tasks.where(status: params[:status]) : @tasks
    
     #good
     @tasks = @tasks.where({ status: params[:status] }.compact)
    
  • このようにhashで渡してやればcompactが省略してくれ、where句自体が実行されない
  • なお実際は@tasks.where({ status: Task.statuses[params[:status]] }.compact) として不正なリクエストパラメーターをクエリに渡さないようにしている

errorレンダリング関数名はHTTPステータスのシンボルで定義すると良い

controllerでのメソッド呼び出しの仕方

  • actionメソッドで利用するTaskのインスタンスの呼び出し方についてこのような定義をしていた

    • それぞれのcotrollerメソッドの前にbefore_action@taskにインスタンスを格納し、それをメソッド内で参照していた
       before_action: :task
       ....
    
       def update
         @task = 必要な処理
         @task.update
       end
    
       def destroy
         @task.destroy
       end
    
       def task
         @task = Task.find[params[id]]
       end
    
    
  • PRで提案された記法がこう

     # before_action: :task
    
    
     def update
       task.update
       ....
     end
    
     def destroy
       task.destroy
     end
    
     private 
    
     def task
       @task ||= Task.find(params[:id])
     end
    
    

point

  • ||= を使い、同一メソッド内で呼び出された場合は、DBへの再参照が起きなようにしている

  • privateメソッドでタスクインスタンスを定義し、メソッドを呼び出して関数内でも利用する。(railsっぽい書き方らしい)

    • before_actionでセットされたインスタンス変数を使うとactionコードだけ見たときにわかりづらいから
  • Q.

    getterメソッドで対応し、インスタンスに直接アクセスしない様にするのは何かアーキテクチャ的理由があるのでしょうか?

  • A.

    クラス内部でインスタンス変数を参照するのは全然構わないと思います!(人によっては getter メソッドに統一する人もいる)
    今回のでいうと、各アクションでは before_action で事前にセットされたインスタンス変数にアクセスしていますが、アクションのコードだけ見るとその前提が分かりづらいので、分かりやすい形にしておきたいって感じですかねー
    こういう時はこういう風に書くというのが大体決まっているので、そこから外れないように書くと他の人にも読みやすいコードになるかと思います!(こういう風というケースは、他の人のコードを読んで学習するのが一番👍)

redirect_toは引数の指定の仕方に注意

redirect_toは3xx以外のstatusを渡すと正常に動かない

  • redirect_toはリダイレクト先とHTTPstatusを渡すことができる

  • 「ここに任意のstatusを与えて使えますよ〜」と書いてある記事は多いが、実際は3xx以外渡すと動かなかった

  • 例えば201を渡すとこんな感じ

      ↳ app/controllers/tasks_controller.rb:41:in `create'
      Redirected to http://localhost:3000/tasks/new
      Completed 201 Created in 76ms (ActiveRecord: 48.7ms | Allocations: 12669)
      ## ↑ここでredirect処理自体は終わっている
    
      ## ↓ここからは?
      Started GET "/tasks" for ::1 at 2022-08-25 17:51:19 +0900
      Processing by TasksController#index as HTML
    
  • http://localhost:3000/tasks/new にリダイレクトされる処理が完了してしまっているが、GETが走っていない。

  • その代わり、直後に謎の力でroot_pathへのGETメソッドが走っている

  • specで同様のことをしてもこの挙動は起きないため、railsの何らかのおせっかいでroot_pathに飛ばしてくれている?

  • redirect_toの公式にも3xx以外だと動かないよ!としか書かれていない rails/redirecting.rb rails/rails

erb

deleteメソッドはlink_toではなくbutton_to

<% %><%= %>は別物

erbLintを入れてerbの整形を

Deviseで使われている認証フレームワークWarden

  • Wardenの使い方 まとめ - 猫Rails
  • 直接触ってはいないが、Deviseで実装したサインイン機能をrspecで呼び出す際に勉強した気がする。
  • 深追いはしない

migrationはbulkupdateで行うと良い

  • rubocopの Rails/BulkChangeTable: You can use change_table :tasks, bulk: true to combine alter queries.でも指摘される

  • 先輩も

    migrationファイルで実行されるSQLは1トランザクションで完結するべきと考えていて、それを半強制するこのルールは好きです。

    とおっしゃっており、ベターっぽい

      # bad
      def up 
        change_column ....
        change_column ....
      end
    
      # good
      def up 
        change_table(:tasks, bulk: true) do |t|
          t.index ...
          t.chage_default ...
        end
      end
    
  • 使い方はこちらを参照:change_table | Railsドキュメント

1
0
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
1
0