更新后的路由问题

时间:2015-11-17 03:51:53

标签: ruby-on-rails ruby-on-rails-4 rails-routing form-for

所以我仍然是一个Rails noob,所以我可能完全没错,但我有两个控制器。问题控制器和答案控制器。我正在尝试构建一个评分功能,允许管理员用户为论文问题分配点数。我正在使用/answer/:id:id是问题的id,然后渲染部分迭代该id的所有答案。清楚如泥,我敢肯定......

我的问题:在显示用户答案的​​部分内容中,我有一个表单,允许管理员填写该答案的分数并提交。理想情况下,我希望它移动到下一页(使用will_paginate),但至少,我想留在同一页面上。我能够使表单工作,但它继续到/ answers /:id,但其中:id是单个答案的id,所以不是我希望的。

answers_controller.rb

class AnswersController < ApplicationController

  def index
    @user = current_user
    @questions = Question.all

  end


  def show
    @user = current_user
    @question = Question.find(params[:id])
    @answers = Answer.where("question_id = ?", @question.id).paginate(:page => params[:page], :per_page => 1)
    @answer = Answer.where("question_id =? AND user_id = ?", @question.id, @user.id)
  end

  def edit
    @answer = Answer.find(params[:id])
  end

  def update
    @answer = Answer.find(params[:id])
    if @answer.update_attributes(grade_params)
      flash[:success] = "Answer Graded"
    else
      flash[:warning] = "Not Graded"
    end
  end

  private

  def grade_params
    params.require(:answer).permit(:points_earned)
  end

end 

_essay_grades.html.erb(在包含表单的节目页面上呈现的部分内容)

<% @answers.each do |answer| %>
<p>User: <%= answer.user_id %></p>
<%= answer.answer %><br>
<%= @question.value %>
<br>
  <%= form_for(answer) do |f| %>

  <%#= f.radio_button :points_earned, @question.value %><br>
  <%#= f.radio_button :points_earned, 0 %> <br>
  <%= f.text_field :points_earned %> Points<br>
  <br>
  <%= f.submit "Award Points" %>
  <% end %>

<% end %>
<br>
<br>

<%= will_paginate @answers, renderer: BootstrapPagination::Rails %>

的routes.rb

Rails.application.routes.draw do


  resources :admins, :answers, :static_pages, :questions

  devise_for :users, :controllers => { registrations: 'registrations' }, 
     :path => '', :path_names => 
    { :sign_in => "login", :sign_up => "register" }


  root "static_pages#index"
end

我确信这里有一个简单的解决方案(或者它可能会改变我设置的方式......)。任何帮助是极大的赞赏!

反馈后 添加了成绩模型并建立了与问题的直接关系。

answer_controller.rb

class AnswersController < ApplicationController


  def show
    @user = current_user
    @question = Question.find(params[:id])
    @answers = Answer.where("question_id = ?", @question.id).paginate(:page => params[:page], :per_page => 1)
    @answer = Answer.where("question_id =? AND user_id = ?", @question.id, @user.id)
  end



  def update
    @user = current_user
    @question = Question.find(params[:question_id])
    @answer = @question.answers.find(params[:id])

    @grade = @question.grades.new(grade_params)

    if @grade.save
      flash[:success] = "Answer Graded"
      redirect_to @question
    end
  end

      private

      def grade_params
        params.require(:grade).permit(:user_id, :answer_id, :points_earned, :graded_by, :comment)
      end

    end

_answer.html.erb

<%= answer.user_id %>
<%= form_tag [@question, answer], method: :put do %>
<%= hidden_field_tag :graded_by, current_user.id %>
<%= hidden_field_tag :answer_id, answer.id %>


    <%= number_field_tag :points_earned %>
    <%= submit_tag "Submit Grade" %>
<% end %>

的routes.rb

Rails.application.routes.draw do

  resources :questions do
    resources :answers, only: [:update]
  end

  resources :admins, :static_pages 

问题/ show.html.erb

...
<h3>Show answers</h3>
<%= render @answers, locals: {question: @question} %>
<%= will_paginate @answers, renderer: BootstrapPagination::Rails %>

2 个答案:

答案 0 :(得分:0)

您必须在表单中使用以下内容,以便更新不会加载新页面,但仍会提交更新。使用Chrome / Firefox开发人员工具查看请求/响应。

<%= form_for(answer), :remote => true do |f| %>

然后,更改答案控制器中的更新操作以加载“下一个未评级的答案”:

def update
  rated_answer = Answer.find(params[:id])
  if rated_answer.update_attributes(grade_params)
    flash[:success] = "Answer Graded"
  else
    flash[:warning] = "Not Graded"
  end
  @answer = get_next_unrated_answer(rated_answer.question_id)
end

private

def get_next_unrated_answer(question_id)
  # I am making a couple of assumptions on your model here, but get an answer that has not been rated yet for this question
  next_answer = Answer.where("question_id = ? and points_earned = ?", question.id, nil)
  #returned automatically
end

然后您必须创建app / views / answers / update.js.erb以使用以下行加载页面的新答案:

$('#main_div').html('<%= escape_javascript(render partial: 'whatever_partial_you_have_created_to_display_the_next_unrated_answer') %>');

只需创建一个新的部分,即可显示您的答案并正确填写下一个未评级的答案。或者理想情况下,使用相关的部分加载您的初始“show.html.erb”并重复使用它们。

这是一种简单的方法,但如果我是你,我可能会将这些新功能重命名为不使用'更新'或'显示',而是将其称为'rate',甚至是'rate_show',所以你如果您的项目稍后需要,可以使用更新并以原始形式显示(用于更新和回答或显示答案)。

答案 1 :(得分:0)

根据我对你的问题的理解,我认为你最好调查nested routes

#config/routes.rb
resources :questions do
   resources :answers, only: [:update]
end

#app/controllers/questions_controller.rb
class QuestionsController < ApplicationController
   def show
      @question = Question.find params[:id]
   end
end

#app/views/questions/show.html.erb
<%= @question.title %>
<%= render @question.answers, locals: {question: @question} %>

#app/views/questions/_answer.html.erb
<%= answer.title %>
<%= form_tag [question, answer], method: :put do %>
    <%= text_field_tag :grade %>
    <%= submit_tag %>
<% end %>

以上内容将为您提供已经存在的内容(只是为了澄清您的“明显疯狂”的评论并非所有的情况!)。

-

以下是嵌套资源的来源。

目前,似乎您在回答问题时遇到了问题:

  

其中:id是个别答案的ID,所以不是我希望的

对此的补救措施如下:

#app/controllers/answers_controller.rb
class AnswersController < ApplicationController
   def update
      @question = Question.find params[:question_id]
      @answer = @question.answers.find params[:id]

      @grade = @answer.grades.new grade_params
      redirect_to @question if @grade.save
   end

   private

   def grade_params
      params.permit(:points_earned) #-> will probably have to refactor this
   end
end

这将为该特定答案创建一个新的grade(您应该在关联的模型中有)。由于答案已与question相关联,因此它允许您使用嵌套路由加载两者。

就您的设置而言,我个人会添加Grade模型,以便您可以为每个答案分配多个成绩。这违反了您当前的架构,但可以很好地确保您具备促进多个等级所需的功能:

#app/models/grade.rb
class Grade < ActiveRecord::Base
   belongs_to :answer
   belongs_to :user
end

#app/models/answer.rb
class Answer < ActiveRecord::Base
   has_many :grades
end