我有一个资源PracticeQuiz
,它有一个名为PracticeQuestion
的嵌套子。我可以成功创建它们,并且可以转到下一个问题,但我想要的是当用户进行测验时,“上一个”和“下一个”按钮应该只显示父ID中的问题。
例如:
foo.com/practice_quizzes/mountains/practice_questions/1-11,24,25
用户应该可以从问题1-11开始,然后在11处应该转到24,如果用户想要回到11,一旦他们得到问题24,在问题25,它应该不显示按钮或说没有其他问题了。
foo.com/practice_quizzes/fruits/practice_questions/12-23,26,27,31
foo.com/practice_quizzes/animals/practice_questions/28-29,30,32
(请注意,这是关于测验中的问题数量,因为将来会删除或更新或更改问题。我不想基于排序ID,除非这是一个坏主意,我不知道为什么)
我需要的是让用户能够通过单击上一个或下一个来浏览show.html.erb页面,并且只显示与测验相关的问题,无论他们的ID是什么,以及应用程序是当它检测到第一个或最后一个没有问题,或者是否添加了新问题时,不会崩溃。
这是我到目前为止所尝试的:
意见/ practice_question.show.html.erb
<%= link_to 'next', practice_quiz_practice_question_path(@practice_quiz, @practice_question.next) %>
车型/ practice_question.rb
class PracticeQuestion < ApplicationRecord
belongs_to :user, optional: true
belongs_to :practice_quiz
def previous
PracticeQuestion.where("practice_quiz_id = ? AND id < ?", self.practice_quiz.id, self.id).first
end
def next
PracticeQuestion.where("practice_quiz_id = ? AND id > ?", self.practice_quiz.id, self.id).first
end
end
车型/ practice_quiz.rb
class PracticeAnswer < ApplicationRecord
belongs_to :practice_question
end
控制器/ practice_questions_controller.rb
class PracticeQuestionsController < ApplicationController
before_action :authenticate_user!
before_action :set_practice_quiz, only: [:show, :edit, :update, :destroy]
before_action :set_practice_question, only: [:show, :edit, :update, :destroy]
def index
if params[:practice_quiz_id]
@practice_questions = PracticeQuiz.friendly.find(params[:practice_quiz_id]).practice_questions
else
@practice_questions = PracticeQuestion.all
end
@all_practice_questions = PracticeQuestion.all
end
def show
@current_practice_question = PracticeQuestion.find(params[:id])
end
def new
@practice_quiz = PracticeQuiz.friendly.find(params[:practice_quiz_id])
@practice_question = PracticeQuestion.new
end
def edit
end
def create
@practice_quiz = PracticeQuiz.friendly.find(params[:practice_quiz_id])
@practice_question = @practice_quiz.practice_questions.build(practice_question_params)
@practice_question.user = current_user
respond_to do |format|
if @practice_question.save
format.html { redirect_to [@practice_quiz, @practice_question], notice: 'Practice question was successfully created.' }
format.json { render :show, status: :created, location: @practice_question }
else
format.html { render :new }
format.json { render json: @practice_question.errors, status: :unprocessable_entity }
end
end
end
private
def set_practice_question
@practice_question = PracticeQuestion.find(params[:id])
end
def set_practice_quiz
@practice_quiz = PracticeQuiz.friendly.find(params[:practice_quiz_id])
end
def practice_question_params
params.require(:practice_question).permit(:question, :explanation, :flagged, practice_questions_attributes: [:answer])
end
end
如何在practice_questions之前/之后执行只显示与其父级id相关的问题?并避免任何错误/陷阱,如达到测验的第一个或最后一个问题?
首先十分感谢 :)
P.S - 有些人说,就控制器/模型/视图而言,这不是一个嵌套资源,但是在我的routes.rb中我这样做了,那么这不是使它成为嵌套资源吗?
resources :practice_quizzes do
resources :practice_questions
end
我想象两个选择:
您可以使用测验控制器中的索引获取此测验的所有问题,并使用分页在索引视图中显示它们。如果您将分页设置为每页1个项目,则可以获得您想要的内容。
PracticeQuizzesController
def show
@quiz = PracticeQuizz.find_by(id: params[:id])
@questions = @quiz.practice_questions.paginate(:page => params[:page], :per_page => 1)
end
视图/ practice_quizzes / show.html.erb
<%= @quiz.name %>
<%= @quiz.description %>
<%= will_paginate @questions %>
<%= render @questions %>
视图/ practice_questions / _practice_question.html.erb
<%= practice_question.text %>
etc...
第二种选择
在问题的show方法中,获取下一个和上一个问题,以在show视图中显示
练习题控制器
def show
@question = PracticeQuestion.find_by(id: params[:id])
@next = @question.practice_quizz.practice_questions.where("id > ?", @question.id).order("id").first
@prev = @question.practice_quizz.practice_questions.where("id < ?", @question.id).order("id desc").first
end
视图/ practice_questions / show.html.erb
<% if @next %>
<%= link_to 'next', practice_quiz_practice_question_path(@practice_quiz, @next) %>
<% end %>