🔥

【脱初心者】RubyとRailsの曖昧なメソッドを理解する

2023/12/19に公開2

はじめに

近頃冷え込んできましたね、@chiba_dです。
8月から新卒インターンとして参加している私も、業務に関わる中で学びが多い状態を継続できています!

COUNTERWORKSではSHOPCOUNTERというサービスを運営しています。
https://shopcounter.jp/

SHOPCOUNTERではフロントにNext.js、バックエンドにRailsを使用しています。

研修の中でプロダクションのコードに触れて、多くの学びや気づきがありました。

そこでRailsチュートリアル1周レベルの私が、入社後に新しく学んだ・理解したRuby・Railsの記述について備忘録的にまとめます。

記事の内容

この記事では私が初学者の状態から業務に関わる中で、RubyとRuby on Railsの曖昧だと感じて、調べ直した記法を順番に紹介します!

必要に応じて

  • 何が違うか(what)
  • どう使い分けるか(how)

を記載します。

この記事で勉強して業務レベルのコードを読めるようになりましょう!

対象読者

  • Ruby・Railsに詳しくなりたい人
  • Railsチュートリアル1周した人

全体

member:(名前付き引数)、:member(シンボル)

項目 内容
キーワード引数 member: 引数を渡す際にkeyを指定して渡す
シンボル :member 値を代入するための変更不可能な文字列の変数
  • what(違い)
    :が前と後ろのどちらについているか
  • how(使い分け)
    キーワード引数はkey,シンボルはvalueとして扱う

ハッシュ、配列

項目 内容
ハッシュ (連想配列) {"name" => "Taro", "internet_name" => "漆黒の太郎"} keyとvalueが一意に対応するオブジェクト
配列 ["Sato", "Yoshida", "Suzuki"] valueのみを複数持つオブジェクト
  • what(違い)
    keyが存在するか
  • how(使い分け)
    レスポンスの設計などkeyが必要な処理ではハッシュ、単純なループ処理では配列

ハッシュではシンボルと文字列の両方をkeyとして定義できます。
valueを読み込む際のkeyの指定には、定義した形式(文字列なら)で記述が必要です。

ハッシュを配列に格納すること、ハッシュにハッシュをvalueとして定義することもできます。

https://qiita.com/kentarok/items/5d38c3f7df37a7396ef9

API Routeにおける単数、複数

項目 内容
単数 PATCH ~/members/1 update,deleteなどの一つのレコードにのみ作用する場合
複数 POST ~/members index,createなどの全て・複数のレコードに作用する場合
  • what(違い)
    APIが実行する処理の対象が単数か複数かで記述を変える
  • how(使い分け)
    同上

:: と . と _

項目 内容
:: Api::V1::User クラス、定数呼び出しで用いる
. User.all メソッド呼び出しで用いる
_ _ 任意の一文字に該当するワイルドカード,数値の区切りに使える
  • what(違い)
    クラス(定数)の呼び出しとメソッドの呼び出し
  • how(使い分け)  
    省略

@@と@とdef +@

項目 内容
@@ @@user クラス変数
@ @user インスタンス変数
def +@ def +@, +: taro 単項演算子を定義する表記
  • what(違い)
    変数のスコープが異なる
  • how(使い分け)
    省略

attr, params

項目 内容
attr attr_accessor :name コントローラー内でオブジェクトの属性を定義する
params https://~/user/1 , params[:id] クエリパラメータとして送られてくる値を取得するメソッド
  • what(違い)
    attrはオブジェクトの属性を定義する、paramsはURLに含まれる値を取得するメソッド
  • how(使い分け)
    省略

paramsはルーティングにおいても/user/:idのように指定して、どこがparamsであるかを教える必要があります

https://bryankawa.hatenablog.com/entry/2017/01/28/150537

class, module, helper

項目 内容
class class User インスタンスが作れる、メソッドもまとめた概念
module module User インスタンスが作れない、メソッドのみをまとめた概念
helper module User ビューファイルで用いることが可能なモジュール
  • what(違い)
    インスタンスが作れるかどうか、ビューファイルで用いるかどうかが異なる
  • how(使い分け)
    同上

