Как обрабатывать данные с двумя ассоциациями has_many - PullRequest
3 голосов
/ 31 мая 2019

Я новичок в Ruby on Rails. Просто разбираюсь в модельных отношениях и в том, как строить CRUD с ними. Мне нужны советы или предложения по устранению этой проблемы.

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

Я не совсем уверен, как взаимодействовать с этим на уровне контроллера. Пока что я построил свою модель и строительные леса - теперь я настраиваю их.

Я использовал официальный учебник, чтобы помочь мне начать: https://guides.rubyonrails.org/v3.2.8/getting_started.html, но я думаю, что теперь я вышел за рамки этого.

# 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 %>

Когда я отправляю форму (которая отображается как часть на странице представления представления service_user), я, похоже, попадаю в часть 'else' логики if @ support_session.save.

Ошибка, отображаемая в моем веб-браузере:

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

Ответы [ 2 ]

2 голосов
/ 31 мая 2019

У вас есть вложенные маршруты для ресурса support_sessions, поэтому вместо

<%= link_to 'Back', support_sessions_path %>

вы должны использовать такой код для построения правильного пути:

<%= link_to 'Back', [@service_user, :support_sessions] %>

или, может быть, вот так:

<%= link_to 'Back', service_user_support_sessions_path(@service_user) %>
0 голосов
/ 01 июня 2019

Вот код, который заставил все работать.Кажется, не очень хорошо работает с проверкой, но данные отправляются.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...