【Ruby on Rails7】cocoonを導入(その5:子の0行入力はエラーとしたい)

この記事では、Ruby on Rails7のgemパッケージcocoonについて、導入・カスタマイズ行います。
今回は登録時に、子の件数が0件にならないようにする手法を考えます。

前回の続き。

今回は、子が0件でも更新されてしまうことを防ぐ方法を考えます。

目次

子が0件でもエラーにならない

多くの紹介記事のとおりに導入すると子が0件でも通ってしまう

掲題のとおりですが、なぜエラーにならないのでしょうか?

モデルapp/models/project.rbを覗いてみます。

class Project < ApplicationRecord
  has_many :tasks, dependent: :destroy
  accepts_nested_attributes_for :tasks, reject_if: :all_blank, allow_destroy: true
end

何が問題なのでしょうか?

解決方法(モデル側の制御)

一般的なエラーロジックを追加しても解決はしない

すべての項目がブランクの場合はエラーにするといったバリデーションを入れても上手くは行かないです。

  # 子のバリデーション
  validate :check_tasks

  private

  # 子供側のバリデーション
  def check_tasks
    tasks.each_with_index do |task, idx|
      if idx == 0
        if task.description.blank? && task.他の入力項目.blnak?
          errors.add(:base, '1行目は入力してください。')
        end
      end
  end

このロジックは除去します。

バリデーションの前にすでに行が除去されていることに気づく

他の障害が発生した際に気が付きましたが、未入力行はバリデーションの前に除去されていることに気が付きました。

ということは、それ以前の定義の問題でしょうか?

reject_if: :all_blankを除去すれば0件出力は防げる

モデル内にあるreject_if: :all_blankの記述を除去すれば、バリデーション前の未入力行の除去が防げます。

class Project < ApplicationRecord
  has_many :tasks, dependent: :destroy
  accepts_nested_attributes_for :tasks, allow_destroy: true
end

このロジックは除去します。

あとは、このモデル側でvalidates :カラム名, presence: trueを追加してあげれば、良いでしょう。

解決方法(追記1:コントロール側の制御)

新規時に1行目(空白行)を表示させたい

新規時に1行目(空白行)を表示させたいは以下のようにします。

  # GET /projects/new
  def new
    @project = Project.new
    # 子モデルも作成
    @project.tasks.build
  end

@project.tasks.buildを挿入してあげれば、1行空行が表示されます。

解決方法(追記2:ビュー側の制御)

1行目のみ削除ボタンを表示させない

全行に削除ボタンを表示させてしまうと、(0件エラーは表示できても)なんかちょっと…と言われる可能性はあります。

この場合、1行目のみ削除ボタンを表示させないという手法がありそうです。

    - if f.options[:child_index] != 0
      .field
        %br
        = link_to_remove_association "明細削除", f

if f.options[:child_index] != 0:child_indexが行番(0〜)なので、0を除いて削除ボタンを表示させるようにします。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA

目次