views:

64

answers:

3

Hi,

I have a survey as part of an application I'm building. The user can create a survey and specify questions dynamically (can have as many as they want), so I've used an associated model with:

  #survey.rb
  has_many :survey_questions, :dependent => :destroy
  has_many :survey_answers, :dependent => :destroy

  after_update :save_survey_questions
  validates_associated :survey_questions

  def save_survey_questions
    survey_questions.each do |t|
      if t.should_destroy?
        t.destroy
      else
        t.save(false)
      end
    end
  end  

  def survey_question_attributes=(survey_question_attributes)
    survey_question_attributes.each do |attributes|
      if attributes[:id].blank?
        survey_questions.build(attributes)
      else
        survey_question = survey_questions.detect { |e| e.id == attributes[:id].to_i }
        survey_question.attributes = attributes
      end
    end
  end

  #surveys_controller.rb

  def new
    @survey = Survey.new
    if(@survey.survey_questions.empty?)
      @survey.survey_questions.build
    end
    respond_to do |format|
      format.html # new.html.erb
    end
  end

  def create
    @survey = Survey.new(params[:survey])
    respond_to do |format|
      if @survey.save
        format.html { redirect_to(survey_path(:id => @survey)) }
      else
        format.html { render :action => "new" }
      end
    end
  end

#survey_question.rb
class SurveyQuestion < ActiveRecord::Base
  belongs_to :survey
  attr_accessor :should_destroy

  def should_destroy?
    should_destroy.to_i == 1
  end

  validates_presence_of :question, :survey_id

end

The problem is when I submit I get an error on the questions:

@errors={"survey_questions"=>["is invalid", "is invalid", "is invalid"]}

I believe it is because the survey_id I have linking surveys to survey_questions is not being filled in.

Any ideas how I can overcome this?

If I create the survey with no questions, then add them afterwards via edit, then it works perfectly.

A: 

Hi, I'm pretty sure that accepts_nested_attributes can help you a lot, there you'll find some examples building the associated objects wich seems to be your problem (since the survey_id in survey_questions is not being filled in), basically you should define in your models something like:

class Survey < ActiveRecord::Base

  has_many :survey_questions
  accepts_nested_attributes_for :survey_questions, :allow_destroy => true

...
end

It will handle all the SurveyQuestions validations through Survey.

jpemberthy
only problem is i'm using rails 2.2.2
Chris
Hey Chris, cool that everything is working for you, but in my opinion, you should use nested_attributes letting rails make the `save_survey_questions` method by including `:reject_if` checking `survey_question.should_destroy?`, also for the `survey_question_attributes=(survey_question_attributes)` laters!
jpemberthy
A: 

Your code looks close to the standard --> http://railscasts.com/episodes/75-complex-forms-part-3

Are you sure you are getting the question parameter back correctly? I only ask because that is the other thing you are validating against and you don't have the form code in there so I can't see what's coming back to the controller.

MattMcKnight
A: 

OK,

I've managed to fix it and it was a really silly mistake on my part.

In survey_question.rb I had the line :

validates_presence_of :question, :survey_id

However, rails automatically deals with survey_id because of the has_many belongs_to relationship!

So this should be validates_presence_of :question

I also in the process of finding this out upgraded rails to 2.3.4 and started using:

accepts_nested_attributes_for :survey_questions, :allow_destroy => true

which dealt with all the attributes etc.

Chris