Rails:没有路由匹配...缺少必需的键:[:id]

Jer*_*myE 2 routes ruby-on-rails

完整错误:

No route matches {:id=>#<Reminder id: nil, medication: nil, time: nil, created_at: nil, updated_at: nil, user_id: 1>} missing required keys: [:id]
Run Code Online (Sandbox Code Playgroud)

以下是index.html.erb中导致错误的代码:

<tbody>
    <% @reminders.each do |reminder| %>
      <tr <%= dom_id(reminder) %>>
        <td><%= reminder.medication %></td>
        <td><%= reminder.time %></td>
        <td>
          <%= link_to "Edit", edit_reminder_path(reminder) %>
          or
          <%= link_to 'Remove', reminder, method: :delete, data: { confirm: 'Are you sure?' } %>
      </td>
      </tr>
    <% end %>
  </tbody>
Run Code Online (Sandbox Code Playgroud)

楷模:

class Reminder < ActiveRecord::Base
    validates :medication, presence: true
    belongs_to :user
end
class User < ActiveRecord::Base
  has_many :reminders
end
Run Code Online (Sandbox Code Playgroud)

操作:

  def index
    @reminders = current_user.reminders
    @reminder = current_user.reminders.new 
  end
  def edit
  end
Run Code Online (Sandbox Code Playgroud)

路线:

Medy::Application.routes.draw do
  devise_for :users
  resources :reminders
  root 'reminders#index'
end
Run Code Online (Sandbox Code Playgroud)

我是否需要在编辑操作中添加一些内容才能使其正常工作?

在我更改@reminders = Reminders.all@reminders = current_user.reminders索引操作后,错误开始发生.

小智 11

这样做的原因是您将未提交的"提醒"实例传递到edit_reminder_path.将实例作为参数传递给路径时,将在该实例上调用"to_param"方法.默认情况下,'to_param'方法返回实例的'id'.

在你的情况下,你有:

def index
  @reminders = current_user.reminders
  @reminder = current_user.reminders.new
end
Run Code Online (Sandbox Code Playgroud)

因为您已将@reminder作用于当前用户.该实例被添加到该用户的提醒集合中,因此也包含在@reminders中.这意味着当您在索引页面上呈现@reminders时,它还会尝试渲染尚未设置"id"的未保存的@reminder.

更好的解决方案是将索引操作更改为:

def index
  @reminders = current_user.reminders
  @reminder = Reminder.new
end
Run Code Online (Sandbox Code Playgroud)

然后,在保存提醒时,很可能是在"创建"操作中,您可以使用current_user:

def create
  @reminder = current_user.reminders.new(reminder_params)
  if @reminder.save .....
end
Run Code Online (Sandbox Code Playgroud)