I'm currently trying to write functionality for my quiz webapp that allows a user who reconnects to continue where they left off (possible reasons for reconnect are: because they lost their connection, or because they logged out unintentionally, or because they refreshed the page).
So I googled and found the solution, that I could write the method "after_sign_in_path_for(resource)"
in the application_controller
, and whatever I put in that method would be executed by Devise after a user logs in.
This solution works perfectly for when I try to render a static page (or even one of many static pages, depending on the "phase" parameter I save to my db). But my app has 2 kinds of users:
- The "Teacher" who clicks links from static page to static page and
- the "Student", who has no control, but gets pushed new HTML whenever the Teacher clicks (pushed = HTML is received over ActionCable and replaces the current page)
So now what happens when a student logs in is this:
after_sign_in_path_for(resource)
is called: determines the user is a Student and calls- the
find_current_page
method in myquiz_session
model: which checks thephase
variable in my db and calls one of multiple methods on the serverside of my channel, e.g. resend_question_page
class method in myIndividualUpdateChannel
: this method builds the html and broadcasts it to the Student.
BUT: instead of receiving and displaying the sent HTML the Student gets "NoMethodError in Devise::SessionsController#create - undefined method `student_url' for #". In the logs it looks to me like 1., 2. and 3. are run, but then suddenly the app tries to redirect the Student somewhere? and fails.
Here is the console output: https://pastebin.com/FKmHF4qS
...
[ActionCable] Broadcasting to student_#3: {:phase=>1, :answers=>["<div class='student-layout'>The call returns immediately without </br>waiting for the I/O to complete.</div>", {"ids"=>[9, 10, 11, 12], "current_question_index"=>1}]}
Redirected to
Completed 500 Internal Server Error in 442ms (ActiveRecord: 103.6ms)
This is the full error message: And this is the rest of the trace: https://pastebin.com/psdyR2w2
And here is the code where the execution stops:
#app\channels\individual_update_channel.rb:
class IndividualUpdateChannel < ApplicationCable::Channel
...
def self.resend_question_page(student)
quiz_session = student.quiz_session
new_answer_html = AnswerButtonCreation.new(quiz_session).create
#This is where it stops
ActionCable.server.broadcast("student_##{student.id}", phase: 1, answers: new_answer_html)
end
I'm using Rails 5.0.2 and Ruby 2.3.3 with Devise 4.2.1 . This is my first Rails project, so please excuse if I got some best practices wrong. My googling of the inner workings of Devise didn't get me anywhere so I'd appreciate any help!
EDIT: This is my routes file:
Rails.application.routes.draw do
resources :given_answers
get 'students/set_quiz_session'
resources :given_answers
#change the sign_in and sign_out routes to /login and /logout
devise_for :users, path: '', path_names: { sign_in: 'login',
sign_out: 'logout'},
:controllers => {:registrations => 'registrations'}
resources :quiz_sessions, :answers, :questions, :quizzes, :courses
# Setup static pages
get 'teacher/quiz_start', to: 'pages#create_session', :as => :teacher_start_quiz
get 'teacher/quiz_question', to: 'pages#show_question', :as => :teacher_question
get 'teacher/quiz_question_result', to: 'pages#show_question_result', :as => :teacher_question_result
get 'teacher/quiz_result', to: 'pages#show_quiz_result', :as => :teacher_quiz_result
get 'teacher/home', to: 'pages#show', :role => "teacher", :page => "home", :as => :teacher_home
get 'student/quiz_start', to: 'pages#join_session', :as => :student_start_quiz
get 'student/home', :role => "student", :page => "home", :as => :student_home
get ':role/:page', to: 'pages#show'
root to: redirect('teacher/home'), :role => "teacher", :page => "home"
mount ActionCable.server => '/cable'
end