Ошибка маршрутизации STI

Новичок, работающий над своим первым приложением для Rails после изучения книги Hartl's Rails Tutorial и видеоролика.

Я использую модель STI, где:

class User < ActiveRecord::Base
class Kid < User
class Parent < User

Пользователь имеет основные элементы: имя, адрес электронной почты и т. д.

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

Моя проблема заключается в том, что мое редактирование ищет действие «обновить» в контроллере пользователей, когда я хочу, чтобы оно перенаправлялось на kidupdate. Я читал много сообщений SO о маршрутизации STI, но, похоже, не могу выясните, почему это не будет маршрутизироваться правильно.

Рспек тест. Ошибка возникает из-за "click_button"

describe "with valid information" do
  let(:new_first)   { "New First" }
  let(:new_last)    { "New Last" }
  let(:new_email)   { "[email protected]" }
  before do
    fill_in "First Name",               with: new_first
    fill_in "Last Name",                with: new_last
    fill_in "Email",                    with: new_email
    select  "Kid",  from: "Are you a Kid or Parent"
    fill_in "Password",                 with: kid.password
    fill_in "Confirmation",             with: kid.password
    click_button "Save changes"
  end

Ошибка Rspec:

     KidPages edit with valid information 
     Failure/Error: click_button "Save changes"
     AbstractController::ActionNotFound:
       The action 'update' could not be found for UsersController
     # (eval):2:in `click_button'
     # ./spec/requests/kids_pages_spec.rb:32:in `block (4 levels) in <top (required)>'

Маршруты:

       root        /                         static_pages#home
       help        /help(.:format)           static_pages#help
    contact        /contact(.:format)        static_pages#contact
     signup        /signup(.:format)         users#new
     signin        /signin(.:format)         sessions#new
    signout DELETE /signout(.:format)        sessions#destroy
    kidshow        /kids/:id(.:format)       users#kidshow
  kidupate PUT    /kids/:id(.:format)       users#kidupdate
    kidedit        /kids/:id/edit(.:format)  users#kidedit
      users GET    /users(.:format)          users#index
            POST   /users(.:format)          users#create
   new_user GET    /users/new(.:format)      users#new
  edit_user GET    /users/:id/edit(.:format) users#edit
       user GET    /users/:id(.:format)      users#show
            PUT    /users/:id(.:format)      users#update
            DELETE /users/:id(.:format)      users#destroy
   sessions POST   /sessions(.:format)       sessions#create
new_session GET    /sessions/new(.:format)   sessions#new
    session DELETE /sessions/:id(.:format)   sessions#destroy

маршруты.rb

  root to: 'static_pages#home'
  match '/help',    to: 'static_pages#help'
  match '/contact', to: 'static_pages#contact'
  match '/signup',  to: 'users#new'
  match '/signin',  to: 'sessions#new'
  match '/signout',  to: 'sessions#destroy', via: :delete
  match 'kids/:id', to: 'users#kidshow',  :as => 'kidshow'
  match 'kids/:id', to: 'users#kidupdate', :via => 'put', :as => 'kidupdate'
  match 'kids/:id/edit', to: 'users#kidedit',  :as => 'kidedit'
  resources :users
  resources :sessions, only: [:new, :create, :destroy]

Я боролся с этими концепциями и этой проблемой в течение нескольких недель, и я ценю помощь.


person iamreff    schedule 19.10.2012    source источник
comment
Кроме того, мои два цента о ИППП и полиморфизме. На самом деле они используются для разных вариантов использования. Вы используете STI, когда у вас есть два типа пользователей, которые различаются, возможно, несколькими столбцами. Вы используете столбец типа, чтобы назначить их в модели UserTypeA и модели UserTypeB. Полиморфизм в Rails(щелчок) — это нечто совершенно другое. Улучшение STI заключается в использовании двух таблиц профилей для хранения различных полей пользователей и использовании таблицы пользователей в первую очередь для данных аутентификации.   -  person benzhang    schedule 19.10.2012


Ответы (1)


Вы можете лучше организовать свой контроллер, чтобы вообще избежать этой проблемы. Увидеть ниже

маршруты.rb

resources :kids 
resources :parents

Это напрямую даст вам именованный путь:

edit_kid_path(kid_id) 
edit_parent_path(parent_id)

kids_controller.rb

class KidsController < ApplicationController
  def update
  end
end

parent_controller.rb

class ParentsController < ApplicationController
  def update
  end    
end

Если вы хотите поделиться поведением контроллера, вы потенциально можете сделать

class KidsController < UsersController
end

class ParentsController < UsersController
end

и поместите общие действия в users_controller.rb и переопределите их в дочерних контроллерах.

Решение о том, какие модельные отношения использовать, не должно зависеть от того, как вы структурируете свои контроллеры. Контроллеры и маршрутизация являются одной из областей рассмотрения. Данные моделирования рассматриваются совершенно отдельно. А объявление ресурсов — это просто ярлыки для некоторых совпадающих маршрутов.

Если вы не собираетесь использовать users#update и т. д., объявление resources :users не нужно, поскольку вы не используете ни один из маршрутов, которые предоставляет объявление.

person benzhang    schedule 19.10.2012
comment
Спасибо за подробный ответ Бен. На самом деле я начал с отдельных контроллеров, где у меня все еще было действие kidupdate, которое все еще направлялось на пользователей#update, когда я думал, что перенаправил его на пользователей#kidupdate. Прочитав популярный пост Алекса Рейснера о наследовании STI, я решил упростить и попытаться разместить все методы в одном классе. Тем не менее, проблема сохраняется. - person iamreff; 19.10.2012
comment
Вы уверены, что действительно попали на сервер с запросом на размещение в kids/:id? Можете ли вы вставить лог вашего сервера? tail -f logs/development.log должен предоставить вам эту информацию. Если вы использовали user_path(@kid) в своем представлении формы, это будет использовать users#update. - person benzhang; 19.10.2012
comment
Да, попадает‹исключая какой-то лог› Rendered /Users/iamreff/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.3/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb при спасении /layout (1,7 мс) Запущен PUT /users/1 для 127.0.0.1 19.10.2012 10:18:45 -0400 AbstractController::ActionNotFound (не удалось найти действие «обновить» для UsersController): - person iamreff; 19.10.2012
comment
Это проблема. он нажимает /users/1 с помощью put, который будет использовать users#update. Вы либо делаете form_for kid, url: '/kid/kid_id' делаете |f| или form_for kid, URL: kidupdate_path(kid) do |f|. В form_for @user много волшебства, предположение, которое делает form_for, не работает для вашей ситуации, поэтому вы должны быть более явными! - person benzhang; 19.10.2012
comment
Спасибо, Бен. кажется, моя проблема заключалась в том, что я не знал, как связать действие формы с маршрутом. Очень признателен! - person iamreff; 20.10.2012