Rails 3 has_one routing

У меня есть два класса:

class User < ActiveRecord::Base
  :has_one :foo
end

class Foo < ActiveRecord::Base
  :belongs_to :user 
end

Foo необязателен.

Я создал следующую маршрутизацию:

resources :users do
  resources :foo
end

Это приводит к следующим маршрутам:

GET    /users/:user_id/foo(.:format)              {:controller=>"foos", :action=>"index"}
user_foos POST   /users/:user_id/foo(.:format)              {:controller=>"foos", :action=>"create"}
new_user_foo GET    /users/:user_id/foo/new(.:format)          {:controller=>"foos", :action=>"new"}
GET    /users/:user_id/foo/:id(.:format)          {:controller=>"foos", :action=>"show"}
PUT    /users/:user_id/foo/:id(.:format)          {:controller=>"foos", :action=>"update"}
user_foo DELETE /users/:user_id/foo/:id(.:format)          {:controller=>"foos", :action=>"destroy"}
edit_user_foo GET    /users/:user_id/foo/:id/edit(.:format)     {:controller=>"foos", :action=>"edit"}

Вопросы:

  • Кажется, что действия Index и Show излишни. Должен ли один из них быть удален? Если да, то какой?
  • Параметр: id в действии Show кажется ненужным, так как user_id является внешним ключом в таблице foos, и для пользователя есть только один foo. Я ошибаюсь?
  • Я хотел бы иметь изящный способ маршрутизации на новое действие, если нет foo. Один из вариантов - проверить @user.foo.nil? в действии FooController Show или Index, затем перенаправляйтесь к новому действию. Есть ли лучший способ?

Спасибо за ваше время.

Ответ 1

Если ваша модель имеет ассоциацию has_one, попробуйте настроить маршрут с помощью resource :foo (обратите внимание на уникальное имя метода "resource", а не "ресурсы" ). Это установит одноуровневый маршрут ресурса (который, например, не имеет никакого действия по индексу, и действия члена не имеют параметра id, поскольку есть только один элемент). См. Также http://apidock.com/rails/ActionController/Resources/resource (2.3 документация, но относится и к 3.0, а также к afaik).

Ответ 2

Я понимаю, почему Крейг пропустил это на самом деле. Это такая тонкая разница, которая даже не перешла мне в голову. Единственное, что меня опрокинуло, это то, что мои именованные маршруты для ресурса singleton имеют странное имя индекса: user_foo_index вместо user_foos.

Это действительно умный вывод из-за отсутствия множественного числа Rails.

Предупреждение: В следующих примерах используется неглубокое вложение: либо

resources :cats, shallow: true do
  resources :noms
end

Или что:

resources :cats do
  shallow do
    resources :noms
  end
end

В любом случае, если вы настроили уникальный ресурс - address в отличие от articles, например, и вы увидите что-то вроде этого:

user_address_index GET | POST
  new_user_address GET
      edit_address GET
           address GET | PUT | DELETE

Затем, как справедливо указал Андреас, вы, вероятно, неправильно указали это на своих маршрутах:

resources :users do
  resources :address
end

И если вы измените это на:

resources :users do
  resource :address
end

Вы должны быть в полном порядке и счастливы и увидеть что-то вроде этого, если вы нажмете rake routes в своем приглашении:

     user_address POST | GET | PUT | DELETE
 new_user_address GET
edit_user_address GET

Примечание. Я знаю, что вывод маршрутов грабли не выглядит точно так, как это (это намного более подробный), я просто упрощаю ради фокуса.

Надеюсь, что это поможет.