2016-10-13 12 views
2

コード少なくとも1つのネストされたオブジェクトの存在を検証する方法は?

class Survey < ApplicationRecord 
    has_many :questions, inverse_of: :survey, :dependent => :destroy 
    accepts_nested_attributes_for :questions 
    validates_associated :questions 
end 

class Question < ApplicationRecord 
    belongs_to :survey, inverse_of: :questions 
    validates_presence_of :survey 
end 

私の調査のコントローラー

def new 
    @survey = Survey.new 
    2.times {@survey.questions.build} 
end 

フォーム

<%= form_for @survey do |f|%> 
     <p> 
      <%= f.label :name%> 
      <%= f.text_field :name%> 
     </p> 
     <%= f.fields_for :questions do |builder|%> 
      <p> 
       <%= builder.text_area :content, rows: 3%> 
      </p> 
     <% end %> 

     <p><%= f.submit %></p> 

    <% end %> 

ユーザーがアンケートを作成し、フォームの2つの質問を提供していたときにあなたが見ることができるように、私は、ユーザーが少なくとも供給したいです調査を作成するときに1つの質問。どのようにそれを達成することができますか?

+1

私はこれを試していないが、多分 '検証しない:質問、存在を:true'には十分であろう。組み込みのレール検証が実際に存在をテストするかどうかは分かりません( 'self.questions.present?'のようなもの)。もしそうなら、それはうまくいくはずです – MrYoshiji

+1

@MrYoshiji私は実際には、「検証:質問、存在:真」が働くとも考えています。私はカスタムの 'validate'をバリデーションのロジックをよりコントロールするために独占的に使用することをお勧めします –

+0

@MrYoshiji私はまた 'validates:questions、presence:true'を試しましたが、うまくいきますが、私はAndrewDeinekoと同意します。 count –

答えて

1

選択肢の一つは、カスタム検証を使用することです:

validate :questions_count 

private 

# or something more explicit, like `at_least_one_question` (credits to @MrYoshiji) 
def questions_count 
    errors.add(
    :base, 
    'You can not save a survey without questions. Add at least one question' 
) if questions.none? 
end 

survey場合、基本的に、検証は、すべてのユーザーが作成する時間や、「タッチ」(更新)surveyオブジェクトを解雇され、それが失敗します少なくとも1つのquestionが関連付けられていません。

+0

私の意見では、メソッドの名前 'questions_count'は明示的ではありません。 'at_least_one_question_is_present_validation'のようなものは、もっと明白です。しかし、あなたは考えました+1 – MrYoshiji

+0

@MrYoshijiは実際に 'at_least'でメソッド名を開始しましたが、' at_least'で始まるメソッドがあったかどうかを考えていました。メッセージはメソッドについての話を伝えるべきですが、あなたのコメントを含めるように答えを編集します:) –

3

あなたは、配列の長さをテストし、簡単に行うことができます:

validates :questions, length: {minimum: 1, message: 'should have at least 1 question defined.'} 
+0

この解決法は私の意見では良い方法です。 Railsのビルトインバリデーションを使用し、新しいものを作成する代わりにI18nデフォルトエラーメッセージを使用することができます。これは、検証の目的ではクリーンです。質問についてもう1つの論理がある場合は、2つの検証のミックスインではなく、このロジックを含むもう1つの個別の検証を実装する必要があります。 +1 – MrYoshiji

関連する問題