transaction {}, hash {}

項目 内容
transaction {} ActiveRecord::Base.transaction do end トランザクションを記述する、処理途中のエラーが発生したらロールバック
hash {} hash do end ハッシュの各属性を検証するときに使う
  • what(違い)
    トランザクションを書くか、ハッシュの検証を書くか
  • how(使い分け)
    同上

https://qiita.com/mtoyopet/items/67d1cff3df00aa651cb7

include, include?

項目 内容
include include Greet モジュールの読み込み
include? "Yamada".include?("Yama") 指定する文字列を含むかどうか
  • what(違い)
    クラスとモジュールのどちらを読み込むか
  • how(使い分け)
    同上

&と&.とdef xxx(&aaa)とxxx(&bbb)

項目 内容
論理積 & 通常の論理積演算子
ボッチ演算子 &. インスタンスがnilでなければメソッドを実行し、nilならばnilを返す記述
ブロック引数 def xxx(&aaa) メソッドを定義する際にブロックを渡すことを記述する
Procを用いるメソッド呼び出し xxx(&bbb) Procオブジェクトをブロックとして渡してメソッドを呼び出す
  • what(違い)
    演算子、メソッド定義、メソッド呼び出しが異なる
  • how(使い分け)
    省略

https://qiita.com/kidach1/items/15cfee9ec66804c3afd2

alias,alias_method,scope

項目 内容
alias alias new_name old_name グローバル変数に別名を付ける
alias_method alias_method :new_method :old_method インスタンスメソッドに別名を付ける
scope scope :current, -> { where(login_current: true) } 別名で呼び出せるように条件式を定義する
  • what(違い)
    対象が変数かインスタンスメソッドか条件式かで異なる
  • how(使い分け)
    同上

https://docs.ruby-lang.org/ja/latest/method/Module/i/alias_method.html

->と=>

項目 内容
-> num = -> (a){a*a} lambda記法
=> {"name" => "Taro"} ハッシュのリテラル
  • what(違い)
    無名関数の定義かハッシュのkey-value定義か
  • how(使い分け)
    省略

メソッド

find, find_by, find_by!

項目 内容
find User.find(1) 該当するidのレコードを取得するメソッド
find_by User.find_by(name: "Taro") 指定した属性・値を持つ初めに見つかったレコードを取得するメソッド、取得できなかった際nilを返す
find_by! User.find_by!(name: "Taro") find_byと同じメソッドだが、取得できなかった際エラーを返す
  • what(違い)
    idでレコードを取得するかどうか、取得できなかった際の戻り値で異なる
  • how(使い分け)
    同上

each, find_each

項目 内容
each [1,2,3].each do ループ処理で要素を取り出す
find_each User.all.find_each do ループ処理で要素を取り出す、大規模なデータの処理で効率的なSQLを作成する
  • what(違い)
    全レコードをメモリに読み込むか、データベースクエリの実行時間
  • how(使い分け)
    ActiveRecord関連の1000件を超えるようなデータ処理ではfind_eachを用いる方がよい、それ以外ではeachでも問題ない

https://techracho.bpsinc.jp/hachi8833/2023_04_11/129118

モデル

.idとids

項目 内容
.id user.id オブジェクトのもつidを参照する
ids User.ids 主キーのカラムを取り出す(SQL)
  • what(違い)
    オブジェクトのidを参照するか主キーのカラムを取り出すか
  • how(使い分け)
    同上

through, source

項目 内容
through has_many :users, through: :favorites 中間モデルを通して関連モデルを参照する
source has_many :favorite_posts, through: :favorites, source: :posts 存在しない関連付けに対して、throughを通して実際に参照する関連モデル
  • what(違い)
    throughは中間モデルを記載する、sourceは実際に参照する関連モデルを記載する
  • how(使い分け)
    同時に使うため省略

belongs_to, has_one

