LoginSignup
0
0

More than 3 years have passed since last update.

【Rails】コントローラーの処理をモデル内のクラスメソッドとして記載する。

Posted at

テーマ

コントローラー内に処理を記載していき、コードが冗長になったり、同じ処理を様々なアクションで使用する場合、一つのメソッドとしてモデル内で定義することがあると思います。
簡単なやり方と、その際にちょこっとだけつまづいた点をまとめています。

バージョン

ruby 2.5.7
Rails 5.2.4.4

やり方

shops_controller.rb
def members

 @table_customers = 2
 @tables = 3

 @all_customers =  @table_customers * @tables
 Shop.update(members:@all_customers)
#店内の総客数を計算するアクション
end

上記のコードでは店内の客数を計算するアクションになります。
(簡略化のために今回は1つのテーブルの客数を2人、テーブル数を3卓と定義しています。)

このアクションをモデル内に定義する場合を順を追って解説します。

shops_controller.rb
def members

 @table_customers = 2
 @tables = 3

 Shop.count_members(@table_customers,@tables)

end

コントローラーの記述

shop.rb
def self.count_members(table_customers,tables) 

  @all_customers =  @table_customers * @tables
  Shop.update(members:@all_customers)

end

モデルの記述

このままではエラーが発生しますが、解消方法はのちに記載します

・コントローラー側の記載
Shop.count_members(@table_customers,@tables)
Shop = メソッドを定義したモデル名
count_members = メソッド名(モデル内に記載してあるもの)
(@table_customers,@tables) = 処理する際に渡す変数

それぞれの記述を簡単に説明するとこのようになります。

・モデル側の記述
def = メソッドを定義
self = クラスメソッドを使用する際に記述(インスタンスメソッドの場合は不要)
count_members = メソッド名
(table_customers,tables) = コントローラーで受け取った値を変数としてそれぞれ再定義(今回の場合は、table_customers = 2, tables = 3 になる)

インスタンスメソッドとクラスメソッドの違いについては別記事を参照して見てください。今回はクラスメソッドを使用しています。

注意ポイント①

前述した通り、単純に処理内容をコピペした上記のコードでは想定した処理が行われずエラーが発生します。
その理由はモデル内で変数を再定義していることためです。

上記のコードでは、コントローラーで定義した@table_customers,@tablesの値をモデルに渡し、table_customers,tablesとして再定義していますが、モデルメソッド内で@table_customers,@tablesが使われており、そのような変数は定義されていないと言うことでエラーが発生します。

コントローラーで定義した変数は、モデルの処理では使えないと言う感じで覚えれば問題ないかと思います。

そのため、エラーを解消するには、、、

shop.rb
def self.count_members(table_customers,tables) 

  all_customers =  table_customers * tables #2つの変数の@を削除
  Shop.update(members:all_customers)

end

モデル内の@table_customers,@talesの@を削除することで正常に動作します。
(all_customersはメソッド内で新たに定義される変数なので@を削除しなくても動作自体は問題ありませんが、消去した方がベターです)

注意ポイント②

また、モデル内で定義した変数をメソッド外の処理や、view内で使用したい場合は注意が必要です。
コントローラーで定義した変数がモデル内で使用できないのと同様に、モデル内で定義した変数もモデル外では使用することができません。

クラスメソッド内で定義した変数をview等で使用したい場合は戻り値としてコントローラーに返す必要があります

仮にall_customersを戻り値として返したい場合

shop.rb
def self.count_members(table_customers,tables) 

  all_customers =  table_customers * tables #2つの変数の@を削除
  Shop.update(members:all_customers)

  return all_customers #returnメソッドで戻り値を指定

end
shops_controller.rb
def members

 @table_customers = 2
 @tables = 3

 @all_customers = Shop.count_members(@table_customers,@tables)
 #戻り値を格納するための変数を定義

end

モデル内で戻り値の指定、コントローラー内で変数の定義を行うことで、モデル内で扱った値をモデル外でも使用できます。また、カンマで区切ることで、複数の戻り値を取得することも可能です。

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