Reputation: 129
I'm new to Ruby on Rails. Just getting my head around modelling relationships and how to build CRUD with them. I'd like advice or suggestions on how to fix this problem.
In my system, a support user (student) has private support sessions (like classes) with their support worker (tutor). Here's how the system will be used: a support worker will log in, select a service user they work with, and record a support session, which includes things like how long the session lasted for and where it took place. Eventually, the system will produce time-sheets that can be used to invoice for the tutor's work in these private support sessions.
I'm not quite sure how to interact with this at a controller level. So far I've built my model and scaffolds - now I'm customising them.
I've been using the official tutorial to help me get started at: https://guides.rubyonrails.org/v3.2.8/getting_started.html but I think I've gone beyond that now.
# Models
# Not entirely sure inverse_of is appropriate but several tutorials suggested it's worth putting in
class ServiceUser < ApplicationRecord
has_many :support_sessions, inverse_of: :service_user
has_many :support_workers, through: :support_sessions
end
class SupportWorker < ApplicationRecord
has_many :support_sessions, inverse_of: :support_worker
has_many :service_users, through: :support_sessions
class SupportSession < ApplicationRecord
belongs_to :support_worker, inverse_of: :support_sessions
belongs_to :service_user, inverse_of: :support_sessions
end
# Controller
class SupportSessionsController < ApplicationController
# POST /support_sessions
# POST /support_sessions.json
def create
# Auto-generated line:
@support_session = SupportSession.new(support_session_params)
# Get service_user_id from query string
@service_user = ServiceUser.find(params[:service_user_id])
# Lifted from RoR 'Getting started' article
@support_session = @service_user.support_sessions.create(params[:service_user])
respond_to do |format|
if @support_session.save
#format.html { redirect_to @support_session, notice: 'Support session was successfully created.' }
format.html { redirect_to service_users_url, notice: 'Support session was successfully created.' }
format.json { render :show, status: :created, location: @support_session }
else
format.html { render :new }
format.json { render json: @support_session.errors, status: :unprocessable_entity }
end
end
end
end
# Service user view/HTML form
# This is rendered as a partial on the service user's show.html.erb view
# select_support_workers() helper retrieves a list of ALL support workers in the system and the control value is the support_worker_id
<%= form_for([@service_user, @service_user.support_sessions.build]) do |f| %>
<tr>
<td>
<%= select_support_workers(f) %>
</td>
<td>
<%= f.text_field :location %>
</td>
<td>
<%= f.text_field :mode_of_delivery %>
</td>
<td>
<%= f.text_field :started_at %>
</td>
<td>
<%= f.text_field :ended_at %>
</td>
<td>
<%= f.text_field :total_breaks %>
</td>
<td>
<%= f.submit 'Save session' %>
</td>
</tr>
<% end %>
When I submit the form (which is being rendered as a partial on the service_user view show page), I seem to be ending up in the 'else' part of the if @support_session.save logic.
Error shown in my web browser is:
NameError in SupportSessions#create
Showing /Users/chris/git-local/timesheets/app/views/support_sessions/new.html.erb where line #5 raised:
undefined local variable or method `support_sessions_path' for #<#<Class:0x00007feb3412d028>:0x00007feb34163268>
Did you mean? @support_session
Extracted source (around line #5):
3 <%= render 'form', support_session: @support_session %>
4
5 <%= link_to 'Back', support_sessions_path %>
Rails.root: /Users/chris/git-local/timesheets
Application Trace | Framework Trace | Full Trace
app/views/support_sessions/new.html.erb:5:in `_app_views_support_sessions_new_html_erb__485411543567831194_70324083953220'
app/controllers/support_sessions_controller.rb:46:in `block (2 levels) in create'
app/controllers/support_sessions_controller.rb:40:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"/xd16JX3LBjA7+9DVfnHwnJziucJkaICaWg/Sd6TK2rDOrugMcZu0r5qr6SO0TfqvXzzhBqvkydMIQqXp2NtrQ==",
"support_session"=>{"support_worker_id"=>"3", "location"=>"", "mode_of_delivery"=>"", "started_at"=>"", "ended_at"=>"", "total_breaks"=>""},
"commit"=>"Save session",
"service_user_id"=>"1"}
Started GET "/service_users/" for ::1 at 2019-05-31 07:58:29 +0100
(0.5ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
↳ /Users/chris/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Processing by ServiceUsersController#index as HTML
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:29 +0100
Rendering service_users/index.html.erb within layouts/application
(0.6ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
↳ /Users/chris/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
ServiceUser Load (0.7ms) SELECT `service_users`.* FROM `service_users`
Processing by ServiceUsersController#show as HTML
↳ app/views/service_users/index.html.erb:22
Parameters: {"id"=>"4"}
Rendered service_users/index.html.erb within layouts/application (7.6ms)
ServiceUser Load (2.4ms) SELECT `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
↳ app/controllers/service_users_controller.rb:69
Rendering service_users/show.html.erb within layouts/application
SupportSession Load (0.9ms) SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
↳ app/views/service_users/show.html.erb:18
Rendered collection of templates [0 times] (0.0ms)
SupportWorker Load (1.2ms) SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
↳ app/helpers/support_sessions_helper.rb:15
Rendered support_sessions/_form.html.erb (7.5ms)
Rendered service_users/show.html.erb within layouts/application (15.6ms)
Completed 200 OK in 94ms (Views: 91.2ms | ActiveRecord: 0.7ms)
Completed 200 OK in 115ms (Views: 105.7ms | ActiveRecord: 4.5ms)
Started GET "/service_users/" for ::1 at 2019-05-31 07:58:30 +0100
Processing by ServiceUsersController#index as HTML
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:30 +0100
Rendering service_users/index.html.erb within layouts/application
Processing by ServiceUsersController#show as HTML
ServiceUser Load (1.5ms) SELECT `service_users`.* FROM `service_users`
Parameters: {"id"=>"4"}
↳ app/views/service_users/index.html.erb:22
Rendered service_users/index.html.erb within layouts/application (5.9ms)
ServiceUser Load (2.2ms) SELECT `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
↳ app/controllers/service_users_controller.rb:69
Rendering service_users/show.html.erb within layouts/application
SupportSession Load (0.8ms) SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
↳ app/views/service_users/show.html.erb:18
Rendered collection of templates [0 times] (0.0ms)
SupportWorker Load (1.3ms) SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
↳ app/helpers/support_sessions_helper.rb:15
Rendered support_sessions/_form.html.erb (5.5ms)
Rendered service_users/show.html.erb within layouts/application (12.1ms)
Completed 200 OK in 126ms (Views: 122.0ms | ActiveRecord: 1.5ms)
Completed 200 OK in 108ms (Views: 100.0ms | ActiveRecord: 4.3ms)
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:34 +0100
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:34 +0100
Processing by ServiceUsersController#show as HTML
Parameters: {"id"=>"4"}
Processing by ServiceUsersController#show as HTML
Parameters: {"id"=>"4"}
ServiceUser Load (1.3ms) SELECT `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
↳ app/controllers/service_users_controller.rb:69
ServiceUser Load (1.5ms) SELECT `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
↳ app/controllers/service_users_controller.rb:69
Rendering service_users/show.html.erb within layouts/application
Rendering service_users/show.html.erb within layouts/application
SupportSession Load (1.5ms) SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
↳ app/views/service_users/show.html.erb:18
SupportSession Load (0.7ms) SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
Rendered collection of templates [0 times] (0.0ms)
↳ app/views/service_users/show.html.erb:18
Rendered collection of templates [0 times] (0.0ms)
SupportWorker Load (1.4ms) SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
↳ app/helpers/support_sessions_helper.rb:15
SupportWorker Load (0.7ms) SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
↳ app/helpers/support_sessions_helper.rb:15
Rendered support_sessions/_form.html.erb (5.7ms)
Rendered service_users/show.html.erb within layouts/application (11.7ms)
Rendered support_sessions/_form.html.erb (5.8ms)
Rendered service_users/show.html.erb within layouts/application (12.6ms)
Completed 200 OK in 80ms (Views: 71.4ms | ActiveRecord: 4.2ms)
Completed 200 OK in 82ms (Views: 74.2ms | ActiveRecord: 2.9ms)
Started POST "/service_users/4/support_sessions" for ::1 at 2019-05-31 07:58:35 +0100
Processing by SupportSessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"KZGBtom/9t6vYu5FyPRq3xA3Xmb6hkzG8LEA7c/qmOkUZGmtslduK+l2as5chNz7w4ikC+5fHRYh3Ak2IZwIvA==", "support_session"=>{"support_worker_id"=>"3", "location"=>"", "mode_of_delivery"=>"", "started_at"=>"", "ended_at"=>"", "total_breaks"=>""}, "commit"=>"Save session", "service_user_id"=>"4"}
ServiceUser Load (0.5ms) SELECT `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
↳ app/controllers/support_sessions_controller.rb:33
(0.3ms) BEGIN
↳ app/controllers/support_sessions_controller.rb:36
(0.3ms) ROLLBACK
↳ app/controllers/support_sessions_controller.rb:36
(0.2ms) BEGIN
↳ app/controllers/support_sessions_controller.rb:41
(0.2ms) ROLLBACK
↳ app/controllers/support_sessions_controller.rb:41
Rendering support_sessions/new.html.erb within layouts/application
SupportWorker Load (0.5ms) SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
↳ app/helpers/support_sessions_helper.rb:15
Rendered support_sessions/_form.html.erb (3.9ms)
Rendered support_sessions/new.html.erb within layouts/application (324.5ms)
Completed 500 Internal Server Error in 336ms (ActiveRecord: 2.0ms)
ActionView::Template::Error (undefined local variable or method `support_sessions_path' for #<#<Class:0x00007ffb0925c658>:0x00007ffb083fa100>
Did you mean? @support_session):
2:
3: <%= render 'form', support_session: @support_session %>
4:
5: <%= link_to 'Back', support_sessions_path %>
app/views/support_sessions/new.html.erb:5:in `_app_views_support_sessions_new_html_erb___2840892112036112501_70358075950960'
app/controllers/support_sessions_controller.rb:46:in `block (2 levels) in create'
app/controllers/support_sessions_controller.rb:40:in `create'
# Crebs:timesheets chris$ rake routes -c support_session
Prefix Verb URI Pattern Controller#Action
service_user_support_sessions GET /service_users/:service_user_id/support_sessions(.:format) support_sessions#index
POST /service_users/:service_user_id/support_sessions(.:format) support_sessions#create
new_service_user_support_session GET /service_users/:service_user_id/support_sessions/new(.:format) support_sessions#new
edit_service_user_support_session GET /service_users/:service_user_id/support_sessions/:id/edit(.:format) support_sessions#edit
service_user_support_session GET /service_users/:service_user_id/support_sessions/:id(.:format) support_sessions#show
PATCH /service_users/:service_user_id/support_sessions/:id(.:format) support_sessions#update
PUT /service_users/:service_user_id/support_sessions/:id(.:format) support_sessions#update
DELETE /service_users/:service_user_id/support_sessions/:id(.:format) support_sessions#destroy
Upvotes: 3
Views: 69
Reputation: 129
Here's the code that got things working. Doesn't seem to work very well with validation but the data submits.
def create
#render plain: params[:support_session].inspect
# Auto-generated line:
#@support_session = SupportSession.new(support_session_params)
# Get service_user_id from query string
# This is so each new record submitted can get the id of the service_user in question
@service_user = ServiceUser.find(params[:service_user_id])
# Copied from RoR 'Getting started' article: https://guides.rubyonrails.org/getting_started.html
# This calls the create method on @service_user.support_session (rather than @service_user alone)
# so the link is made between the service_user and the support_session
# Calls private method below to safeguard input parameters (only permitted ones)
@support_session = @service_user.support_sessions.create(support_session_params)
#redirect_to service_user_path(@service_user)
respond_to do |format|
if @support_session.save
#if @support_session
#if @service_user.support_sessions.create(support_session_params)
#if @service_user.support_sessions.new(support_session_params)
#format.html { redirect_to @support_session, notice: 'Support session was successfully created.' }
format.html { redirect_to @service_user, notice: 'Support session was successfully created.' }
format.json { render :show, status: :created, location: @support_session }
else
#format.html { render :show }
format.html { redirect_to service_user_path(@service_user), notice: 'There was an error!' }
format.json { render json: @support_session.errors, status: :unprocessable_entity }
end
end
end
Upvotes: 0
Reputation: 643
You have nested routes for support_sessions
resource, so instead of
<%= link_to 'Back', support_sessions_path %>
you should use code like this to build correct path:
<%= link_to 'Back', [@service_user, :support_sessions] %>
or maybe like this one:
<%= link_to 'Back', service_user_support_sessions_path(@service_user) %>
Upvotes: 2