我查看了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 %>
答案 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生成的路由匹配。
现在一切正常。
所以,问题解决了,虽然我以前还不知道自己做错了什么。任何可以脱落的光都会受到赞赏。