質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

2回答

935閲覧

railsのcontroller内の綺麗な書き方について

yuta66jp

総合スコア11

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

1グッド

0クリップ

投稿2020/03/13 04:41

前提・実現したいこと

railsの練習としてダイエットサイトを作成しております。
tableがそれぞれ、users,rewards,diaries,body_weightsなどあります。
機能としてポイント付与機能を実装いたしましたが、rewardsが作成されるメッソドが同じような記述で増えてしまっております。
あまり、記述として綺麗ではないのかなと思っております。
また今後の実装予定として、userテーブルのランクステータスがポイントに応じてシルバーやゴールドなどに更新するように考えておりますが、その記述も現在のdaiarycontrollerのcreateアクションに記載していいものか悩んでおります。
rewardsが作成されるメッソドなどをmodelに記載するなどの方法は可能でしょうか。
また、書き方としてベストな書き方でしょうか。

該当のソースコード

class DiariesController < ApplicationController def new # viewへ渡すためのインスタンス変数に空のモデルオブジェクトを作成 @diary = Diary.new @body_weight = BodyWeight.new end def create # build=モデルオブジェクトを生成(newの別名) # 1対Nの際、buildによる関連付けメソッド(関連付けメソッド名.build)を使用 @diary = current_user.diaries.build(diary_params) @diary.save # 日記作成ポイント付与 @diary_point = current_user.rewards.build( user_id: current_user.id, point: 10, issue_reason: 2 ) @diary_point.save # 今後この下にuserステータスのポイントに応じた変更を記載予定 # body_weight作成 # 1対1の際、buildによる関連付けメソッド(build_関連付けメソッド名)を使用 @body_weight = @diary.build_body_weight( user_id: current_user.id, weight_record: params[:diary][:body_weight][:weight_record] ) @body_weight.save # 目標体重達成ポイント付与 @weight_record = @body_weight.weight_record @goal_weight = current_user.goal_weight if @weight_record <= @goal_weight @achieve_point = current_user.rewards.build( user_id: current_user.id, point: 100, issue_reason: 5 ) @achieve_point.save end # 今後この下にuserステータスのポイントに応じた変更を記載予定 # createで新規食事記録画面へ遷移(パラメーターをredirect_toに直接渡す) redirect_to new_meal_record_path(id: @diary.id) end

試したこと

modelに記載しようと思い書きましたが、
NoMethodError (undefined method `point' for #Class:0x00007fa7fc0dfad8):
とエラーが出ました。
そもそもmodelに記載することがベストなのかも知りたいです。

class Reward < ApplicationRecord # アソシエーション設定 belongs_to :user # enum機能の定義 enum issue_reason: { 新規登録: 0, ログイン: 1, 日記投稿:2, コメント: 3, フォロー: 4, 目標達成:5 } def point @diary_point = current_user.rewards.build( user_id: current_user.id, point: 10, issue_reason: 2 ) @diary_point.save end end
def create # build=モデルオブジェクトを生成(newの別名) # 1対Nの際、buildによる関連付けメソッド(関連付けメソッド名.build)を使用 @diary = current_user.diaries.build(diary_params) @diary.save # 日記作成ポイント付与   Rewaed.point # 今後この下にuserステータスのポイントに応じた変更を記載予定
s.k👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

アプリの全体像を把握しないでの回答ですので、枝葉の話になってるかもしれないのはご勘弁

基本的にはcontrollerに書かずにmodelに書く方針は良いと思います。
問題はどのmodelに書くか、です。
Reward を User に 与える物、としての model があるならそこに書くべきなのですがそれがないときに Reward にかくか Userに書くか。
インスタンスmethodにしたいなぁという個人的な思いがあるので、私でしたらUsrに書きたい。
一方、reason毎にmethodを書くのはDRYでないので、resonを渡してそれに基づきpointを決めたいが、その対応はUserではなくReasonが保つべき。
やっぱりReasonのクラスmethod必要か。。。

Point = [50,5,20,.....] def self.give_reward(user,reason) create(point: Point[reason],      issue_reason: reason,      user_id: user.is      ) end

reason は enum にしたいですが。

投稿2020/03/19 21:39

winterboum

総合スコア23329

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuta66jp

2020/03/20 00:56

回答ありがとうございます! modelに書く方針で問題ないとのことで安心しました。 まだ、勉強を始めたばかりでインスタンスメソッドとクラスメソッドの違い(使い分け?)が明確わかっていないので、勉強いたします!
yuta66jp

2020/03/20 01:18

何度も質問しすみません。 回答頂いた、コードで動き何度も同じ記述をせずにDRYな書き方ができました。 Point = [50,5,20,.....]ここの部分がよくわかっておりません。このPointと言うのは何になるのでしょうか。 なぜ大文字でないと動かないのかもわかりません。 ご回答いただければありがたいです。
winterboum

2020/03/20 02:11

Point = [50,5,20,.....] issue_reasn の 0,1,2,3,4 に応じた point です 大文字で始めたのは、 model Reward の 定数 として持たせたかったので
yuta66jp

2020/03/21 03:23

回答ありがとうございます!
guest

0

modelに記載する際にメッソドの前にselfを記載し使用することができました。現在modelに記載しておりますが、適切でしょうか。

class Reward < ApplicationRecord # アソシエーション設定 belongs_to :user # バリデーション設定 # numericalityは属性に数値のみが使われているか検証(デフォルトでnillは弾く) # only_integerで整数のみを許可 validates :point, numericality: { only_integer: true } validates :issue_reason, presence: true # enum機能の定義 enum issue_reason: { 新規登録: 0, ログイン: 1, 日記投稿:2, コメント: 3, フォロー: 4, 目標達成:5 } # 取得ポイントの合計値を計算 def self.total_point self.all.sum(:point) end # 新規登録ポイント定義 def self.sign_up_point(user) sign_up_point = Reward.new( user_id: user.id, point: 50, issue_reason: 0 ) sign_up_point.save end # ログインポイント定義 def self.sign_in_point(user) sign_in_point = Reward.new( user_id: user.id, point: 5, issue_reason: 1 ) sign_in_point.save end # 日記作成ポイント定義 def self.diary_point(user) diary_point = Reward.new( user_id: user.id, point: 20, issue_reason: 2 ) diary_point.save end # コメントポイント定義 def self.comment_point(user) comment_point = Reward.new( user_id: user.id, point: 5, issue_reason: 3 ) comment_point.save end # フォローポイント定義 def self.follow_point(user) follow_point = Reward.new( user_id: user.id, point: 20, issue_reason: 4 ) follow_point.save end # 目標体重達成ポイント定義 def self.achieve_point(user) achieve_point = Reward.new( user_id: user.id, point: 100, issue_reason: 5 ) achieve_point.save end end

投稿2020/03/17 23:43

yuta66jp

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問