手动更改路由时,不会将ID参数发送到Controller

时间:2018-01-07 23:30:40

标签: ruby-on-rails ruby ruby-on-rails-3

我查看了StackOverflow上提供的其他答案,但没有人回答我的问题。以下是我的代码所发生的事情。

错误

undefined method `update' for nil:NilClass

问题: 看起来param id没有从表单发送到控制器,因为它们在控制台中使用byebug显示为nil。

控制台读数:

(byebug) params[:id]
nil
(byebug) @support
nil
(byebug) params[:title]
nil
(byebug) params[:support]
<ActionController::Parameters {"title"=>"Test", "subtitle"=>"testing", 
"website"=>"www.test.com", "type_of_support"=>"", "description"=>""}
permitted: false>
(byebug) params[:support][:id]
nil
(byebug) params[:support][:title]
"Test"

我不相信问题与表单有关,因为它是部分用于new / create操作的相同形式,然后params被发送到控制器然后创建对象(尽管在那种情况下没有id,因为它是在创建对象时生成的,不是从表单传递的)。

您可以在下面的代码中看到PATCH的路线只是支持&#39;没有:id参数。如果我尝试将其添加到路线中,我会收到一条错误消息,指出没有路线匹配&#39;支持/&#39;。因此,我必须在路由中删除:id param,以便将信息传递给控制器​​。

我在这里不知所措。如何将:id传递给控制器​​? rails如何做到这一点?在我手动更改路由之前,resources :supports的自动路由包含:id路由的PATCH参数,并且可以正常工作。我做错了什么,它不允许我将其添加到路线中?

代码:

配置/ routes.rb中

get    'support',          as: 'supports',     to: 'supports#index'
post   'support',                              to: 'supports#create'
get    'support/new',      as: 'new_support',  to: 'supports#new'
get    'support/:id/edit', as: 'edit_support', to: 'supports#edit'
get    'support/:title',   as: 'support_page', to: 'supports#show'
patch  'support/',                             to: 'supports#update'
put    'support/:id',                          to: 'supports#update'
delete 'supports/:id',                         to: 'supports#destroy'

为rake路线提供此结果:

supports     GET    /support(.:format)                supports#index
support      POST   /support(.:format)                supports#create
new_support  GET    /support/new(.:format)            supports#new
edit_support GET    /support/:id/edit(.:format)       supports#edit
support_page GET    /support/:title(.:format)         supports#show
             PATCH  /support(.:format)                supports#update
             PUT    /support/:id(.:format)            supports#update
             DELETE /supports/:id(.:format)           supports#destroy

应用程序/控制器/ supports_controllers.rb

class SupportsController < ApplicationController
  before_action :set_support_by_title, only: [:show]
  before_action :set_support_by_id,    only: [:edit, :update, :destroy]

  def index
    @supports = Support.all
  end

  def show
  end

  def new
    @support = Support.new
  end

  def edit
  end

  def create
    @support = Support.new(support_params)

    respond_to do |format|
      if @support.save
        format.html { redirect_to @support, 
                      notice: 'Support was successfully created.' }
      else
        format.html { render :new }
      end
    end
  end

  def update
    # byebug
    respond_to do |format|
      if @support.update(support_params)
        format.html { redirect_to @support, 
                      notice: 'Support was successfully updated.' }
      else
        format.html { render :edit }
      end
    end
  end

  def destroy
    @support.destroy
    respond_to do |format|
      format.html { redirect_to supports_url, 
                    notice: 'Support was successfully destroyed.' }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_support_by_title
      @support = Support.find_by(title: params[:title])
      # byebug
    end

    def set_support_by_id
      @support = Support.find(params[:id])
      # byebug
    end

    # Never trust parameters from the scary internet, 
    # only allow the white list through.

    def support_params
      params.require(:support).permit(:title, 
                                      :subtitle, 
                                      :website, 
                                      :type_of_support, 
                                      :description)
    end
end

应用程序/视图/载体/ edit.html.erb

<h1>Editing Support</h1>

<%= render 'form', support: @support %>

<%= link_to 'Show', support_page_path(@support.title) %> |
<%= link_to 'Back', supports_path %>

应用程序/视图/支持/ _form.html.erb

<%= form_with(model: support, local: true) do |form| %>
  <% if support.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(support.errors.count, "error") %> 
          prohibited this support from being saved:
      </h2>

      <ul>
      <% support.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    Title: 
    <%= form.text_field :title, id: :support_title %>
  </div>

  <div class="field">
    Subtitle: 
    <%= form.text_field :subtitle, id: :support_subtitle %>
  </div>

  <div class="field">
    Website: 
    <%= form.text_field :website, id: :support_website %>
  </div>

  <div class="field">
    Type of Support: 
    <%= form.text_field :type_of_support, id: :support_type %>
  </div>

  <div class="field">
    Description: 
    <%= form.text_area :description, id: :support_description %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

1 个答案:

答案 0 :(得分:0)

在写这个问题时,我想到了一些事情并试了一下。它奏效了。我没有自己重写所有路线,而是只写了2并使用resources :supports, except: [:index, :show]来生成其他路径。这解决了我的问题。

<强>解释

我知道幕后发生了一些我不理解的事情。在我开始改变路线之前,整个过程运转良好。所以,那里的东西是不正确的。 (我仍然不知道它是什么以及如何改变它。)

我真正想要改变的两条路线是用户看到的两条路线。我不关心路由在管理后端的外观。所以,这意味着我只需要更改索引的路线并显示为SEO友好并且在浏览器中看起来更好。所以,为此,我写了这样的路线:

配置/ routes.rb中

resources :supports, except: [:index, :show]

get 'support', as: 'support_index', to: 'supports#index'
get 'support/:title', as: 'support_page', to: 'supports#show'

然后为我创建了所有新的,创建,编辑,更新,销毁路径。完成此操作后,这就是我的路线现在的样子:

supports      POST   /supports(.:format)               supports#create
new_support   GET    /supports/new(.:format)           supports#new
edit_support  GET    /supports/:id/edit(.:format)      supports#edit
support       PATCH  /supports/:id(.:format)           supports#update
              PUT    /supports/:id(.:format)           supports#update
              DELETE /supports/:id(.:format)           supports#destroy
support_index GET    /support(.:format)                supports#index
support_page  GET    /support/:title(.:format)         supports#show

如您所见,PATCH路由现在让参数:id能够更新记录。

现在,我必须在创建,更新和销毁之后更改控制器中的一些重定向,如下所示:

def create
  @support = Support.new(support_params)

  respond_to do |format|
    if @support.save
      format.html { redirect_to support_page_path(title: @support.title), 
                    notice: 'Support was successfully created.' }
    else
      format.html { render :new }
    end
  end
end

def update
  respond_to do |format|
    if @support.update(support_params)

      format.html { redirect_to support_page_path(title: @support.title), 
                    notice: 'Support was successfully updated.' }
    else
      format.html { render :edit }
    end
  end
end

def destroy
  @support.destroy
  respond_to do |format|
    format.html { redirect_to support_index_path, 
                  notice: 'Support was successfully deleted.' }
  end
end

这些redirect_to语句现在与我为index和show生成的路由匹配。

现在一切正常。

所以,问题解决了,虽然我以前还不知道自己做错了什么。任何可以脱落的光都会受到赞赏。