項目 内容
belongs_to belongs_to :favorite 自らが外部キーとして相手モデルの主キーをカラムとして持つ
has_one has_one :user belongs_toの説明の相手モデル側、外部キーをカラムとして持たない
  • what(違い)
    外部キーが定義されたカラムを持つか
  • how(使い分け)
    外部キーをカラムとして持つ側かどうかで変える

テスト関連(RSpec,FactoryBot)

let, let!

項目 内容
let let(:user) {User.new(name: "Taro", age: "18")} 遅延評価で値を定義する
let! let!(:user) {User.new(name: "Taro", age: "18")} 即時評価で値を定義する
  • what(違い)
    参照されたタイミングで値が決定するかどうか
  • how(使い分け)
    処理の途中で値が変わる可能性がある場合即時評価を使う

create, build

項目 内容
create FactoryBot.create(:user) FactoryをDB上に作成する
build FactoryBot.build(:user) Factoryをメモリ上に作成する
  • what(違い)
    FactoryをDB上に持つか、メモリ上に持つか
  • how(使い分け)
    ActiveRecordが関連する場合はcreateを使う

https://qiita.com/takutotacos/items/4a8bd25ccb42141bf67c

subject, describe, context, it

項目 内容
subject subject { math.sum } is_expectedで評価される式を定義する
describe describe '足し算' do 実行するテストの大枠を記載する
context context '整数の時' 条件分岐・状況を記載する
it it '1+1 = 2であること' do テストの詳細を記述する
  • what(違い)
    記載内容、describe > context > itの順で外側から記載する
  • how(使い分け)
    同上

delete, soft_delete

項目 内容
delete user.delete レコードの物理削除を行う
soft_delete user.soft_delete レコードの論理削除を行う
  • what(違い)
    レコードを実際に削除するか
  • how(使い分け)
    データを削除後も残しておきたいかどうか

member, collection

項目 内容
member resources :users do member do get 'account' end end ルーティングにおいてresource とmemberの間に:idを持つ
collection resources :users do collection do get 'account' end end ルーティングにおいてresource とcollectionの間に:idを持たない
  • what(違い)
    idを受け取るかどうか
  • how(使い分け)  
    コントローラーでparams[:id]を用いるかどうか

おわりに

いかがだったでしょうか!
この記事では私の経験をもとにRubyとRuby on Railsの初心者が曖昧になりがちな記述について解説しました。
この記事が初学者の手助けになれば幸いです。

今後も学習途中の不明点は理解した後に備忘録として残しておきたいと思います。

We are hiring !!

COUNTERWORKS では一緒に働く仲間を絶賛募集中です。
今後の更なる成長のためには圧倒的に仲間が不足しています。皆さまのご応募お待ちしております!

https://counterworks.co.jp/recruit/?utm_source=zenn&utm_medium=referral&utm_campaign=advent-calendar-2023&utm_content=19

参考

https://railsguides.jp/v5.2/active_record_querying.html
https://docs.ruby-lang.org/ja/latest/doc/symref.html
https://qiita.com/kentarok/items/5d38c3f7df37a7396ef9
https://qiita.com/kidach1/items/15cfee9ec66804c3afd2
https://qiita.com/takutotacos/items/4a8bd25ccb42141bf67c
https://techracho.bpsinc.jp/hachi8833/2023_04_11/129118
https://docs.ruby-lang.org/ja/latest/method/Module/i/alias_method.html

COUNTERWORKS テックブログ

Discussion

yasulabyasulab

Railsチュートリアル/Railsガイドについて言及していただきありがとうございます! 😻✨

細かな点で恐縮ですが以下の「単数」の部分については members/1 になるかなと思いました! ✅

API Routeにおける単数、複数

- member/1
+ members/1

参考: CRUD、verb、アクション - Railsガイド

ご参考になれば幸いです...!! 🙏✨

Chiba_dChiba_d

ご指摘頂きとても助かります!ありがとうございます!🙏
指摘事項に関して仰る通り私の誤りでした。

member/1 -> members/1

誤った記述でしたので、上記の通り修正いたしました。(2023/12/19)

(RailsガイドとRailsチュートリアルを頻繁に読んでおります!重ねてお礼申し上げます✨)