Search code examples
ruby-on-railssimple-formsimple-form-for

Rails - Simple Form - Nested Resources paths


I am trying to make an app in Rails 4 using simple form.

I have 3 models: Project, Project_Question, Project_Answer

The associations are:

Project:

 has_many :project_questions, dependent: :destroy#, through: :projects
  accepts_nested_attributes_for :project_questions

Project Question:

belongs_to :project#, counter_cache: true
  has_one :project_answer, dependent: :destroy
  belongs_to :user
  accepts_nested_attributes_for :project_answer

Project Answer:

  belongs_to :project_question#, counter_cache: true
  belongs_to :user

My routes are nested as follows:

resources :projects do
  resources :project_questions do
    resources :project_answers
  end
end

In my Project Questions partial, I want a link to answer the question. I have a link that is set out as follows:

        <%= link_to 'Answer this question', new_project_project_question_project_answer_path(:project_id => @project.id, :project_question_id => singleQuestion.id) %>

I got help getting to the link point with help on the attached question:

http://stackoverflow.com/questions/30978447/rails-link-to-path

I since changed the project answer model so that project question has one (rather than has many project answers) and updated the path in the Answer this Question link, to singular instead of plural.

When I click the 'Answer this question' link, I get this error:

undefined method `project_answers_path' 

It is pointing to the simple form for line in the project answers form. That form has:

<%= simple_form_for [@project, @project_question, @project_answer] do |f| %>
    <%= f.input :project_question_id, as: :hidden, input_html: {value: @project_question.id} %>
    <%= f.input :answer, label: 'Answer?', :label_html => {:class => 'question-project'}, placeholder: 'Type your answer here', :input_html => {:style => 'width: 650px', class: 'response-project'} %>
    <br><br><br>
    <%= f.button :submit, 'Send!', :class => "cpb" %>

<% end %>

When I rake routes for project answer, I get:

    project_project_question_project_answers GET      /projects/:project_id/project_questions/:project_question_id/project_answers(.:format)          project_answers#index
                                              POST     /projects/:project_id/project_questions/:project_question_id/project_answers(.:format)          project_answers#create
  new_project_project_question_project_answer GET      /projects/:project_id/project_questions/:project_question_id/project_answers/new(.:format)      project_answers#new
 edit_project_project_question_project_answer GET      /projects/:project_id/project_questions/:project_question_id/project_answers/:id/edit(.:format) project_answers#edit
      project_project_question_project_answer GET      /projects/:project_id/project_questions/:project_question_id/project_answers/:id(.:format)      project_answers#show
                                              PATCH    /projects/:project_id/project_questions/:project_question_id/project_answers/:id(.:format)      project_answers#update
                                              PUT      /projects/:project_id/project_questions/:project_question_id/project_answers/:id(.:format)      project_answers#update
                                              DELETE   /projects/:project_id/project_questions/:project_question_id/project_answers/:id(.:format)      project_answers#destroy

I don't understand why the #new action for the project_project_questions_project_answers action is plural for answers when there will only be one answer, but I think this has something to do with the error message I get when I click the 'Answer this Question' link.

new_project_project_question_project_answer GET      /projects/:project_id/project_questions/:project_question_id/project_answers/new(.:format)      project_answers#new
 e

When I try pluralising the first line of the form for project answers, for project questions, like this:

<%= simple_form_for [@project, @project_questions, @project_answer] do |f| %>

I get this error:

undefined method `project_answers_path' for #<#<Class:0x0000010a193f10>:0x0000010a3abb40>

When I try pluralising the first line of the form for project answers, for project questions and project answers, like this:

<%= simple_form_for [@project, @project_questions, @project_answers] do |f| %>

I get this error:

undefined method `model_name' for NilClass:Class

Can anyone see what I've done wrong? I read a post suggesting that I use project_answer (singular) in the routes.rb. I tried this but I get an error saying no route matches the plural.

Project Answer Controller:

class ProjectAnswersController < ApplicationController
  before_action :set_project_answer, only: [:show, :edit, :update, :destroy]

  # GET /project_answers
  # GET /project_answers.json
  def index
    @project_answers = ProjectAnswer.all
  end

  # GET /project_answers/1
  # GET /project_answers/1.json
  def show
  end

  # GET /project_answers/new
  def new
    @project_answer = ProjectAnswer.new
  end

  # GET /project_answers/1/edit
  def edit
  end

  # POST /project_answers
  # POST /project_answers.json
  def create
    @project_answer = ProjectAnswer.new(project_answer_params)

    respond_to do |format|
      if @project_answer.save
        format.html { redirect_to @project_answer, notice: 'Project answer was successfully created.' }
        format.json { render action: 'show', status: :created, location: @project_answer }
      else
        format.html { render action: 'new' }
        format.json { render json: @project_answer.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /project_answers/1
  # PATCH/PUT /project_answers/1.json
  def update
    respond_to do |format|
      if @project_answer.update(project_answer_params)
        format.html { redirect_to @project_answer, notice: 'Project answer was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @project_answer.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /project_answers/1
  # DELETE /project_answers/1.json
  def destroy
    @project_answer.destroy
    respond_to do |format|
      format.html { redirect_to project_answers_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_project_answer
      @project_answer = ProjectAnswer.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def project_answer_params
      params[:project_answer].permit(:answer, :project_question_id)
    end
end

Solution

  • Your new action of project_answers controller should be having @project, @project_question defined

    def new
      @project_answer = ProjectAnswer.new
      @project = Project.find(params[:project_id])
      @project_question = ProjectQuestion.find(params[:project_question_id])
    end
    

    So that you can use those in the form like this

    <%= simple_form_for [@project, @project_question, @project_answer] do |f| %>