Rails 5控制器before_action方法没有接收形式参数

时间:2016-11-22 22:27:37

标签: ruby-on-rails rails-activerecord ruby-on-rails-5 form-helpers

我有一个具有Venue模型的应用程序,每个场地都有很多事件,每个事件都有许多sign_ups可注册(我还有另一个模型也有注册)。我的问题是当我尝试从场地页面创建特定事件的注册时。这是我的相关代码:

型号:

# 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

我对rails非常陌生,不确定我做错了什么。我猜find_signupable没有得到params[:event]

1 个答案:

答案 0 :(得分:0)

表格中的参数如下:

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