#テーマ
コントローラー内に処理を記載していき、コードが冗長になったり、同じ処理を様々なアクションで使用する場合、一つのメソッドとしてモデル内で定義することがあると思います。
簡単なやり方と、その際にちょこっとだけつまづいた点をまとめています。
#バージョン
ruby 2.5.7
Rails 5.2.4.4
#やり方
def members
@table_customers = 2
@tables = 3
@all_customers = @table_customers * @tables
Shop.update(members:@all_customers)
#店内の総客数を計算するアクション
end
上記のコードでは店内の客数を計算するアクションになります。
(簡略化のために今回は1つのテーブルの客数を2人、テーブル数を3卓と定義しています。)
このアクションをモデル内に定義する場合を順を追って解説します。
def members
@table_customers = 2
@tables = 3
Shop.count_members(@table_customers,@tables)
end
コントローラーの記述
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が使われており、そのような変数は定義されていないと言うことでエラーが発生します。
コントローラーで定義した変数は、モデルの処理では使えない
と言う感じで覚えれば問題ないかと思います。
そのため、エラーを解消するには、、、
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を戻り値として返したい場合
def self.count_members(table_customers,tables)
all_customers = table_customers * tables #2つの変数の@を削除
Shop.update(members:all_customers)
return all_customers #returnメソッドで戻り値を指定
end
def members
@table_customers = 2
@tables = 3
@all_customers = Shop.count_members(@table_customers,@tables)
#戻り値を格納するための変数を定義
end
モデル内で戻り値の指定、コントローラー内で変数の定義を行うことで、モデル内で扱った値をモデル外でも使用できます。また、カンマで区切ることで、複数の戻り値を取得することも可能です。