5

私は以下のように私のモデルを設定しています。すべてのパーツおよびチャプター フィールドが空白であっても、空白のパーツ レコードが許可されることを除いて、すべて正常に機能します。

class Book < ActiveRecord::Base
  has_many :parts, inverse_of: :book
  accepts_nested_attributes_for :parts, reject_if: :all_blank
end

class Part < ActiveRecord::Base
  belongs_to :book, inverse_of: :parts
  has_many :chapters, inverse_of: :part
  accepts_nested_attributes_for :chapters, reject_if: :all_blank
end

class Chapter < ActiveRecord::Base
  belongs_to :part, inverse_of: :chapters
end

コードを詳しく調べると、:all_blankに置き換えられproc { |attributes| attributes.all? { |key, value| key == '_destroy' || value.blank? } }ます。そのため、代わりにそれを使用して、:all_blankデバッグを追加します。空白の値のみを含む別のハッシュが含まれているにもかかわらず、インスタンス化されたハッシュ オブジェクトであるため、パーツの chapters 属性が応答しているように見えblank?ます。false

chapters_attributes: !ruby/hash:ActionController::Parameters
  '0': !ruby/hash:ActionController::Parameters
    title: ''
    text: ''

このように動作することを意図していないだけですか?

回避策を見つけました:

accepts_nested_attributes_for :parts, reject_if: proc { |attributes|
  attributes.all? do |key, value|
    key == '_destroy' || value.blank? ||
        (value.is_a?(Hash) && value.all? { |key2, value2| value2.all? { |key3, value3| key3 == '_destroy' || value3.blank? } })
  end
}

しかし、これを処理するためのより良い方法が欠けていることを望んでいました。


更新 1:blank? for を再定義しようとしましHashたが、問題が発生します。

class Hash
  def blank?
    :empty? || all? { |k,v| v.blank? }
  end
end

更新 2:これ:all_blankは期待どおりに機能しますが、見苦しく、十分にテストされていません。

module ActiveRecord::NestedAttributes::ClassMethods
  REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |k, v| k == '_destroy' || v.valueless? } }
end
class Object
  alias_method :valueless?, :blank?
end
class Hash
  def valueless?
    blank? || all? { |k, v| v.valueless? }
  end
end

更新 3:どーも!更新 1 にタイプミスがありました。このバージョンは動作するようです。

class Hash
  def blank?
    empty? || all? { |k,v| v.blank? }
  end
end

これは、実行可能な選択肢として意図しない結果をもたらす可能性が高すぎますか? これが適切なオプションである場合、アプリのどこにこのコードを配置する必要がありますか?

4

3 に答える 3