Rails - Where should this code go to stay true to

2019-08-26 20:37发布

问题:

I'm new to Rails, and working my way through a couple of books, coding small test projects as I go. My latest dev app is a question and answer program. The idea is to have a database table full of questions. A user will bring up the web app and be presented with the first question. User enters answer into a form, and if it is correct, he gets the next question. Pretty simple.

So, I've used generate scaffold to create a questions table and a users table. This works well - I can navigate to the system-generated views to add/edit/delete questions and users.

I then created a new controller called gateway. I made this my root controller and gave it an index method. The index method takes in a user ID as a URL parameter and fetches the appropriate question for the user. It then loads a view which displays the question and has a form where the user enters the answer.

I'm now programming the logic to test the answer - I was doing this in a new method called "test_answer" in the gateway controller, but I feel like I'm now breaking MVC design, since this code is not directly related to displaying a view. I'm a bit confused as to where I should put code like this (the method tests the answer, if correct increments the user's level, if wrong redirects to an error page)

Should it go in an existing model (user or question)? Should it stay in the gateway controller? Should I create a new file in /lib?

I get the general concept of MVC (views display info, models store and manipulate data, controllers handle interactions between the two) but I'm not sure how this code fits in.

Thanks!

For reference, here is my current gateway.rb controller - please, pick it apart! I'm sure there are a number of questionable bits in there...

class GatewayController < ApplicationController
  def index
    if params[:uid]
      @user = User.where(:uid => params[:uid]).first
    else
      @user = User.where(:uid => "000").first
    end  
    @question = Question.where(:question_number => @user.current_level).first
    session[:uid] = @user.uid
    session[:answer] = @question.answer_text
  end

# POST /gateway/answer
# POST /gateway/answer.xml
  def answer
    #below is code I feel shouldn't be here...the logic to test the answer and then increment user's level
    if (params[:user_answer]) == session[:answer]
      @user = User.where(:uid => session[:uid]).first
      @user.increment!(:current_level)
      respond_to do |format|
        #code here will redirect to "Correct answer" page
      end
    else
      respond_to do |format|    
        #code here will redirect to "Wrong answer" page
      end
    end
  end
end

回答1:

I would put that test_answer in your model because it is concerning the data. This will return a boolean value in which the controller will then compare on, to determine whether or not to redirect to an error page.

Semi Pseudo Code:

class Question
  def test_answer(arg)
    if answer_is_right
      user.incr_level
    else
      false
    end
  end
end

class GatewayController < ApplicationController
  #code

  def answer
    if !question.test_answer(param)
      redirect_to error_page_path
    end

  end
end