4

Code

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

My Surveys Controller

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

Form

    <%= 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 %>

As you can see when user creates a survey the form provides two questions, i want user to supply at least one question when creating the survey. How can it be achieve???

4
  • 1
    I never tried this, but maybe validates :questions, presence: true would be sufficient. I don't know if the built-it rails validation actually test the presence (something like self.questions.present?). If yes, then it should be fine Commented Oct 13, 2016 at 20:41
  • 1
    @MrYoshiji I actually also think, that validates :questions, presence: true would work. I would prefer the custom validate exclusively because of more control over validation's logic Commented Oct 13, 2016 at 20:52
  • @MrYoshiji i also tried 'validates :questions, presence: true' it works but i agree with AndreyDeineko who knows maybe one day i will have to validate 2 question count Commented Oct 13, 2016 at 21:02
  • @EmmanuelMtali henners66's answer can provide a solution if one day you want to force the questions count to be different than 1. Commented Oct 14, 2016 at 14:57

2 Answers 2

7

You could just test for the length of the array and simply do:

validates :questions, length: {minimum: 1, message: 'should have at least 1 question defined.'}
Sign up to request clarification or add additional context in comments.

1 Comment

This solution is way better in my opinion. It uses Rails' built-in validations, can use the I18n default error messages instead of forcing you to create a new one. This is clean for the purpose of the validation. If there is another logic to be done about the questions, then another separate validation should be implemented, containing this logic and not a mixin of the two validations. +1
1

One of the options is to use custom validation:

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

Basically, the validation will be fired every time you create or "touch" (update) the survey object, and it will fail, if survey will not have at least one question associated.

2 Comments

In my opinion, the method's name questions_count is not explicit at all. Something like at_least_one_question_is_present_validation would be way more explicit. But you got the idea, +1
@MrYoshiji actually started the method name with at_least, but caught myself thinking whether I have ever had a method starting with at_least - and I could not remember such :D So I think validation message should tell the story about the method, but will edit the answer to include your comment :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.