Почему "render 'new" меняет мой URL?(Рубин на рельсах) - PullRequest
5 голосов
/ 21 сентября 2019

У меня есть представление под названием new.html.erb для клиентов на localhost:3000/clients/new.Я проверяю это на ошибки.Если есть ошибка, я отображаю новый вид снова, чтобы показать все ошибки.Проблема в том, что он отображается как localhost:3000/clients в моем браузере вместо localhost:3000/clients/new.Почему это?Разве «render» не должен ничего менять из URL?Это создает проблемы, когда я обновляю страницу, потому что у меня нет представления «индекс», и оно вызывает ошибку вместо отображения «нового» представления, как это должно быть.

new.html.erb

<% if @client.errors.any? %>
    <div class="alert alert-danger">
        <h4 class="alert-heading">Error</h4>
            <% @client.errors.full_messages.each do |msg| %>
                <p><%= msg %></p>
            <% end %>
     </div>
<% end %>

<%= form_for @client, url: clients_path, remote: false do |f| %>
    <div class="form-group  row"><label class="col-sm-2 col-form-label">*Name</label>
        <div class="col-sm-3">
            <%= f.text_field :name, class:"form-control" %>
                <% if @client.errors[:name].any? %>
                    <script>$('#client_name').css('border-color', 'red');</script>
                <% end %>
         </div>
</div>

<div class="col-sm-4 col-sm-offset-2">
    <%= f.submit "Submit", id:"submit", class: 'btn btn-primary btn-sm'%>
    <%= link_to "Cancel", controller:"mainpages", action:"index", :html=>{:class=> "btn btn-primary btn-sm"}%>
</div>
<% end %>

clients_controller.rb

def new
    @client = Client.new
  end

  def create
    @client = Client.new(client_params)

      if @client.save 
        return redirect_to :root
      end
      render 'new'
  end

rout.rb

  root to: "mainpages#index"

  get '/mainpages', controller: 'mainpages', action: 'index'
  get '/planes', controller: 'planes', action: 'planes'

  resources :clients
  resources :planes

клиент.rb

class Client < ApplicationRecord
    validates :name, presence: true
end

Ответы [ 4 ]

4 голосов
/ 21 сентября 2019

Причина, по которой URL показывает /clients после отправки неверных данных, заключается в том, что форма /clients/new отправляет запрос на clients#create, который зарегистрирован под POST /clients, если вы используете значения по умолчанию Rails.

ЕслиВаши данные были действительны, Rails перенаправит пользователя на корневой путь GET /.Если ваши данные были недействительными, они будут render :new в качестве ответа на POST /clients, который отображается в вашем браузере как /clients.

Если вы попытаетесь обновить страницу после отправки неверных данных, браузер должен что-то спроситькак «Вы хотите повторно отправить форму?».Если вы нажмете «да», страница обновится, и она не должна нажать GET /clients (что обычно приводит к clients#index).Если вы вручную нажмете в строке URL-адреса своего веб-браузера и нажмете Enter , вместо этого будет отправлен запрос GET /clients, что приведет к попаданию на неправильную страницу.

Вы можете увидеть все маршрутывключая типы запросов, выполнив команду rails routes.

2 голосов
/ 22 сентября 2019

Ваше ожидание полностью неверно, но довольно распространено среди начинающих Rails.

В Аромат Rails REST GET /clients/new - это просто страница, которая содержит форму для создания нового ресурса.Поскольку это запрос GET, он идемпотент - это означает, что он не имеет состояния и выглядит одинаково для всех посетителей.

Когда вы отправляете форму, ваш браузер отправляет запрос POST на /clients.И снова в REST со вкусом Rails вы создаете ресурс.

Если проверка не пройдена, rails просто отображает ответ, содержащий форму.Это НЕ ДОЛЖНО перенаправлять пользователя, поскольку то, что вы видите, является результатом неидемпотентного запроса POST.Это не тот же ресурс, что и GET /clients/new.

На самом деле render 'new' - это всего лишь ярлык для render 'app/views/clients/new.html.erb'.Две конечные точки разделяют точку зрения - больше ничего.

Почему это?Разве «render» не должен ничего менять из URL?

Опять полностью ошибочно.render не меняет URL.Отправка формы ранее изменила URL в браузере.Render просто отображает представление и возвращает его как тело ответа.Посмотрите журналы вашего Rails-приложения, если хотите получить представление о том, как на самом деле работает обмен между клиентом и сервером.

Вы можете сопоставить это с redirect_to, который отправляет заголовок location иправильный код ответа (302), который перенаправит браузер на новое место.

Это создает проблемы при обновлении страницы, поскольку у меня нет представления «индекс», и вместо отображения«новый» вид, как и должно быть.

Чтобы решить эту проблему, вам нужно добавить действие индекса, которое может быть простым перенаправлением на /clients/new.Когда вы перезагружаете страницу, вы отправляете запрос GET на /clients, который должен обработать индекс.

Я бы действительно рекомендовал вам попробовать просто создать приложение для лесов с рельсами, чтобы вы получили представление о том, как эти рельсысоглашения делают простые операции CRUD, прежде чем вы начнете навязывать свои собственные идеи.

0 голосов
/ 22 сентября 2019

Когда вы отправляете эту форму, она переходит на / client URL с методом post.И когда вы вызываете метод render в случае ошибки, давайте разберемся, как работает 'render' и что он делает (и чем он отличается от 'redirect'):

render: визуализирует содержимое, которое будет возвращенобраузер как тело ответа.

Render сообщает Rails, какое представление или актив отображать пользователю, не теряя доступа к каким-либо переменным, определенным в действии контроллера.

Перенаправление отличается.Метод redirect_to сообщает вашему браузеру отправить запрос на другой URL.Поскольку запрос совершенно другой, представление, на которое вы перенаправляете, НЕ будет иметь доступа ни к каким переменным, определенным в контроллере.

Так что в этом случае, если вы перенаправите, вы потеряете отправленные данные, так как это будетсовершенно новый и независимый запрос.

Есть несколько способов (описанных ниже в URL), с помощью которых вы также можете изменить URL с помощью render (но это не Rails и Rest way.)

Сделать шаблон и изменить строку URL в браузере?

0 голосов
/ 21 сентября 2019

Вы должны перенаправить вместо рендера

def create
  @client = Client.new(client_params)
  if @client.save 
    redirect_to :root
  else
    # you might wanna add a flash error
    flash[:error] = "please fix the problems in the record" 
    redirect_to :new
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...