Rails 5控制器before_action方法没有收到表单参数
问题描述:
我有一个应用程序有一个场地模型,每个场地有很多事件,并且每个事件都有许多sign_ups(我有另一个模型也有sign ups)。我的问题是,当我尝试从场地页面创建注册特定活动时。这里是我的相关代码:Rails 5控制器before_action方法没有收到表单参数
型号:
# app/models/venue.rb
class Venue < ApplicationRecord
has_many :events, dependent: :destroy
end
# app/models/event.rb
class Event < ApplicationRecord
belongs_to :venue
has_many :sign_ups, as: :signupable
end
# app/models/sign_up.rb
class SignUp < ApplicationRecord
belongs_to :signupable, polymorphic: true
end
控制器:
#app/controllers.sign_ups_controller.rb
class SignUpsController < ApplicationController
before_action :find_signupable
def new
@sign_up = SignUp.new
end
def create
@sign_up = @signupable.sign_ups.new sign_up_params
if @sign_up.save
redirect_to :back
flash[:notice] = 'Your submission was received!'
else
redirect_to :back
flash[:danger] = "Error: #{@sign_up.errors.full_messages.to_sentence}"
end
end
private
def sign_up_params
params.require(:sign_up).permit(:first_name, :last_name, :phone, :email, :num_guys, :num_girls, :date)
end
def find_signupable
@signupable = Event.find(params[:event_id]) if params[:event_id]
@signupable = Event.find(params[:event]) if params[:event]
end
end
形式:
# app/views/venues/_sign_up_form.html.html
= form_for [@venue, SignUp.new] do |f|
.form-group
%label{ :for => "event" } Event ID
= f.select :event, options_from_collection_for_select(@venue.events, :id, :name), {:prompt => "Select Date"}, {class: "form-control", id: "event"}
.form-group
= f.submit "Submit", class: "form-control"
当我尝试提交我得到以下错误的形式:
NoMethodError at /venues/20/sign_ups
undefined method `sign_ups' for nil:NilClass
我很新的轨道,不知道我做错了什么。我猜find_signupable
没有得到params[:event]
。
答
从表格中的参数会象下面这样:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"(snip)", "sign_up"=>{"event"=>"2"}, "commit"=>"Submit", "venue_id"=>"1"}
正如你所说,find_signupable
是没有得到params[:event]
。所以一个事件的ID在params[:sign_up][:event]
。这将是找到正确的事件:
def find_signupable
# If you use Ruby 2.3 or above, you may do params.dig(:sign_up, :event) instead of this:
event_id = params[:sign_up] && params[:sign_up][:event]
@signupable = Event.find(event_id) if event_id
end
(注1)请注意你的例子在模板中使用@venue
,它在这样的new
动作来定义:
@venue = Venue.find(params[:venue_id])
(注2)此外,模板中的f.select :event
将引发NoMethodError,因为SignUp模型没有event
。所以我认为你必须将其更改为f.select :signupable_id
并在控制器中更改find_signupable
方法,如下所示:
def find_signupable
# If you use Ruby 2.3 or above, you may do params.dig(:sign_up, :signupable_id) instead of this:
signupable_id = params[:sign_up] && params[:sign_up][:signupable_id]
@signupable = Event.find(signupable_id) if signupable_id
end