2017-08-01 7 views
1

私は、関連があるモデルではかなり複雑なビジネスロジックを持っています。私は、ユーザーが未完成の(無効な)モデルを将来の完成のために保存できるようにしたい。私のコントローラでは、私はinstance.save(validate: false)と呼んでいます。保存後にRailsコールバックを復元する(validate:false)

私のアプリケーションから抽出した3つのモデルは次のとおりです。 関連する部分のみを抽出したため、モデルが過度に見られることがあります。

1)Containerモデル:

class Container < ApplicationRecord 
    Languages = %w(fr en de it es) 

    belongs_to :name, class_name: "Name", foreign_key: :name_id 

    accepts_nested_attributes_for :name 

    validates :name, presence: true 

    # create an empty model 
    def self.create_new 
     c = Container.new 

     c.name = Name.new 
     c.name.save 
     Languages.each do |l| 
      c.name.translations << NameItem.new(language: l, text: "") 
     end # Languages.each do |l| 

     c.description = Description.new 
     c.description.save 
     Languages.each do |l| 
      c.description.translations << DescriptionItem.new(language: l, text: "") 
     end # Languages.each do |l| 

     c 
    end 
end 

2)Nameモデル:

class Name < ApplicationRecord 
    has_many :translations, class_name: "NameItem", foreign_key: :parent_id 

    accepts_nested_attributes_for :translations 
end 

3)NameItemモデル:命令の次のシーケンスを考える

class NameItem < ApplicationRecord 
    validates :language, presence: true 
    validate :text_validation 

    private 
    def text_validation 
     return if language.nil? 

     errors.add(:text, :blank_text, language: language) if text.nil? || text.size == 0 
    end 
end 

、私がでていますなぜ最後の命令(instance.valid?) trueを返します。検証コールバックは無効になっているようですが、これが適切な診断であるかどうかはわかりません。 ?これはaccepts_nested_attributes_forの使用に関連することができます

# create an invalid model (since empty) 
instance = Container.create_new 

# check that this instance is invalid 
instance.valid? # returns false, this is the expected behavior 

# save the model, skipping the validations 
instance.save(validate: false) 

# now instance.valid? will always return true, because it will 
# skip the validations. How can I restore the callbacks ? 
instance.valid? # returns true, but this is not the desired behavior, 
       # hence my question 

私は次のような指示にコールバックを無効にし、再度有効にしようとしたが、無駄に。

[:create, :save, :update].each do |action| 
    Container.skip_callback(action) 
end 

[:create, :save, :update].each do |action| 
    Container.set_callback(action) 
end 

だから私の質問は:instance.save(validate: false)を呼び出した後、命令は私がinstance.valid?が実際に再検証チェックを実行し、falseを返すないように実行する必要が何をすべきか?

+0

ユーザーがいくつかの属性を入力せずにレコードを作成できる場合は、作成イベントではなく、その存在をまったく検証しないでください。しかし、レコードのライフサイクルの後半で、ユーザーがこのレコードを公開したい(またはそれを使用して「完了」としてチェックする)場合は、検証を行う必要があります。 – MrYoshiji

+0

ありがとうございます@MrYoshiji。この目的を達成するためのコードスニペットを提案してください。 –

+0

あなたのアプリケーションでは、Container **が必要とする瞬間(イベント)で**属性の有無をチェックする必要がありますか?特定のコンテキストでコンテナを使用したい場合、使用可能なコンテナにattrsが存在する必要があります。 – MrYoshiji

答えて

2

save(validate: false)を実行してもコールバックはオフにならないため、レコードを検証するためにsaveの後に実行される他のコードが必要です。

before/after_saveコールバックを確認し、モデルを投稿することがあります。

編集:関連付けは、新しいレコードで適切に存在していないとして、新たなレコードのネストされた属性を使用して

はあなたに検証トラブルを与えるだろう、それは本当に既存のレコードに最適です。これについての良い説明と最後の段落の回避策はthis answerです。

+0

ありがとうございます+あなたのヒントを+1してください。私は質問を更新しました。 'before/after_save'コールバックは、Railsでの私の経験と同じように、何も特別なものを保持しません。私はむしろ問題が 'accepts_nested_attributes_for'と関係していると思っていますが、Googleの検索で問題が解決されませんでした。 –

+1

こんにちはAlbertさん、私の答えをあなたに役立つ何かへのリンクで更新しました。 – Matt

関連する問題