0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】具体例を用いてクラスメソッドとインスタンスメソッドの違いを説明

Posted at

はじめに

こんにちは。アメリカ在住で独学でエンジニアを目指している taira です。
現在時差ぼけに苦しみながらも、少しずつですが勉強のリズムを取り戻しつつあり、本日からRailsチュートリアルの勉強を再開しました

そこで出てきたクラスメソッドとインスタンスメソッドの使いわけについて、まだ理解しきれていないところがあったので再度確認のために記事を書いております

コード内容

今回は具体的なコードを用いて説明を進めていきます。
以下のコードはRailsチュートリアルのコードを一部拝借させていただいております

class User < ApplicationRecord 
  
  
  

  # 渡された文字列のハッシュ値を返す
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
    BCrypt::Password.create(string, cost:cost)
  end

  # ランダムなトークンを返す
  def User.new_token
    SecureRandom.urlsafe_base64
  end

  # 永続セッションのためにユーザーをデータベースに記憶する
  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_digest, User.digest(remember_token))
  end
end

ここで、渡された文字列のハッシュ値を返すUser.digest(string)メソッドと、ランダムなトークンを返すUser.new_tokenはクラスメソッドとして扱われています。
一方、永続セッションのためにユーザーをデータベースに記憶するrememberメソッドはインスタンスメソッドです。

上記を見て「User.digestUser.new_tokenも、ユーザーごとにあることを踏まえるとインスタンスメソッドとして扱うのがもっとものように思えるのですが、なぜクラスメソッドとして定義しているのだろうと思いました」

それぞれの違い

これの解答としては、User.digestUser.new_tokenも「特定のユーザー自身とは関係がなく、ユーザーという概念一般に対して共通の処理であるため」クラスメソッドに定義しています。
ポイントは、これらのメソッドが「個別のユーザーインスタンスに紐付く情報を一切使っていない」点にあります。
それぞれのメソッドごとに見ていきましょう

1. User.digestの場合

def User.digest(string)
  cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
  BCrypt::Password.create(string, cost: cost)
end

このメソッドは、受け取った文字列を単にハッシュ化するだけであり、

  • どのユーザーの情報も必要としていません。
  • 個々のユーザーごとの状態に依存しません。

つまり、ユーザーAさんの情報があってもなくても、このメソッドは完全に独立して動作します。
ユーザーオブジェクトのインスタンス変数に一切アクセスせず、単純な「汎用のハッシュ生成機能」を提供しています。

そのため、「特定のユーザーのための処理」ではなく、「Userクラスに属する汎用的な機能」としてクラスメソッドにしています。

2. User.new_token (トークン生成)

こちらも同様に、

  • 乱数によって「新しいランダムなトークンを作る」だけです。
  • 特定のユーザーの情報や状態に依存していません。

つまり、ユーザーが存在しているかどうかとは無関係にトークンを生成できます。

rememberメソッド

一方で、rememberメソッド は「特定のユーザー(インスタンス)を対象にして」、そのユーザーが次回訪問したときにログインを継続させる仕組みを準備する役割を持っています。

具体的には、

  • トークンを生成して 自身(self)のインスタンス変数に保存 します。
  • さらにそのユーザーの情報を データベースに保存(update_attribute) します。

つまり、rememberメソッドは、各ユーザーの状態に依存しているので、インスタンスメソッドにする必要があります。

  • ユーザーAのトークンと、ユーザーBのトークンは異なるものが生成されます。
  • それぞれ異なるトークンを各ユーザーのデータベースに保存するため、「特定のユーザーの状態」を前提にしています。

このように、「特定のユーザー」を意識している場合はインスタンスメソッドになります。

まとめ

  • クラスメソッド: クラス全体に共通する、インスタンス(今回はユーザー)に依存しない処理
  • インスタンスメソッド: 特定のインスタンスごとの処理や状態を扱う

勉強では学んだものの、実際のコードをいざ見てみると使い分けって難しいなと感じました。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?