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

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

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

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

2回答

1827閲覧

すべてtrueだったらupdateするif文について

ssk

総合スコア332

Ruby on Rails 5

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

1クリップ

投稿2019/07/30 02:18

編集2019/07/30 05:09

前提・実現したいこと

ある条件でループを回して、全ての条件でレコードを取得することができたら
そのレコードのカラムをアップデート。できなかかったら、バリでショーンエラーを返す書き方を教えていただきたいです。

該当のソースコード・試したこと

やりたいことを伝えるための雰囲気でのコードになりますが、以下のようなイメージです。

ruby

1def Workflow < ApplicationRecord 2 3 before_save -> { update_accident_progress('payment') } 4 5 def update_progress(status) 6 return if number.blank? # numberがなければリターン 7 8 wf = Workflow.where(number: number) 9 wf.each do |w| 10 as = [] 11 as = Status.find_by( compensation: wf.compensation, progress: status) #statusは引数で受け取っています。 12 end 13 14 if as.all? 15 wf.update_all(progress: status) # 1つでもasにfalseがあれば、update_allは実行したくありません。 16 else 17 errors[:base] << 'ダメです。' 18 end 19 end 20end

補足情報(FW/ツールのバージョンなど)

・Rails 5.1.7
・Ruby 2.6.3

追記

ruby

1StatusCSVファイルをnewしてモデルのように扱っています。 2class Status 3 attr_accessor :compensation :progress, :status 4 5 def self.find_by(compensation:, progress:) 6 STATUS_MANAGER.find_by(compensation: compensation, progress: progress) 7 end 8 9 def self.statuses 10 STATUS_MANAGER.statuses 11 end 12end 13

追記2

ruby

1module ProgressUpdateble 2 extend ActiveSupport::Concern 3 4 included do 5 after_create -> { update_progress('payment') } 6 validate :check_combination_status 7 end 8 9 def update_progress(status) 10 return if number.blank? 11 w = Workflow.where(approval_status: 'pending', number: number) 12 w.update_all(progress: status) 13 end 14 15 def check_combination_status 16 return if number.blank? 17 wf = Workflow.where(number: number) 18 unless wf.all? { |w| Status.find_by(compensation: w.compensation progress: progress).present? } 19 errors[:base] << 'エラーメッセージ' 20 end 21 end 22end 23

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

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

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

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

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

guest

回答2

0

wf = Workflow.where(number: number) なもの全てが
Status.find_by( compensation: wf.compensation, progress: status)
であったら
wf.update_all(progress: status)
一つでも違うものが有ったらエラーですね?

wf = Workflow.where(number: number) if wf.all?{|w| Status.find_by( compensation: w.compensation, progress: status) } wf.update_all(progress: status) else ここでエラーであることを設定 end

で行けますが、問題は エラーをどのobjectにもたせるか、です。
errors.add は 配列、ないし Relationではもてず、そのインスタンスでないとだめなので。
errors という配列にもたせて返す、ということになるでしょうか

投稿2019/07/30 04:50

winterboum

総合スコア23329

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

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

ssk

2019/07/30 04:56

ご回答ありがとうございます。 追記2でvalidateとbefore_saveで役割を分けてみました。 こちらの方法で問題ないでしょうか?
ssk

2019/07/30 04:56

>一つでも違うものが有ったらエラーですね? 仰る通りです。
winterboum

2019/07/30 05:03

追記2はちょっと論旨がおかしい before_save はinstanceをsaveする前に行うことなのに、そこで多くの者のupdateが行われる。 雰囲気でなく、きちんと書いてみたほうが良かもです。 定義されていない変数を使っているので、そこだけでエラーになってしまうし。 number とか error とか
ssk

2019/07/30 05:13

ご返信ありがとうございます。 一部、追記2を修正いたしました。 更新がないので、コールバックをafter_createに変更しました。 >雰囲気でなく、きちんと書いてみたほうが良かもです。 雰囲気ではなく、しっかりと書いたつもりでした。 >定義されていない変数 自身がもっているものなので、numberでとることができます。
winterboum

