2011-03-08 8 views
2

설명하기가 어렵지만 최선을 다할 것입니다 :컨트롤러 설계 (레일 3)

사용자가 코스를 수강 할 수있는 시스템을 구축 중입니다. 과정은 단계별로 이루어지며 순서대로 수행해야합니다. 시스템에서 6 단계 종류가 있습니다 (다운로드, 프리젠 테이션, 비디오, 텍스트, 퀴즈 및 설문 조사) 사용자가 현재 단계에 액세스

방법은 다음과 같습니다

http://example.com/courses/2/course_steps/1

당신이 course_steps을 말할 수 코스 아래에 중첩되어 있습니다. 다음은

코스 단계 쇼 방법 :

def show 
    render "show_#{@course_step.step.step_type.name.downcase}" 
end 

당신은 기본적으로 [TYPE] (퀴즈, 설문 조사, text..etc)

이 작품을 show_ 할 뷰를 선택합니다 말할 수 텍스트, 비디오 또는 다운로드와 같은 간단한 단계는 괜찮지 만 다음과 같은 이유로 퀴즈와 같은 복잡한 단계에서는이 모델이 제대로 작동하지 않습니다.

  • 퀴즈 또는 설문 조사는 내가 될거야 다른 컨트롤러 (QuizAttemptsController)를 부릅니다.
  • REST 교장을 퀴즈로 여는 것처럼 보입니다. 설문 조사는 별도로 처리해야합니다. (나는 그들이 단계 유형을 알고 있지만, 그들은 자신의 행동과 검증 할 수 있습니다)

단계 모델

class Step < ActiveRecord::Base 
    belongs_to :step_type 
    belongs_to :client 
    has_one :step_quiz, :dependent => :destroy 
    has_one :step_survey, :dependent => :destroy 
    has_one :step_text, :dependent => :destroy 
    has_one :step_download, :dependent => :destroy 
    has_one :step_video, :dependent => :destroy 
    has_one :step_presentation, :dependent => :destroy 
    has_many :course_steps, :dependent => :destroy 
    has_many :courses, :through => :course_steps 
    has_many :patient_course_steps, :dependent => :destroy 

    attr_accessible :step_type_id, :client_id, :title, :subtitle, :summary 

    validates :title, :presence=>true 
    validates :summary, :presence=>true 

    def getSpecificStepObject() 
    case self.step_type.name.downcase 
     when "text" 
     return StepText.find_by_step_id(self.id) 
     when "quiz" 
     return StepQuiz.find_by_step_id(self.id) 
     when "survey" 
     return StepSurvey.find_by_step_id(self.id) 
     when "download" 
     return StepDownload.find_by_step_id(self.id) 
     when "video" 
     return StepVideo.find_by_step_id(self.id) 
     when "presentation" 
     return StepPresentation.find_by_step_id(self.id) 
    end 
    end 
end 

단계 퀴즈 모델 :

class StepQuiz < ActiveRecord::Base 
    belongs_to :step, :dependent => :destroy 
    has_many :step_quiz_questions, :dependent => :destroy 
    has_many :quiz_attempts, :dependent => :destroy 

    accepts_nested_attributes_for :step 
    accepts_nested_attributes_for :step_quiz_questions, :allow_destroy => true 
    attr_accessible :step_id, :instructions, :step_attributes, :step_quiz_questions_attributes 
    validates :instructions, :presence=>true 
end 

CourseStep을 모델

class CourseStep < ActiveRecord::Base 
    belongs_to :step 
    belongs_to :course 

    validates_uniqueness_of :step_id, :scope => :course_id 

    def next_step() 
    Course.find(self.course.id).course_steps.order(:position).where("position >= ?", self.position).limit(1).offset(1).first 
    end 

    def previous_step() 
    Course.find(self.course.id).course_steps.order("position DESC").where("position <= ?", self.position).limit(1).offset(1).first 
    end 
end 

어떻게 수정 하시겠습니까? 당신이 원하는 무엇

답변

0

문제를 해결하는 한 가지 방법은 course_steps 컨트롤러에 "submit_quiz"멤버 동작을 추가하는 것입니다. 코드가보기 흉하게 보일 때 나는 이것을 좋아하는지 모르겠습니다. 나는 의견에 감사 할 것입니다.(참고 : 나는 캉캉 그렇게 @course_step가 course_steps_controller에서 자동적으로 만들어 사용하고 있는가) 내가 싫어하는

것들이다 :

  • show_quiz보기
  • submit_quiz가 거기에 코드를 많이 가지고 course_steps_controller에
  • quiz_attempt 모델 (검증을 위해) quiz_questions의 가상 속성

show_quiz.html.erb있다

<%= form_for (@quiz_attempt.blank? ? QuizAttempt.new(:started => Time.now.utc, :step_quiz_id => @course_step.step.step_quiz.id) : @quiz_attempt, :url => submit_quiz_course_course_step_path(@course_step.course, @course_step)) do |f| %> 
<%= render :partial => 'shared/error_messages', :object => f.object %> 
    <% @course_step.step.step_quiz.step_quiz_questions.each do |quiz_question| %> 
     <h3><%= quiz_question.value %></h3> 
     <% quiz_question.step_quiz_question_choices.each do |quiz_question_choice| %> 
     <%= radio_button_tag("quiz_attempt[quiz_questions][#{quiz_question.id}]", quiz_question_choice.value, f.object.get_quiz_question_choice(quiz_question.id) == quiz_question_choice.value)%> 
     <%= quiz_question_choice.value %><br /> 
     <% end %> 

    <% end %> 
    <%= f.hidden_field(:step_quiz_id)%> 
    <%= f.hidden_field(:started)%> 
    <%= submit_tag("Submit Quiz")%> 
<% end %> 

course_steps_controller.rb

def show 
    PatientCourseStep.viewed(current_user.id, params[:course_id], @course_step.step.id) 
    render "show_#{@course_step.step.step_type.name.downcase}" 
    end 

    def submit_quiz 
    @quiz_attempt = QuizAttempt.new(params[:quiz_attempt]) 

    if [email protected]_attempt.save() 
     render 'show_quiz' 
    end 
    end 

quiz_attempt.rb

class QuizAttempt < ActiveRecord::Base 
    belongs_to :step_quiz 
    belongs_to :patient 

    attr_accessor :quiz_questions 
    attr_accessible :step_quiz_id, :patient_id, :started, :ended, :correct, :incorrect, :quiz_questions 

    validate :answered_all_questions? 

    def get_quiz_question_choice(quiz_question_id) 
    unless self.quiz_questions.blank? 
     quiz_questions[quiz_question_id.to_s] 
    end 
    end 

    private 
    def answered_all_questions? 
     #Making sure they answered all the questions 
     if self.quiz_questions.blank? or self.quiz_questions.try(:keys).try(:count) != self.step_quiz.step_quiz_questions.count 
     errors.add_to_base "Not all questions were answered" 
    end 
    end 
end 


    def submit_quiz 
    @quiz_attempt = QuizAttempt.new(params[:quiz_attempt]) 

    if [email protected]_attempt.save() 
     render 'show_quiz' 
    end 
    end 
2

이 원하는 상태에 도달 할 때까지, 당신의 컨트롤러는 여러 단계가 일어날 수 있도록 상태에 따라 다른보기를 표시 할 수 Finite State Machine로 모델을 구현하고 지속적으로 new 또는 edit 조치를 다시로드합니다.