Rails 4:has_many 的路由:通过关联

Rails 4: routing for has_many :through association

我有三个模型:

class User < ActiveRecord::Base
  has_many :administrations
  has_many :calendars, through: :administrations
end

class Calendar < ActiveRecord::Base
  has_many :administrations
  has_many :users, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

当我简单地使用以下路由时:

resources :users
resources :administrations
resources :calendars

一切正常,意味着我可以访问

和每个模型的 CRUD 实例。

但这不是我想要达到的。

我想要的是允许用户:

所以我想我需要更新我的路线。

这是我尝试过的:

解决方案 1

resources :users do
  resources :administrations
  resources :calendars
end

但是,当我访问 http://localhost:3000/users/1/calendars 时,出现以下错误:

NameError in Calendars#index

Showing /Users/TXC/code/rails/calendy/app/views/calendars/index.html.erb where line #27 raised:

undefined local variable or method `new_calendar_path' for #<#<Class:0x007fb807e672d0>:0x007fb807e66510>

Extracted source (around line #27):

<br>

<%= link_to 'New Calendar', new_calendar_path %>

解决方案 2

concern :administratable do
  resources :administrations
end

resources :users, concerns: :administratable
resources :calendars, concerns: :administratable

但是,当我访问 http://localhost:3000/users/1/calendars 时,出现以下错误:

Routing Error
No route matches [GET] "/users/1/calendars"

我肯定遗漏了一些明显的东西 — 抱歉,我对 Rails 不是很有经验 — 但我不知道为什么。

知道我应该如何嵌套我的资源吗?

方案1是我会采用的方式。问题是当你嵌套资源时,它会导致 helpers 发生变化(你可以通过 运行 rake routes 看到这一点)。正确的辅助方法是 new_user_calendar_path 所以改变

<%= link_to 'New Calendar', new_calendar_path %>

<%= link_to 'New Calendar', new_user_calendar_path(@user) %>

其中 @user 在控制器中设置为指向正确的用户。

奖金

您还可以查看 shallow routes(该页面的第 2.7.2 节)。它们提供了一种更简洁的方式来调用带有 URL

的嵌套日历
GET /calendars/:id

而不是

GET /users/:userId/calendars/:calendarId

因为 calendarId 无论如何都是唯一的。