How to handle data with two has_many associations - ruby-on-rails

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"}
Console output
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

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

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

Related

Rails: Unpermitted parameters: :authenticity_token, :order, :commit. after upgrade

I am upgrading a functional app from Ruby 1.8.7 Rails 3 to Ruby 3 Rails 7: quite a journey and I am almost finished. But I have an order process, which is not running after the upgrade and is difficult for me to debug. The order process consists in a multistep form, rendered through partials and a create function in my Order controller.
In the first step of the multistep form you have to input the shipping details. When trying to get to the next step, I get the following error message in the server log: Unpermitted parameters: :authenticity_token, :order, :commit. Context: ... etc and the note that all validations have failed is rendered in my website.
Started POST "/orders" for ::1 at 2022-02-22 17:24:01 +0100
Processing by OrdersController#create as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "order"=>{"email"=>"name#example.com", "phone_number"=>"1234567", "ship_to_first_name"=>"John", "ship_to_last_name"=>"Doe", "ship_to_address"=>"Pennsylvania Avenue 12", "ship_to_city"=>"Houston", "ship_to_postal_code"=>"12345", "land_id"=>"112", "shipping_service_id"=>"50"}, "commit"=>"Continue"}
Cart Load (0.3ms) SELECT `carts`.* FROM `carts` WHERE `carts`.`id` = 4 LIMIT 1
↳ app/controllers/application_controller.rb:66:in `initialize_cart'
Unpermitted parameters: :authenticity_token, :order, :commit. Context: {controller: OrdersController, action: create, request: #<ActionDispatch::Request:0x00007fee489e8e30>, params: {"authenticity_token"=>"[FILTERED]", "order"=>{"email"=>"name#example.com", "phone_number"=>"1234567", "ship_to_first_name"=>"John", "ship_to_last_name"=>"Doe", "ship_to_address"=>"Pennsylvania Avenue 12", "ship_to_city"=>"Houston", "ship_to_postal_code"=>"12345", "land_id"=>"112", "shipping_service_id"=>"50"}, "commit"=>"Continue", "controller"=>"orders", "action"=>"create"} }
CartItem Load (0.4ms) SELECT `cart_items`.* FROM `cart_items` WHERE `cart_items`.`cart_id` = 4
↳ app/models/cart.rb:86:in `inject'
....
This is the same process in the old app.
Started POST "/orders" for 127.0.0.1 at Tue Feb 22 10:02:12 +0100 2022
Processing by OrdersController#create as HTML
Parameters: {"authenticity_token"=>"sometoken", "order"=>{"email"=>"name#example.com", "ship_to_first_name"=>"John", "ship_to_address"=>"Pennsylvania Avenue 12", "ship_to_city"=>"Houston", "land_id"=>"112", "ship_to_last_name"=>"Doe", "ship_to_postal_code"=>"12345", "phone_number"=>"1234567", "shipping_service_id"=>"1"}, "commit"=>"Continue", "utf8"=>"✓"}
Cart Load (0.3ms) SELECT `carts`.* FROM `carts` WHERE `carts`.`id` = ? LIMIT 1 [["id", 6255]]
CartItem Load (0.8ms) SELECT `cart_items`.* FROM `cart_items` WHERE `cart_items`.`cart_id` = 6255
ActiveShippingHub Load (0.3ms) SELECT `active_shipping_hubs`.* FROM `active_shipping_hubs` LIMIT 1
(0.5ms) SELECT MAX(`cart_items`.`length`) AS max_id FROM `cart_items` WHERE `cart_items`.`cart_id` = 6255
(0.5ms) SELECT MAX(`cart_items`.`width`) AS max_id FROM `cart_items` WHERE `cart_items`.`cart_id` = 6255
Rendered shared/_error_messages.html.erb (0.1ms)
Land Load (0.6ms) SELECT `lands`.* FROM `lands` WHERE `lands`.`id` = 112 LIMIT 1
ShippingService Load (0.5ms) SELECT `shipping_services`.* FROM `shipping_services` WHERE `shipping_services`.`id` = 1 LIMIT 1
ProductVariant Load (0.3ms) SELECT `product_variants`.* FROM `product_variants` WHERE `product_variants`.`id` = 14 LIMIT 1
Image Load (0.3ms) SELECT `images`.* FROM `images` WHERE `images`.`id` = 174 LIMIT 1
Rendered orders/_paymentoptions_step.html.erb (10.6ms)
Rendered orders/new.html.erb within layouts/application (14.0ms)
Rendered layouts/_header.html.erb (0.1ms)
Rendered layouts/_footer.html.erb (0.5ms)
Completed 200 OK in 68ms (Views: 20.9ms | ActiveRecord: 26.9ms)
My Order create action starts with
def create
session[:order_params].deep_merge!(order_params) if params[:order]
#order = Order.new(session[:order_params])
#shipping_services = #cart.available_shipping_services.joins(:lands).where(lands: {id: #order.land_id})
#order.customer_ip = request.remote_ip
populate_order
#order.current_step = session[:order_step]
...
I have set the order_params in the same controller as strong params:
...
private
def order_params
params.permit(:bill_to_address, :bill_to_city, :bill_to_first_name, :bill_to_last_name, :bill_to_land, :bill_to_land_id, :bill_to_postal_code, :date_payment_reminder, :email, :EULA, :express_token, :land_id, :payment, :date_payment_reminder, :phone_number, :signupnewsletter, :ship_to_address, :ship_to_city, :ship_to_first_name, :ship_to_last_name, :ship_to_postal_code, :shipping_service, :shipping_service_id, :shipping_date, :tracking_number, :order_status, :order_status_id, :stripe_card_token, :TOS)
end
end
I am not sure why I get this error. The use of strong_parameters in newer versions of Rails or the way associations are now verified?
When I turn off all validations in my Order model I still get the same message in my logs, but get the message, that there were problems with the shipping_land, shipping_service and bill_to_land fields: three associations of my Order model.
The associations are set in my Order model as follows:
# Associations
belongs_to :bill_to_land, class_name: "Land", foreign_key: :bill_to_land_id
belongs_to :land, foreign_key: :land_id
belongs_to :order_status
belongs_to :shipping_service
The multistep form is set in orders/new.html.erb
<%= form_for #order do |f| %>
<%= render "#{#order.current_step}_step", :f => f %>
<%= f.submit "Continue" unless #order.payment_options_step? || #order.billing_step? || #order.creditcard_options_step? || #order.last_step? %>
In the multistep form I only gather data and kick this data between steps in the session. The order entry is created only after the final submit.
Why do I get this error message? How can I debug the order session? What data has been written to it...
I hope someone can put me into the right direction.
private
def order_params
params.require(:order).permit(:bill_to_address, :bill_to_city, :bill_to_first_name, :bill_to_last_name, :bill_to_land,
:bill_to_land_id, :bill_to_postal_code, :date_payment_reminder, :email, :EULA, :express_token, :land_id, :payment, :date_payment_reminder, :phone_number, :signupnewsletter, :ship_to_address, :ship_to_city, :ship_to_first_name, :ship_to_last_name, :ship_to_postal_code, :shipping_service, :shipping_service_id, :shipping_date, :tracking_number, :order_status, :order_status_id, :stripe_card_token, :TOS)
end
end

