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

class ThingsController < ApplicationController


  # POST /things
  def create

    @thing = Thing.new(params[:thing])

    if @thing.save
      flash[:notice] = 'Thing created'
      redirect_to(@thing)
    else
      render :action => :new
    end

  end

При сбое @thing.save пользователю предоставляется та же форма, предварительно заполненная только что введенными значениями, а также всплывающее сообщение о том, что пошло не так. Пока все хорошо, за исключением того, что теперь URL-адрес изменился с / things / new на things /, который, как можно было бы ожидать, вместо этого будет отображать представление индекса.

Кроме того, если пользователь обновляет страницу, он теперь просматривает индексное представление. Если он щелкнет обратно, ему будет предложено повторно отправить форму, чего я всегда старался избегать. Если я redirect_to (new_thing_path), предыдущая отправка пользователя теряется, как и сообщения об ошибках.

Я понимаю, что RESTfully, этот метод может быть «правильным», поскольку создание объекта thing должно быть результатом POSTing в / things, но с точки зрения пользовательского интерфейса меня это особо не волнует.

Я мог бы «вручную» сохранить недопустимый объект @thing в сеансе пользователя, чтобы он отображался после того, как я перенаправлю его обратно на new_thing_path, но это похоже на взлом. Похоже, что для этого должен быть «рельсовый способ».

Идеи ?

10
dearlbry 19 Фев 2011 в 01:10
У меня точно такая же жалоба на ядро ​​Rails, но вы сформулировали ее лучше, чем я :) Хороший вопрос.
 – 
Andrew
3 Апр 2011 в 07:35

2 ответа

Лучший ответ

Как вы обнаружили, по умолчанию, когда вы указываете resources :things, путь POST для создания нового объекта находится в /things. Вот результат для rake routes:

    things GET    /things(.:format)          {:action=>"index", :controller=>"things"}
           POST   /things(.:format)          {:action=>"create", :controller=>"things"}
 new_thing GET    /things/new(.:format)      {:action=>"new", :controller=>"things"}
edit_thing GET    /things/:id/edit(.:format) {:action=>"edit", :controller=>"things"}
     thing GET    /things/:id(.:format)      {:action=>"show", :controller=>"things"}
           PUT    /things/:id(.:format)      {:action=>"update", :controller=>"things"}
           DELETE /things/:id(.:format)      {:action=>"destroy", :controller=>"things"}

Похоже, вы хотите чего-то большего:

create_things POST   /things/new(.:format)      {:action=>"create", :controller=>"things"}
       things GET    /things(.:format)          {:action=>"index", :controller=>"things"}
    new_thing GET    /things/new(.:format)      {:action=>"new", :controller=>"things"}
   edit_thing GET    /things/:id/edit(.:format) {:action=>"edit", :controller=>"things"}
        thing GET    /things/:id(.:format)      {:action=>"show", :controller=>"things"}
              PUT    /things/:id(.:format)      {:action=>"update", :controller=>"things"}
              DELETE /things/:id(.:format)      {:action=>"destroy", :controller=>"things"}

Хотя это не рекомендуется, вы можете получить этот результат следующим образом:

resources :things, :except => [ :create ] do
  post "create" => "things#create", :as => :create, :path => 'new', :on => :collection
end

Вам также нужно будет изменить свои формы, чтобы они отправляли POST по правильному пути.

При этом описание URL-адресов в вашем вопросе звучит неверно. Вы перечисляете следующее: После отправки нового thing (отправка формы на /things/new),

  1. URL изменится с /things/new на /things
  2. Нажатие назад предлагает повторно отправить форму
  3. Обновление шоу things#index

Это не функциональность, которую я испытываю в моих собственных приложениях Rails 3. Вместо этого я обнаружил, что: после отправки нового thing (отправка формы на /things/new),

  1. URL изменится с /things/new на /things (это то же самое)
  2. При нажатии кнопки "назад" пользователь возвращается к не -отправленной форме (нет запроса на повторную публикацию)
  3. Обновление запросов на повторную отправку формы (как и ожидалось, на мой взгляд)
3
Michelle Tilley 20 Фев 2011 в 03:22
1
Спасибо, Брэндон. Это полезно, хотя мне все равно не важны функции по умолчанию. Думаю, я просто буду использовать проверку javascript, чтобы этого избежать, насколько это возможно.
 – 
dearlbry
21 Фев 2011 в 19:38

Я знаю, что это старый вопрос, но один подход, с которым я играл в последнее время, - это отправить форму с помощью AJAX, даже если в противном случае это не потребовалось бы. Это позволяет отправить его в действие по умолчанию для создания / обновления по всем маршрутам, но URL-адрес в браузере не изменяется. Ответ может быть простым 200 для успеха со ссылкой на страницу / index или куда вы перенаправляете при успешном сохранении, или «400 неверный запрос» с сообщением (ями) об ошибке, если данные были недопустимыми.

Самым большим недостатком является то, что отображение сообщений об ошибках и недопустимых полей теперь полностью зависит от JavaScript на стороне клиента. Это становится гораздо меньшей проблемой и даже может быть полезным, если вы используете что-то вроде Backbone или KnockoutJS на стороне клиента.

0
sockmonk 3 Июн 2014 в 18:13