嵌套表单创建问题 - ActionController::UrlGenerationError in Calls#new

Issue with Nested Form Create - ActionController::UrlGenerationError in Calls#new

嘿,我正在 Rails 4 Ruby 2 中构建应用程序。

我最近在我的呼叫显示页面的一侧嵌套了一个表单,我添加了 Ping(更新)功能。

因为我完成了嵌套...我可以在显示字段中看到 Ping 创建新 Ping 的按钮有效,但是我已经失去了一起创建新呼叫的能力。

我得到的错误是:

ActionController::UrlGenerationError in Calls#new
Showing /Users/TaurenLTD1/Desktop/TaurenLabs/PatrolProCAD/PatProCadApp/app/views/calls/_form.html.erb where line #459 raised:

No route matches {:action=>"new", :call_id=>nil, :controller=>"calls/pings"} missing required keys: [:call_id]
Extracted source (around line #459):
457
458
459
460
461
462

    </div>
    <div class="panel panel-info" id="update-pnl">
    <div class="panel-heading" id="update-top"><center><h4><strong id="update-txt">Live Updates - Found In View Call</strong> <%= link_to "Add Update", new_call_ping_path(@call), class: 'btn btn-primary btn-sm', :id => 'add-update' %> </h4></center></div>
    </div>
  <div class="new-wrapper">
    <div class="panel panel-warning" id="location-box">

Trace of template inclusion: app/views/calls/new.html.erb

我的路线rb文件:

Rails.application.routes.draw do

  devise_for :users, controllers: { registrations: 'registrations' }

  devise_scope :user do
    authenticated :user do
      root 'calls#index', as: :authenticated_root
    end

    unauthenticated do
      root 'devise/sessions#new', as: :unauthenticated_root
    end
  end

  resources :sites

  resources :calls do 
    resources :pings, except: [:index], controller: 'calls/pings'

    collection do
      get 'history'
    end

    member do
      patch :update_unit_on_scene
      patch :update_unit_clear
      patch :update_unit2_os
      patch :update_unit2_cl
      patch :update_unit3_os
      patch :update_unit3_cl
      patch :update_unit4_os
      patch :update_unit4_cl
    end
  end

end

我的 calls/pings 控制器:(通过 shot.html.erb 页面访问的更新表单)

class Calls::PingsController < ApplicationController
  before_action :set_ping, only: [:show, :edit, :update, :destroy]

  # GET /pings
  # GET /pings.json
  def index
    @pings = Ping.all
  end

  # GET /pings/1
  # GET /pings/1.json
  def show

  end

  # GET /pings/new
  def new
    @call = Call.find(params[:call_id])
    @ping = Ping.new
  end

  # GET /pings/1/edit
  def edit

  end

  # POST /pings
  # POST /pings.json
  def create
    @call = Call.find(params[:call_id])
    @ping = Ping.new(ping_params)
    @ping.call = @call

    respond_to do |format|
      if @ping.save
        format.html { redirect_to @call, notice: 'Call update has been successfully added to call.' }
        format.json { render :show, status: :created, location: @call }
      else
        format.html { render :new }
        format.json { render json: @call.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /pings/1
  # PATCH/PUT /pings/1.json
  def update
    respond_to do |format|
      if @ping.update(ping_params)
        format.html { redirect_to @ping, notice: 'Ping was successfully updated.' }
        format.json { render :show, status: :ok, location: @ping }
      else
        format.html { render :edit }
        format.json { render json: @ping.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /pings/1
  # DELETE /pings/1.json
  def destroy
    @ping.destroy
    respond_to do |format|
      format.html { redirect_to pings_url, notice: 'Ping was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_ping
      @ping = Ping.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def ping_params
      params.require(:ping).permit(:priority, :msg, :received, :call_id)
    end
end

这是我的呼叫控制器(原始形式)

class CallsController < ApplicationController
  before_action :set_call, only: [:show, :edit, :update, :destroy]

  # GET /calls
  # GET /calls.json
  def index
    @calls = Call.all
    @active_calls = @calls.select{|x| x.status == 'ACTIVE'}
    @pending_calls = @calls.select{|x| x.status == 'PENDING'}
    @clear_calls = @calls.select{|x| x.status == 'CLEAR'}
    @approved_calls = @calls.select{|x| x.status == "APPROVED"}
    @on_scene = @calls.select{|x| x.status == "ACTIVE"}
  end

  # GET /calls/1
  # GET /calls/1.json
  def show
    @unit_2 = @call.unit_2
    @unit_3 = @call.unit_3
    @unit_4 = @call.unit_4

    @call = Call.find(params[:id])
    @pings = @call.pings
  end

  # GET /calls/new
  def new
    @call = Call.new

    @unit_2 = @call.unit_2
    @unit_3 = @call.unit_3
    @unit_4 = @call.unit_4

    @pings = @call.pings
  end

  # GET /calls/1/edit
  def edit
    @call = Call.find(params[:id])
  end

  # POST /calls
  # POST /calls.json
  def create
    @call = Call.new(call_params)

    @call = Call.find(params[:call_id])
    @ping = Ping.new(ping_params)
    @ping.call = @call


    respond_to do |format|
      if @call.save
        format.html { redirect_to @call, notice: 'Call was successfully created.' }
        format.json { render :show, status: :created, location: @call }
      else
        format.html { render :new }
        format.json { render json: @call.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /calls/1
  # PATCH/PUT /calls/1.json
  def update
    respond_to do |format|
      if @call.update(call_params)
        format.html { redirect_to @call, notice: 'Call was successfully updated.' }
        format.json { render :show, status: :ok, location: @call }
      else
        format.html { render :edit }
        format.json { render json: @call.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /calls/1
  # DELETE /calls/1.json
  def destroy
    @call.destroy
    respond_to do |format|
      format.html { redirect_to calls_url, notice: 'Call was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

### Custom View for Call History
  def history
    @approved_calls = Call.where(status: 'APPROVED')
  end

### Custom Calls for Unit 1-4 On Scene and Call Buttons ###
  def update_unit_on_scene
    @call = Call.find(params[:id])
    @call.unit_on_scene = DateTime.now
    @call.status = "ACTIVE"
    @call.save

    respond_to do |format|
      if @call.save
        format.html { redirect_to @call, notice: "On Scene Time Successfully Updated. - You Are Now Logged Out Of Service" }
      else
        format.html { render action: 'edit' }
      end
    end
  end

  def update_unit_clear
    @call = Call.find(params[:id])
    @call.unit_clear = DateTime.now
    @call.status = "CLEAR"
    @call.save

    respond_to do |format|
      if @call.save
        format.html { redirect_to @call, notice: "Scene Clear Time Successfully Updated. - You Are Now Logged In Service" }
      else
        format.html { render action: 'edit' }
      end
    end
  end

  def update_unit2_os
    @call = Call.find(params[:id])
    @call.unit2_os = DateTime.now
    @call.save

    respond_to do |format|
      if @call.save
        format.html { redirect_to @call, notice: "On Scene Time Successfully Updated. - You Are Now Logged Out Of Service" }
      else
        format.html { render action: 'edit' }
      end
    end
  end

  def update_unit2_cl
    @call = Call.find(params[:id])
    @call.unit2_cl = DateTime.now
    @call.save

    respond_to do |format|
      if @call.save
        format.html { redirect_to @call, notice: "Scene Clear Time Successfully Updated. - You Are Now Logged In Service" }
      else
        format.html { render action: 'edit' }
      end
    end
  end

  def update_unit3_os
    @call = Call.find(params[:id])
    @call.unit3_os = DateTime.now
    @call.save

    respond_to do |format|
      if @call.save
        format.html { redirect_to @call, notice: "On Scene Time Successfully Updated. - You Are Now Logged Out Of Service" }
      else
        format.html { render action: 'edit' }
      end
    end
  end

  def update_unit3_cl
    @call = Call.find(params[:id])
    @call.unit3_cl = DateTime.now
    @call.save

    respond_to do |format|
      if @call.save
        format.html { redirect_to @call, notice: "Scene Clear Time Successfully Updated. - You Are Now Logged In Service" }
      else
        format.html { render action: 'edit' }
      end
    end
  end

  def update_unit4_os
    @call = Call.find(params[:id])
    @call.unit4_os = DateTime.now
    @call.save

    respond_to do |format|
      if @call.save
        format.html { redirect_to @call, notice: "On Scene Time Successfully Updated. - You Are Now Logged Out Of Service" }
      else
        format.html { render action: 'edit' }
      end
    end
  end

  def update_unit4_cl
    @call = Call.find(params[:id])
    @call.unit4_cl = DateTime.now
    @call.save

    respond_to do |format|
      if @call.save
        format.html { redirect_to @call, notice: "Scene Clear Time Successfully Updated. - You Are Now Logged In Service" }
      else
        format.html { render action: 'edit' }
      end
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_call
      @call = Call.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def call_params
      params.require(:call).permit(:call_time, :status, :primary_type, :secondary_type, :site, :address, :unit_1, :unit_2, :unit_3, :unit_4, :call_details, :unit_on_scene, :unit_clear, :call_num, :site_id, :user_id, :unit2_os, :unit2_cl, :unit3_os, :unit3_cl, :unit4_os, :unit4_cl)
    end
end

我不知道我哪里出错了,因为我之前和之后都没有嵌套,通过一些关于嵌套的教程我仍然卡住了。

非常感谢任何帮助!

提前致谢!

编辑 #1:

受影响脚手架的 Rake 路由输出:

     Prefix Verb   URI Pattern                                Controller#Action

               call_pings POST   /calls/:call_id/pings(.:format)            calls/pings#create
             new_call_ping GET    /calls/:call_id/pings/new(.:format)        calls/pings#new
            edit_call_ping GET    /calls/:call_id/pings/:id/edit(.:format)   calls/pings#edit
                 call_ping GET    /calls/:call_id/pings/:id(.:format)        calls/pings#show
                           PATCH  /calls/:call_id/pings/:id(.:format)        calls/pings#update
                           PUT    /calls/:call_id/pings/:id(.:format)        calls/pings#update
                           DELETE /calls/:call_id/pings/:id(.:format)        calls/pings#destroy
             history_calls GET    /calls/history(.:format)                   calls#history
 update_unit_on_scene_call PATCH  /calls/:id/update_unit_on_scene(.:format)  calls#update_unit_on_scene
    update_unit_clear_call PATCH  /calls/:id/update_unit_clear(.:format)     calls#update_unit_clear
      update_unit2_os_call PATCH  /calls/:id/update_unit2_os(.:format)       calls#update_unit2_os
      update_unit2_cl_call PATCH  /calls/:id/update_unit2_cl(.:format)       calls#update_unit2_cl
      update_unit3_os_call PATCH  /calls/:id/update_unit3_os(.:format)       calls#update_unit3_os
      update_unit3_cl_call PATCH  /calls/:id/update_unit3_cl(.:format)       calls#update_unit3_cl
      update_unit4_os_call PATCH  /calls/:id/update_unit4_os(.:format)       calls#update_unit4_os
      update_unit4_cl_call PATCH  /calls/:id/update_unit4_cl(.:format)       calls#update_unit4_cl
update_primary_resp_1_call PATCH  /calls/:id/update_primary_resp_1(.:format) calls#update_primary_resp_1
                     calls GET    /calls(.:format)                           calls#index
                           POST   /calls(.:format)                           calls#create
                  new_call GET    /calls/new(.:format)                       calls#new
                 edit_call GET    /calls/:id/edit(.:format)                  calls#edit
                      call GET    /calls/:id(.:format)                       calls#show
                           PATCH  /calls/:id(.:format)                       calls#update
                           PUT    /calls/:id(.:format)                       calls#update
                           DELETE /calls/:id(.:format)                       calls#destroy

编辑 #2:Rails 单击新呼叫按钮时的服务器输出:

tarted GET "/calls/new" for ::1 at 2015-11-22 23:26:21 -0700
Processing by CallsController#new as HTML
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =   ORDER BY "users"."id" ASC LIMIT 1  [["id", 3]]
  Rendered calls/_form.html.erb (11.8ms)
  Rendered calls/new.html.erb within layouts/application (13.4ms)
Completed 500 Internal Server Error in 19ms (ActiveRecord: 0.2ms)

ActionView::Template::Error (No route matches {:action=>"new", :call_id=>nil, :controller=>"calls/pings"} missing required keys: [:call_id]):
    456:       </table>
    457:     </div>
    458:     <div class="panel panel-info" id="update-pnl">
    459:     <div class="panel-heading" id="update-top"><center><h4><strong id="update-txt">Live Updates - Found In View Call</strong> <%= link_to "Add Update", new_call_ping_path(@call), class: 'btn btn-primary btn-sm', :id => 'add-update' %> </h4></center></div>
    460:     </div>
    461:   <div class="new-wrapper">
    462:     <div class="panel panel-warning" id="location-box">
  app/views/calls/_form.html.erb:459:in `block in _app_views_calls__form_html_erb___1493490319796568156_70162629771600'
  app/views/calls/_form.html.erb:1:in `_app_views_calls__form_html_erb___1493490319796568156_70162629771600'
  app/views/calls/new.html.erb:3:in `_app_views_calls_new_html_erb___3696559492073097692_70162629705900'

编辑 #3:使用 new_call_ping_path 时出错

ActionController::UrlGenerationError in Calls#edit
Showing /Users/TaurenLTD1/Desktop/TaurenLabs/PatrolProCAD/PatProCadApp/app/views/calls/_form.html.erb where line #459 raised:

No route matches {:action=>"new", :controller=>"calls/pings", :id=>"3"} missing required keys: [:call_id]

</div>
    <div class="panel panel-info" id="update-pnl">
    <div class="panel-heading" id="update-top"><center><h4><strong id="update-txt">Live Updates - Found In View Call</strong> <%= link_to "Add Update", new_call_ping_path, class: 'btn btn-primary btn-sm', :id => 'add-update' %> </h4></center></div>
    </div>
  <div class="new-wrapper">
    <div class="panel panel-warning" id="location-box">

我会尝试从命令行 运行 rake routes 看看 rails 从 routes.rb 生成的任何路由是否与您的错误匹配。

发布来自 运行 rake routes 的相关信息可能会有用。

编辑:

尝试在第 459 行仅 new_call_ping_path 而不是 new_call_ping_path(@call)

编辑 2:

尝试new_call_ping_path(call_id: @call.id)。这里的问题是 URL 生成器期望 call_id 因为在 routes.rb 中声明格式如下:new_call_ping GET /calls/:call_id/pings/new(.:format).

如果您在呼叫控制器中更新呼叫的 ping,那么您必须这样做:-

型号Call.rb

has_many :pings
accepts_nested_attributes_for :pings

允许 call_params 方法中的嵌套属性并更改 calls_contoller.rb 中的新方法和创建方法,例如:-

def new
    @call = Call.new
    @unit_2 = @call.unit_2
    @unit_3 = @call.unit_3
    @unit_4 = @call.unit_4
    @pings = @call.pings.build
end

def create
    @call = Call.new(call_params)
    respond_to do |format|
        if @call.save
            format.html { redirect_to @call, notice: 'Call was successfully created.' }
            format.json { render :show, status: :created, location: @call }
        else
            format.html { render :new }
            format.json { render json: @call.errors, status: :unprocessable_entity }
        end
end

private

def call_params
    params.require(:call).permit(:call_time, :status, :primary_type, :secondary_type, :site, :address, :unit_1, :unit_2, :unit_3, :unit_4, :call_details, :unit_on_scene, :unit_clear, :call_num, :site_id, :user_id, :unit2_os, :unit2_cl, :unit3_os, :unit3_cl, :unit4_os, :unit4_cl,
                                 pings_attributes: [:id, :priority, :msg, :received])
end

如果你想为来自 ping 控制器的调用添加 ping,那么你可以通过这样做来添加:-

def new
    @call = Call.find(params[:call_id])
    @pings = @call.pings.build
end

def create
    @call = Call.find(params[:call_id])
    respond_to do |format|
        if @call.update_attributes(call_params)
            format.html { redirect_to @call, notice: 'Call update has been successfully added to call.' }
            format.json { render :show, status: :created, location: @call }
        else
            format.html { render :new }
            format.json { render json: @call.errors, status: :unprocessable_entity }
        end
    end
end

private

def call_params
    params.require(:call).permit(pings_attributes: [:id, :priority, :msg, :received])
end

所以我解决了这个小问题..这实际上是一个非常荒谬的问题..当我创建嵌套控制器时,当我将文件拖放到控制器下的调用文件夹中时,我打开了控制器..

尽管我指向 calls/pings 控制器并且 rake routes 显示了适当的路线,但 rails 仍在查看原始 pings 控制器。

我一删除重复的控制器,一切就绪并开始正常工作。

感谢大家为解决此问题所做的努力!