Rails action being called multiple times per request

I have a controller action that's being called three times per browser request. Any ideas? config/routes.rb and application_controller.rb are totally straightforward.
Code below,
config/routes.rb
Rails.application.routes.draw do
root 'tiles#index'
+
controllers/tiles_controller.rb
class TilesController < ApplicationController
def index
puts "this line prints three times in the console per request"
end
+
tiles/index.html.erb
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<div id="tiles">
<%= render "tile", tile: { type: "sam", id: "0" } %>
<%= render "tile", tile: { type: "inputs", id: "1" } %>
<%= render collection: #tiles, partial: "tile" %>
<%= render "tile", tile: { type: "social", id: "1000" } %>
</div>
+
This is the console log:
log/development.log
Started GET "/" for 127.0.0.1 at 2017-08-31 16:56:28 -0400
Processing by TilesController#index as HTML
Started GET "/" for 127.0.0.1 at 2017-08-31 16:56:28 -0400
Processing by TilesController#index as HTML
[1m[36mProject Load (0.5ms)[0m [1m[34mSELECT "projects".* FROM "projects" ORDER BY "projects"."launch_date" ASC LIMIT $1[0m [["LIMIT", 10]]
[1m[36mProject Load (9.1ms)[0m [1m[34mSELECT "projects".* FROM "projects" ORDER BY "projects"."launch_date" ASC LIMIT $1[0m [["LIMIT", 10]]
Rendering tiles/index.html.erb within layouts/application
Rendered tiles/_tile_sam.html.erb (0.3ms)
Rendered tiles/_tile.html.erb (8.0ms)
Rendering tiles/index.html.erb within layouts/application
Rendered tiles/_tile_sam.html.erb (0.0ms)
Rendered tiles/_tile.html.erb (0.9ms)
Rendered tiles/_tile_instagram.html.erb (12.6ms)
...
Rendered tiles/_tile_twitter.html.erb (0.5ms)
Rendered collection of tiles/_tile.html.erb [48 times] (125.9ms)
Rendered tiles/_tile_project.html.erb (0.1ms)
Rendered tiles/_tile_social.html.erb (0.6ms)
Rendered tiles/_tile.html.erb (2.7ms)
Rendered tiles/index.html.erb within layouts/application (166.1ms)
Rendered tiles/_tile_twitter.html.erb (0.6ms)
...
Rendered collection of tiles/_tile.html.erb [48 times] (158.5ms)
Rendered tiles/_tile_social.html.erb (0.1ms)
Rendered tiles/_tile.html.erb (1.0ms)
Rendered tiles/index.html.erb within layouts/application (165.3ms)
Completed 200 OK in 1310ms (Views: 217.1ms | ActiveRecord: 9.1ms)
Completed 200 OK in 1325ms (Views: 204.5ms | ActiveRecord: 0.5ms)
Help!
WOW
Finally figured this one out by removing code related to this action/view line by line. Basically, I was generating a few img tags with empty src fields. Apparently this causes many modern browsers to load a website several times, possibly in an attempt to find missing images or assuming the root URL is the image itself?
Found the behavior cited here:
https://forums.asp.net/t/1804472.aspx?Bizzare+safari+thing+two+page+loads+for+each+page+
page loads twice in Google chrome

How to create many single select inputs for a has_many association on simple form?

I've created a form using Simple Form in Rails to create new tests. My Test model has a has_and_belongs_to_many association with the Tool Model.
My code gets all tools and groups them into categories (a category is an attribute of a tool). It then creates a single select box for each category (as shown in the image).
- all_tools = Tool.all.group_by(&:category)
- all_tools.each do |category|
= f.association :tools,
collection: category.last,
label: category.first,
label_method: lambda { |tool| "#{tool.name} (#{tool.description})"},
input_html: { multiple: false }
Many select boxes
When choosing a tool from each select box and submitting the form, I get the following error:
found unpermitted parameter: tool_ids
and the there's only one id currently being submitted for the tool_ids instead of an array of ids which I need.
I know this works when the boxes are multiple selects but I only want the user to be able to select one tool from each category and have it submit all tool_ids in an array similar to the way it would if the user was selecting them from a multiple select box.
So my question is, how can I use multiple single select boxes to submit an array of tool_ids in Simple Form?
EDIT:
As requested, I've added the relevant code:
tests_controller:
def create
#test = Test.new(test_params)
#tools = Tool.all.select(:name).distinct
if #test.save
Activity.log(current_user, "Created test #{#test.id}")
redirect_to #test, notice: 'Test was successfully created.'
else
render :new, notice: 'Unable to save Test Details.'
end
end
private
# Only allow a trusted parameter "white list" through.
def test_params
params.require(:test).permit(
:date,
:start_time,
:description,
:machine,
:location,
:feeder_screw_diameter,
:notes,
:user_id,
:tool_ids => [],
:powder_ids => []
)
end
Log output when submitting:
Started POST "/tests" for 127.0.0.1 at 2016-05-08 13:24:52 +0100
Processing by TestsController#create as HTML
Parameters: {"utf8"=>"✓","authenticity_token"=>"WKw+tQ1WKyxW7XZWCDvbvShCKnZ7iMY597P8eDGIvZEyis4ks7Mf4Lcu4vCf7q+fwtsReocmAlMGUrrhI4SgdQ==",
"test"=>{"start_time(1i)"=>"2016",
"start_time(2i)"=>"5",
"start_time(3i)"=>"8",
"start_time(4i)"=>"13",
"start_time(5i)"=>"23",
"description"=>"Test",
"machine"=>"Some machine",
"location"=>"Some Place",
"feeder_screw_diameter"=>"15",
"tool_ids"=>"21",
"powder_ids"=>["", "3"],
"user_id"=>"1",
"date"=>"11-05-2016",
"notes"=>"Some Notes"},
"button"=>""}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Completed 500 Internal Server Error in 14ms (ActiveRecord: 0.4ms)
** [Airbrake] Notice was not sent due to configuration:
Environment Monitored? false
API key set? true
ActionController::UnpermittedParameters (found unpermitted parameter: tool_ids):
app/controllers/tests_controller.rb:201:in `test_params'
app/controllers/tests_controller.rb:70:in `create'
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/actionpack-4.2.5.1/lib/action_dispatch/middleware/templates/rescues/_source.erb (4.0ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/actionpack-4.2.5.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.7ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/actionpack-4.2.5.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.7ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/actionpack-4.2.5.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (12.9ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/web-console-2.2.1/lib/web_console/templates/_markup.html.erb (0.2ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/web-console-2.2.1/lib/web_console/templates/_inner_console_markup.html.erb within layouts/inlined_string (0.2ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/web-console-2.2.1/lib/web_console/templates/_prompt_box_markup.html.erb within layouts/inlined_string (0.2ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/web-console-2.2.1/lib/web_console/templates/style.css.erb within layouts/inlined_string (0.2ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/web-console-2.2.1/lib/web_console/templates/console.js.erb within layouts/javascript (7.9ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/web-console-2.2.1/lib/web_console/templates/main.js.erb within layouts/javascript (0.2ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/web-console-2.2.1/lib/web_console/templates/error_page.js.erb within layouts/javascript (0.2ms)
Rendered /home/me/.rvm/gems/ruby-2.1.7/gems/web-console-2.2.1/lib/web_console/templates/index.html.erb (16.1ms)
Many thanks for any help!

Ruby class 'split' not working

I'm trying to use the split class to split up an array. I keep getting this error:
MethodError (undefined method `split' for nil:NilClass):
This is what I'm trying to do:
def create
#listing.landlord = current_landlord
if #listing.save
photo_id_array = params[:images].split(/,/)
photo_id_array.each do |image|
#image = Photo.find_by_id("photo.id")
#image.listing_id = #listing.id
end
render :show, :status => 200
else
render :status => 403, :json => {:errors => #listing.errors}
end
end
I'm running Rails 3.2.9. Any ideas into what may be causing this?
Edit:
Here is the full post:
Started POST "/listings" for 127.0.0.1 at 2012-12-12 01:04:52 -0800
Processing by ListingsController#create as application/json; charset=utf-8
Parameters: {"listing"=>{"street_address"=>"123 main st", "city"=>"los angeles", "state"=>"ca", "availability"=>"12 Dec 2012", "price"=>"2000", "period"=>"2", "category"=>"1", "cats"=>"false", "dogs"=>"false", "square_footage"=>"0", "bedrooms"=>"3", "bathrooms"=>"2", "short_description"=>"tree-lined street", "long_description"=>"big yard", "images"=>["70621", "70622", "70620"]}, "auth_token"=>"6489Cn7KeTmejSxaWsws"}
WARNING: Can't verify CSRF token authenticity
User Load (1.6ms) SELECT "users".* FROM "users" WHERE "users"."authentication_token" = '6489Cn7KeTmejSxaWsws' LIMIT 1
Landlord Load (0.6ms) SELECT "landlords".* FROM "landlords" WHERE "landlords"."authentication_token" = '6489Cn7KeTmejSxaWsws' LIMIT 1
Role Load (0.5ms) SELECT "roles".* FROM "roles" WHERE "roles"."name" = 'admin' LIMIT 1
Role Exists (0.7ms) SELECT 1 AS one FROM "roles" INNER JOIN "landlords_roles" ON "roles"."id" = "landlords_roles"."role_id" WHERE "landlords_roles"."landlord_id" = 5867 AND "roles"."id" = 1 LIMIT 1
Completed 500 Internal Server Error in 275ms
NoMethodError (undefined method `split' for nil:NilClass):
app/controllers/listings_controller.rb:8:in `create'
Rendered /Users/rigelstpierre/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.9/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.9ms)
Rendered /Users/rigelstpierre/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.9/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (2.1ms)
Rendered /Users/rigelstpierre/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.9/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (16.9ms)
Use:
params[:listing][:images]
And it's already an Array, no need to split. You can directly do: params[:listing][:images].each.
params[:images] is nil, you're after params[:listing][:images] I assume.
Your params are structured like: "listing"=>{"images"=>["70621", "70622", "70620"]}.
Plus, you needn't split it, it's an array. Access each item of the array with: params[:listing][:images].each do |i|

Adding items to a cart redirecting wrong

I've been following this Railscast on implementing Active Merchant in a new test app and it was going well, but now that I'm trying to add what I made to my main app its breaking.
When clicking 'add to cart' on my test app, it redirects to the current cart and lists the item as expected.
On my main app clicking the add to cart link redirects to:
http://mainapp.dev/line_items?product_id=1
The line_items controller looks like this:
class LineItemsController < ApplicationController
def create
#product = Product.find(params[:product_id])
#line_item = LineItem.create!(:cart => current_cart, :product => #product, :quantity => 1, :unit_price => #product.price)
flash[:notice] = "Added #{#product.name} to cart."
redirect_to current_cart_url
end
end
The add to cart link looks like this:
<%= link_to "Add to Cart", line_items_path(:product_id => product), :method => :post, :class => "product_actions" %>
edit - logs
Test version on adding an item (working):
Started POST "/line_items?product_id=5" for 127.0.0.1 at 2011-09-01 07:33:27 +0100
Processing by LineItemsController#create as HTML
Parameters: {"authenticity_token"=>"li7gkjksc9MENevuGz7emDwnbB6HrvPAE3CY=", "product_id"=>"5"}
[1m[35mProduct Load (0.4ms)[0m SELECT `products`.* FROM `products` WHERE `products`.`id` = 5 LIMIT 1
[1m[36m (33.1ms)[0m [1mBEGIN[0m
[1m[35mSQL (179.4ms)[0m INSERT INTO `carts` (`created_at`, `purchased_at`, `updated_at`) VALUES ('2011-09-01 06:33:28', NULL, '2011-09-01 06:33:28')
[1m[36m (48.3ms)[0m [1mCOMMIT[0m
[1m[35m (0.2ms)[0m BEGIN
[1m[36mSQL (0.2ms)[0m [1mINSERT INTO `line_items` (`cart_id`, `created_at`, `product_id`, `quantity`, `unit_price`, `updated_at`) VALUES (29, '2011-09-01 06:33:29', 5, 1, 250, '2011-09-01 06:33:29')[0m
[1m[35m (0.5ms)[0m COMMIT
Redirected to http://sell.dev/cart
Completed 302 Found in 1265ms
Started GET "/cart" for 127.0.0.1 at 2011-09-01 07:33:29 +0100
Processing by CartsController#show as HTML
[1m[36mCart Load (0.2ms)[0m [1mSELECT `carts`.* FROM `carts` WHERE `carts`.`id` = 29 LIMIT 1[0m
[1m[35mLineItem Load (0.3ms)[0m SELECT `line_items`.* FROM `line_items` WHERE `line_items`.`cart_id` = 29
[1m[36mProduct Load (0.5ms)[0m [1mSELECT `products`.* FROM `products` WHERE `products`.`id` = 5 LIMIT 1[0m
Rendered carts/show.html.erb within layouts/application (202.1ms)
Rendered layouts/_header.html.erb (0.8ms)
Rendered layouts/_footer.html.erb (0.7ms)
Completed 200 OK in 368ms (Views: 284.2ms | ActiveRecord: 79.5ms)
The main app version:
Started GET "/line_items?product_id=1" for 127.0.0.1 at 2011-09-01 07:34:59 +0100
Processing by LineItemsController#index as HTML
Parameters: {"product_id"=>"1"}
Rendered line_items/index.html.erb within layouts/application (0.3ms)
Rendered layouts/_header.html.erb (1.3ms)
Rendered layouts/_footer.html.erb (178.4ms)
Completed 200 OK in 218ms (Views: 182.3ms | ActiveRecord: 35.5ms)
I can't figure out why it's wanting to redirect to the line items index and not create, the code is the same.
edit - routes
get "cart" => "carts#show", :as => "current_cart"
resources :orders
resources :line_items
resources :carts
resources :products
resources :order_transactions
edit - taken from my application controller
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def current_cart
if session[:cart_id]
#current_cart ||= Cart.find(session[:cart_id])
session[:cart_id] = nil if #current_cart.purchased_at
end
if session[:cart_id].nil?
#current_cart = Cart.create!
session[:cart_id] = #current_cart.id
end
#current_cart
end
Thanks for any help its much appreciated!
If you add an item to your cart by clicking on the link "Add to cart" then you will need to call the create action in the LineItemsController controller as you have it now.
The last line of that method is
redirect_to current_cart_url
So you are indeed redirecting to the current_cart as you want but you are saying you are not redirecting to the current cart which is nonsense really.
Perhaps you have not yet set up the current_cart_url path or views or something?
I'm am not clear on what your actual problem is
Started GET "/line_items?product_id=1" for 127.0.0.1 at 2011-09-01 07:34:59 +0100
Processing by LineItemsController#index as HTML
Parameters: {"product_id"=>"1"}
Rendered line_items/index.html.erb within layouts/application (0.3ms)
Rendered layouts/_header.html.erb (1.3ms)
Rendered layouts/_footer.html.erb (178.4ms)
Completed 200 OK in 218ms (Views: 182.3ms | ActiveRecord: 35.5ms)
There MUST be something happening after this! ~What is it?
edit - solution
Sorry, I totally missed the obvious.
<%= link_to "Add to Cart", line_items_path(:product_id => product), :method => :post, :class => "product_actions" %>
is issuing a get request NOT a post request as indicated by your log file Started GET "/cart" for 127.0.0.1 at 2011-09-01 07:33:29 +0100
You are adding an item to the cart which means you are changing state on the server which means you should be using a POST request NOT a get (link) request and therefore you should use a form (button_to will give you that form). Unless you want loads of bot's spiders;/crawlers etc... adding stuff to your cart you should use
<%= button_to 'Add to Cart', line_items_path(:product_id => product) %>

Resources