Как сделать рендер: новый в контроллере и не потерять параметры из URL? - PullRequest
0 голосов
/ 04 ноября 2019

Я хочу сделать render :new в моем методе создания из контроллера, проблема в том, что он меняет URL-адрес, а в URL-адресе у меня есть параметр, необходимый для заполнения формы в моем html (например: localhost3000 / episodes/ new? serie_id = 8, я делаю это с hidden_field_tag).

Мой контроллер:

  def new
    @episode= Episode.new
  end

  def create
    # params = { episode: { name: valor, serie_id: valor, ... more} }
    @episode = Episode.new(episode_permits)
    if @episode.save
      redirect_to @episode
    else
      render :new #This render I want to fix
    end
  end

Мой частичный _form.html.erb:

  <%= form_for @chapter do |f| %>
        <%= f.label :name, 'Name' %>
        <%= f.text_field :name%> <!-- I don't want to use required: true -->
        <%= f.hidden_field :serie_id, value: params[:serie_id] %>
  <% end %>

Если пользователь нажимает кнопку, которая присваивает форму из нового для создания,если он ошибается при заполнении формы, @episode не может быть сохранен и делает render :new, а затем URL-адрес меняется на localhost3000 / episodes /

Как я могу сделать для render :new не меняютсяURL?

Я пытался вместо render :new использовать redirect_to new_episode_path(:serie_id => params[:episode][:serie_id]), но при этом терялось то, что пользователь вводил в форму, и любые проверки не показывают, что произошло, так что это не вариант.

Просто немного больше информации о проекте, если он неоднозначный: я делаю сеть Netflix для изучения Rails, серия (имя) имеет много эпизодов, а эпизод (имя, serie_id) относится к серии.

Ответы [ 2 ]

0 голосов
/ 04 ноября 2019

Рельсы способ сделать это путем создания вложенного ресурса :

# config/routes.rb
resources :series do
  resources :episodes, shallow: true
end

Выполнить rails routes, чтобы увидеть выходные данные маршрутов. Ключевым моментом здесь является то, что он создает маршрут GET /series/:series_id/episodes/new и POST /series/:series_id/episodes. Это делает связь между двумя ресурсами явной, а не скрытой в теле запроса.

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

class EpisodesController
  before_action :set_series

  # GET /series/1/episodes/new
  def new
    @episode = @series.episodes.new
  end

  # POST /series/1/episodes
  def create
    @episode = @series.episodes.new(episode_params)
    if @episode.save
       redirect_to @episode
    else
       render :new
    end
  end
  # ...
  private 
  def set_series
     @series = Series.find(params[:series_id])
  end

  def episode_params
    params.require(:episode).permit(:foo, :bar, :baz)
  end
end

Чтобы получить форму для отправки на /series/:serie_id/episodes вместо /series, мы передаем массив:

<%= form_for([@series, @episode]) %>
  <%= f.label :name, 'Name' %>
  <%= f.text_field :name%>
  <%= f.submit %>
<% end %>

Если пользователь нажимаеткнопка, которая присваивает форму из нового для создания, если он делает ошибку при заполнении формы, @episode не может быть сохранен и выполняет рендеринг: новый, а затем URL-адрес меняется на localhost3000 / episodes /

Это действительно распространенное зависание новичка, вызванное непониманием того, как стиль Rails REST работает

В REST вы создаете ресурс, публикуя его на маршруте сбора (POST /episodes). Это означает, что URL-адрес браузера изменяется путем публикации формы, и именно так и должно быть.

render :new НЕ меняет URL-адрес. Он просто инструктирует рельсы для рендеринга вида app / views / episodes / new.html.erb .

То, что вы затем видите, является результатом выполнения неидемпотентного действия. Вы НЕ ДОЛЖНЫ перенаправлять назад, так как они оба не нужны и требуют, чтобы вы поместили все параметры в строку запроса, что не идеально.

PS

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

# config/intializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.irregular 'series', 'series'
en

Затем следует переименовать модель и ассоциации.

Почему это важно? Принцип наименьшего удивления.

0 голосов
/ 04 ноября 2019

Я бы просто изменил

<%= f.hidden_field :serie_id, value: params[:serie_id] %>

на

<%= f.hidden_field :serie_id, value: (f.object.serie_id.presence || params[:serie_id]) %>

, чтобы сделать откат только на params[:serie_id], когда атрибут serie_id еще не установлен в главе.

...