【问题标题】:Nested Routes - Broken Form, NoMethodError - undefined method嵌套路由 - 损坏的形式,NoMethodError - 未定义的方法
【发布时间】:2015-08-07 14:11:35
【问题描述】:

为了学习 Rails,我正在开发一个简单的日历应用程序。首先,我创建了两个脚手架和正确的关联/路由:

  • 日历
  • content_items

app/models/calendar.rb

class Calendar < ActiveRecord::Base
   has_many :content_items
end

app/models/content_item.rb

class ContentItem < ActiveRecord::Base
  belongs_to :calendar
end

routes.rb

resources :calendars do
  resources :content_items
end

controllers/content_items_controller.rb

 def create
   @content_item = ContentItem.new(content_item_params)
   @calendar = Calendar.find(params[:calendar_id] )
   respond_to do |format|
     if @content_item.save
       format.html { redirect_to calendar_content_item_path(@calendar,@content_item), notice: 'Content item was successfully created.' }
       format.json { render :show, status: :created, location: @content_item }
     else
       format.html { render :new }
       format.json { render json: @content_item.errors, status: :unprocessable_entity }
     end
   end
 end

当我创建嵌套路由时,我在尝试创建新的 content_items 时开始遇到错误。每当我提交表单时,我都会收到此错误:

ContentItems 中的 NoMethodError#create
未定义的方法`content_items_path'

错误来自: views/content_items/index.html.erb

<%= form_for [@calendar, @content_item] do |f| %>

更新 使用@Gaurav GptA 下面发布的代码修复了表单问题,但导致了一个新错误。每当我访问 /calendars/1/content_items 时,我都会收到一个错误 - 但只有在创建条目之后。使用空数据库,它可以正常工作。

ActionController::UrlGenerationError 没有路由匹配 {:action=>"show", :calendar_id=>#, :controller=>"content_items", :format=>nil, :id=>nil} 缺少必需的键:[:id]

我相信这是因为 content_item 在没有 calendar_id 的情况下被保存。如何设置 content_item 与它所属的 calendar_id 一起保存?

更新 2 它现在使用 calendar_id 保存,但是当保存项目时,edit/shpw/destroy 的链接会抛出错误。

No route matches {:action=>"show", :calendar_id=>#<ContentItem id: 1, , content_type: "Test", content_text: "Tetst\r\n", calendar_id: 1, created_at: "2015-05-26 07:06:42", updated_at: "2015-05-26 07:06:42", content_image_file_name: nil, content_image_content_type: nil, content_image_file_size: nil, content_image_updated_at: nil>, :controller=>"content_items", :format=>nil, :id=>nil} missing required keys: [:id]

突出显示文件的这一部分:

<td><%= link_to 'Show', calendar_content_item_path(content_item) %></td>

GitHub 链接:https://github.com/JeremyEnglert/baked

【问题讨论】:

  • 我认为问题出在这一行 "format.html { redirect_to @content_item, notice: 'Content item was created.' }" 您在 content_items_controller 中的创建操作
  • 您能否更新您的问题以在终端中包含ContentItems#create 的代码和rake routes 的输出
  • 更新了上面的问题。
  • 将其更改为:

标签: ruby-on-rails ruby associations nested-routes


【解决方案1】:

尝试将 content_items_controllercreate 操作更改为:

 def create
   @calendar = Calendar.find(params[:calendar_id] )
   @content_item = @calendar.content_items.new(content_item_params) #Edit

   respond_to do |format|
     if @content_item.save
       format.html { redirect_to calendar_content_item_path(@calendar,@content_item), notice: 'Content item was successfully created.' }
       format.json { render :show, status: :created, location: @content_item }
     else
       format.html { render :new }
       format.json { render json: @content_item.errors, status: :unprocessable_entity }
     end
   end
 end

希望这对你有用。

【讨论】:

  • 太棒了 - 这解决了表单问题 - 非常感谢!我认为表单在没有 calendar_id 的情况下保存,这会在保存内容后导致另一个错误。我更新了上面的问题。
  • 您的节目操作路径必须是“/calendars/:calendar_id/content_items/:id”,例如 '/calendars/1/content_items/23'
  • @GauravGupta,您没有保存关联,因此@content_item calendar_id 为零。而是@content_item = @calendar.content_items.build(params[:content])
【解决方案2】:

好的,您拥有的路线:

resources :calendars do
  resources :content_items
end

例如,您会得到这样的路径:

/calendars/50
/calendars/50/content_items/77

然后路由到:

app/controllers/calendars_controller.rb
app/controllers/content_items_controller.rb

您的错误来自您在ContentItemsController 中的create 操作。您发布到操作的参数包括您的日历 ID "calendar_id"=&gt;"1" 但没有任何东西可以接收它。 您需要获取与您正在创建的项目关联的日历实例。

@calendar = Calendar.find(params[:calendar_id] )

然后在您保存 @content_item 后,将两个对象传递给 calendar_content_item_path(如您的路线所示):

format.html { redirect_to calendar_content_item_path(@calendar,@content_item), notice: 'Content item was successfully created.' }

ContentItemsController 的create 方法中应该如下所示:

 def create
   @calendar = Calendar.find(params[:calendar_id] )
   @content_item = @calendar.content_items.build(params[:content])
   respond_to do |format|
     if @content_item.save
       format.html { redirect_to calendar_content_item_path(@calendar,@content_item), notice: 'Content item was successfully created.' }
       format.json { render :show, status: :created, location: @content_item }
     else
       format.html { render :new }
       format.json { render json: @content_item.errors, status: :unprocessable_entity }
     end
   end
 end

我还注意到您正在将日历 ID 传递给您的强参数。由于日历的 id 不是由用户分配的,所以这会出错。 您可以在Strong Parameters 上阅读更多内容。

【讨论】:

  • 这很好用,直到我保存一个项目。这些项目似乎在没有 calendar_id 的情况下保存,因此在尝试查看 /calendars/1/content_items 时出现错误。我用保存项目后收到的新错误更新了原始问题。
猜你喜欢
  • 1970-01-01
  • 2016-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多