2019/07/30 05:18

混乱してきた、、、 関係するモデルは何でしょう。 moduleは何にinclude?extend?されるものでしょう。 何をトリガーに wfのチェックを行うのでしょう
ssk

2019/07/30 05:21

>moduleは何にinclude?extend?されるものでしょう。 モデルにincludeしております。 >何をトリガーに wfのチェックを行うのでしょう モデルの値になります。
guest

0

ベストアンサー

rb

1module ProgressUpdateble 2 extend ActiveSupport::Concern 3 4 included do 5 after_save -> { update_progress('payment') }, if: proc { self.number.present? } 6 validate :check_combination_status, if: proc { self.number.present? } 7 end 8 9 def update_progress(status) 10 work_flows = Workflow.where(approval_status: 'pending', number: number) 11 wf.update_all progress: status 12 end 13 14 def check_combination_status 15 wf = Workflow.where number: number 16 return if wf.all? { |w| Status.find_by(compensation: w.compensation progress: progress).present? } 17 18 errors[:base] << 'エラーメッセージ' 19 end 20end

before_saveよりafter_saveの方が良さそう。
うーん、なんかもっといい方法がありそうな気もする。

after_saveif:の書き方か場所が違うかも...。
after_save -> { ... }の書き方がよくわからなかった、ごめんよ。

update_allはコールバックをスキップするのを意識しておくといいかも。
もし修正するときにsaveの無限ループに陥らないためにも。

投稿2019/07/30 03:08

編集2019/07/30 05:23
Mugheart

総合スコア2344

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

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

ssk

2019/07/30 03:47

ご回答いただき、ありがとうございます。情報不足で申し訳ございません。 Statusはモデルではないため、以下のエラーになってしまいました。 (StatusはCSVファイルをnewしてモデルのように扱っています) undefined method `exists?' for AccidentStatus:Class
Mugheart

2019/07/30 03:50

Status.find_by(...).present? にするか Status クラスにメソッドを追加するかで対応できそうです。
ssk

2019/07/30 03:55

ありがとうございます。動作確認まですることができました。 また、ログは吐いていますが、バリデーションエラーを発生させることができませんでした。 before_saveだとバリデーションエラーを発生させることはできませんか? ログ出力 logger.error 'Unable to update :progress to the entered status.'
Mugheart

2019/07/30 04:01

before_saveではなくupdate_allがバリデーションチェックを行いません。 なので明示的にActiveRecord::RecordInvalidを発生させています。 バリデーションチェックがしたいのであればループを回して1つずつupdateすれば良いです。
Mugheart

2019/07/30 04:05

あぁ、でもbefore_saveではなくbefore_validationでやるべきな気もしますね。
Mugheart

2019/07/30 04:06

before_save は バリデーションが通った後の save 直前にコールバックされるものなのでそういう意味ではバリデーションエラーを発生させることができないともなるのかもしれないです。
ssk

2019/07/30 04:18

ありがとうございます。 before_validationにした場合、validation前にupdate_allされる可能性があるのはまずいですね。
ssk

2019/07/30 04:19

となると、before_saveとvalidateを分けた方がいいということでしょうか?
Mugheart

2019/07/30 04:28

validate :validate_method でバリデーションを用意しておくのがいいかもしれないですね。 回答編集してみます。
ssk

2019/07/30 04:53

ありがとうございます。他でも使い回すので、concern化して追記2に書いてみました。 どうしょうか。。
Mugheart

2019/07/30 05:14

いつの間にかafter_createになっていた。 新規作成の時しか呼ばれないけど大丈夫ですか?
ssk

2019/07/30 05:19

ありがとうございます。 更新がないものなので、新規作成のみで大丈夫です。 (あとからの変更で申し訳ないです。)
Mugheart

2019/07/30 05:20

うまく動くことを願ってます。
Mugheart

2019/07/30 05:24

if と unless 逆に書いてました危ない危ない。修正しました。
ssk

2019/07/30 05:25

修正、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問