嵌套表单创建问题 - 调用#new中的ActionController :: UrlGenerationError

时间:2015-11-23 03:56:30

标签: ruby ruby-on-rails-4 routes nested-forms

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

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

因为我已经完成了嵌套...我可以在show字段中看到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

我的来电/ ping控制器:(通过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 Routes输出:

     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" = $1  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">

3 个答案:

答案 0 :(得分:1)

我会尝试从命令行运行rake routes,看看routes.rb生成的路由是否符合您的错误。

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

编辑:

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

编辑2:

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

答案 1 :(得分:1)

如果更新呼叫控制器中的呼叫,则必须执行以下操作: -

模型Call.rb

has_many :pings
accepts_nested_attributes_for :pings

允许call_params方法中的嵌套属性,并在calls_contoller.rb中更改new和create方法,如: -

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

答案 2 :(得分:0)

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

发生了什么事虽然我指的是呼叫/ ping控制器,即使rake路线显示了相应的路线,rails还是看着原来的ping控制器..

一旦我删除了重复的控制器,所有都落到了位置并开始正常工作。

感谢大家努力解决这个问题!