Визуализировать шаблон и изменить строку URL в браузере? - PullRequest
9 голосов
/ 16 января 2011

У меня есть 2 действия - Редактировать и Обновить. Форма в Edit передает значения в действие Update. При сбое при сохранении модели я отрисовываю шаблон редактирования, где пользователь видит ошибки, а поля заполняются тем, что он заполнил ранее. Это огромное, но для меня - в панели URL в браузере пользователя есть / user / update, даже когда (и потому что) я обработал шаблон редактирования Могу ли я как-то изменить это с передачей некоторых параметров для рендеринга метода в действии обновления? Я не хочу, чтобы пользователь видел, что есть какое-либо (обновление) действие, кроме редактирования. Возможно ли это?

Ответы [ 5 ]

6 голосов
/ 25 октября 2012

Вот третий способ обойти это:

На вашем маршруте. Rb

resources :users
match 'users/:id/edit' => 'users#update', :via => :put, :as => :put_user

На ваш взгляд (например, edit.html.erb)

<%= form_for @user, :url => put_user_path do |f| %>
  ...
<%  end %>

В вашем контроллере (например, users_controller.rb)

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user])
    ...
  else
    render 'edit'
  end
end
2 голосов
/ 17 января 2011

Существует два способа решения этой проблемы:

1) Перенаправить из действия обновления обратно в действие редактирования вместо простого рендеринга шаблона и передать сообщения об ошибках и атрибуты, которые вы хотите использовать для заполненияобъект, который редактируется.Это приведет к тому, что URL-адрес будет /user/edit.

def update
  @user = User.find(params[:id])
  if @user.update_attributes params[:user]
    ...
  else
    redirect_to edit_user_path(@user, :messages => @user.errors)
  end
end

2) Опубликовать в действии редактирования вместо действия обновления и полностью удалить действие обновления.Вы можете использовать request.post?в вашем действии редактирования, чтобы проверить, является ли запрос сообщением или запросом на получение, а затем выполнить действия по обновлению и редактированию, используя одно и то же определение функции.

def edit
  @user = User.find(params[:id])
  if request.post?
    @user.update_attributes params[:user]
    ...
  else
    ...
  end
end

ПРИМЕЧАНИЕ: Имейте в виду, что вы никогда не сможетедействительно скрыть действие POST от клиента, потому что они всегда могут просмотреть ваш исходный код и увидеть действие, которое вы публикуете в форме.

1 голос
/ 03 сентября 2018

Я бы сказал, что вы просто не поняли, как и, что более важно, почему REST работает так же, как в Rails, и вы должны попытаться изучить фреймворк, прежде чем навязывать ему свои собственные идеи.рельсовые маршруты не имеют действия в этом.Вы выполняете обновление, отправляя запрос PATCH или PUT на things/:id.Исключением являются new и edit, поскольку эти действия используются для визуализации форм.

           Prefix Verb   URI Pattern                                                                              Controller#Action
           things GET    /things(.:format)                                                                        things#index
                  POST   /things(.:format)                                                                        things#create
        new_thing GET    /things/new(.:format)                                                                    things#new
       edit_thing GET    /things/:id/edit(.:format)                                                               things#edit
            thing GET    /things/:id(.:format)                                                                    things#show
                  PATCH  /things/:id(.:format)                                                                    things#update
                  PUT    /things/:id(.:format)                                                                    things#update
                  DELETE /things/:id(.:format)                                                                    things#destroy

Действие редактирования (GET / things /: id / edit) отображает форму для редактирования ресурса.Это идемпотентное действие, так как оно должно возвращать тот же результат и не изменять ресурс.

Действие обновления (PATCH | PUT / things /: id) отображает результат выполнения неидемпотентного преобразования вресурс.

Следует также отметить, что рендеринг в Rails не имеет ничего общего с перенаправлением.Что является распространенным заблуждением.

render :edit

На самом деле это просто сокращение для:

render "things/edit"

Это не вызывает действие редактирования - оба просто разделяют представление, но концептуально совершенно разные действия.

Перезагрузка этой страницы, конечно, не будет отображать тот же результат, что и запрос GET для /things/1 - не PATCH / PUT.Помните, что запросы GET всегда должны быть идемпотентными.

Перенаправление назад создаст запись в истории как отдельный запрос GET плюс тот факт, что вам нужно передать все тело формы в виде параметров GET, что вряд ли идеально.Кроме того, вы в основном отбрасываете реальную мощь рельсов, то есть производительность, которую вы получаете, принимая ее условности.

0 голосов
/ 03 сентября 2018

Можно использовать метод pushState (), описанный здесь: https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_pushState()_method

Например, вы можете поместить это в функцию javascript, которая вызывается при возникновении ошибки (ошибок) валидации:

  var url = document.referrer;
  window.history.pushState(null, null, url);
0 голосов
/ 16 мая 2017

Немного более современная версия, основанная на ответе К.Л. Чанга

resources :jobs, except: [:update] do
    member do
        patch 'edit', action: :update, :as => :update_edit
    end
end

Генерирует все стандартные маршруты отдыха, кроме стандартного маршрута обновления. (если вам не нужны все действия, вы можете использовать only: [<your routes not including :update>]

Кроме того, он генерирует

update_edit_job PATCH  /jobs/:id/edit(.:format) 

Теперь просто обновите форму, указав путь

<%= form_for @job, :url => update_edit_job_path do |f| %>
  ...
<%  end %>

поэтому вместо отправки / обновления через патч он переходит в / jobs // редактировать через патч, и это касается вашего действия по обновлению

теперь, если есть ошибка, вы можете отредактировать, и все ошибки будут видны - но пользователь не заметит, что URL отличается от URL редактирования (потому что отличается только метод)

def update
  @job = Job.find(params[:id])
  if @job.update_attributes(user_params)
    #redirect somewhere???
  else
    render 'edit'
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...