Разработка приложения контроллера (Rails 3) - PullRequest
2 голосов
/ 09 марта 2011

Это сложно объяснить, но я сделаю все возможное:

Я строю систему, где пользователь может проходить курсы.Курсы состоят из шагов, которые должны быть выполнены по порядку.В системе существует 6 типов шагов (загрузка, презентация, видео, текст, викторина и опрос)

Способ доступа пользователя к STEP в настоящее время:

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

Как вы можете сказать, курсовые шаги вложены в курсы.

Ниже приведен метод show в шагах курса:

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

Как вы можете сказать, он в основном выбирает представление для show_ [TYPE] (викторина, опрос, текст ... и т. д.)

Это прекрасно работает для простых шагов, таких как текст, видео или загрузка, но для сложных шагов, таких как викторина, эта модель не работает дляследующие причины:

  • Как проверить форму для опроса или опроса, как если бы я использовал другой контроллер (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

Как бы вы предложили это исправить?

Ответы [ 2 ]

2 голосов
/ 09 марта 2011

То, что вы хотите сделать, это реализовать вашу модель как Finite State Machine и постоянно перезагружать действие new или edit, пока не будет достигнуто желаемое состояние, тогда ваш контроллер может отображать различные представления в зависимости отв состоянии, чтобы можно было выполнить несколько шагов.

0 голосов
/ 11 марта 2011

Один из способов решить эту проблему - добавить действие члена "submit_quiz" в контроллер course_steps.Я не уверен, нравится ли мне это, так как код выглядит некрасиво.Я был бы признателен за отзыв. (Примечание: я использую CanCan, поэтому @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 !@quiz_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 !@quiz_attempt.save()
      render 'show_quiz'
    end
  end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...