2015-11-17 2 views
1

Donc, je suis toujours un Rails noob alors je vais peut-être complètement à tort, mais j'ai deux contrôleurs. Un contrôleur de question et un contrôleur de réponse. J'essaie de créer une fonction de notation qui permet à un utilisateur admin d'assigner des points à des questions à développement. J'utilise le /answer/:id pour être où: id est l'identifiant de la question et ensuite rendre un partiel pour parcourir toutes les réponses pour cet identifiant. Clair comme de la boue, je suis sûr ...Problème de routage après la mise à jour

Mon problème: Dans le partiel où la réponse de l'utilisateur est affichée, j'ai un formulaire qui permet à l'administrateur de remplir le nombre de points pour cette réponse et soumettre. Idéalement, je voudrais passer à la page suivante (en utilisant will_paginate), mais au moins, j'aimerais rester sur la même page. Je suis capable de faire fonctionner le formulaire mais il continue à aller à/answers /: id mais où: id est l'identifiant de la réponse individuelle, donc pas ce que j'espère.

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 (partiel qui est rendue sur la page d'affichage qui contient le formulaire)

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

de 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 

Je suis sûr qu'il y a une solution simple ici (ou peut-être que ça change la façon dont j'ai les choses en place ...). Toute aide est grandement appréciée!

APRÈS RÉTROACTION: Ajout du modèle de catégories et établissement d'une relation directe avec les questions.

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 

Questions/show.html.erb

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

Je ne suis pas 100% clair sur la question, mais '<% = form_for réponse à distance: true fais | f | %> 'pourrait être ce que vous cherchez, cela empêchera un lien vers une nouvelle URL. –

Répondre

0

Vous devrez utiliser ce qui suit dans votre formulaire afin que la mise à jour ne charge pas une nouvelle page, mais soumette toujours votre mise à jour. Utilisez les outils de développement Chrome/Firefox pour afficher les demandes/réponses.

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

Ensuite, modifier l'action de mise à jour dans le contrôleur de réponses pour charger la « réponse suivante non notée »:

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 

Ensuite, vous devrez créer app/vues/réponses/update.js.erb pour charger la nouvelle réponse à votre page avec la ligne suivante:

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

Il suffit d'aller et de créer une nouvelle partie qui affiche votre réponse et formulaire correctement pour la prochaine réponse non notée. Ou idéalement, chargez votre 'show.html.erb' initial avec les partiels pertinents et réutilisez-les.C'est la manière simple de le faire, mais si j'étais vous, je renommerais probablement ces nouvelles fonctions pour ne pas utiliser 'update' ou 'show' mais plutôt l'appeler quelque chose comme 'rate' et même 'rate_show' donc vous pouvez utiliser la mise à jour et l'afficher sous sa forme originale (pour mettre à jour et répondre ou afficher une réponse) si nécessaire plus tard dans votre projet.

+0

Parfait! Je vais essayer de l'essayer une fois que je nettoierai d'autres trucs aussi. J'aime l'idée d'être capable de parcourir les pages comme on soumet une note alors j'espère que ça va marcher! Merci encore. – Prkl8r

+0

OK, laissez-moi savoir comment ça se passe ... – hec

0

D'après ce que je comprends de votre question, je pense que vous seriez mieux regarder dans 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 %> 

précédentes vous donner ce que vous avez déjà (juste pour clarifier votre remarque « clairement fou » est pas le cas du tout!). .

-

Ce qui suit est l'endroit où les ressources sont imbriquées dans

À l'heure actuelle, il semble que vous avez un problème associant une réponse à une question:

:id est l'id de la réponse individuelle, donc pas ce que j'espère

Une solution pour cela est la suivante:

#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 

Cela va créer une nouvelle grade (que vous devriez avoir dans un modèle associé), pour cette réponse spécifique. Parce que la réponse a été associée à un question, il vous permettra d'utiliser les routes imbriquées pour charger les deux.

En ce qui concerne votre configuration, j'ajouterais personnellement un modèle Grade, de sorte que vous puissiez avoir plusieurs notes par réponse. Ceci est contre votre schéma actuel, mais fonctionne bien pour vous assurer d'avoir les fonctionnalités nécessaires pour faciliter plusieurs qualités:

#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 
+0

J'ai fait quelques-uns de vos changements suggérés. Je continue à courir dans un "undefined method' permis "pour" 1 ": String" erreur sur l'instruction params.require. Je ne peux pas comprendre. Le hash params, semble avoir toutes les informations nécessaires pour créer l'objet de qualité. J'ai également essayé de changer l'entrée de catégorie en un nombre comme je l'ai établi en tant qu'entier. – Prkl8r

+0

Paramètres: { "UTF8" => "✓", "_method" => "put", "authenticity_token" => "8UhJhKm9V6Mejxfm2uMpTPTP + 4eGhxzfwpgJyc9k9afOG61iy/BjLPwJJUeiFFNMXqBOS3 + 2axlno/fbWagq + A ==", « graded_by "=" "1", "answer_id" => "20", "grade" => "1", "commit" => "Submit Grade", "question_id" => "1", " id "=>" 20 "} – Prkl8r