Как создать несколько кнопок отправки для одной и той же формы в Rails?

Мне нужно иметь несколько кнопок отправки.

У меня есть форма, которая создает экземпляр Contact_Call.

Одна кнопка создает его как обычно.

Другая кнопка создает его, но должна иметь другое значение атрибута по умолчанию, и ему также необходимо установить атрибут другой, но связанной модели, используемой в контроллере.

Как мне это сделать? Я не могу изменить маршрут, так что есть способ отправить другую переменную, которая получает [: params]?

И если я это сделаю, что мне делать в контроллере, настройте оператор case?

Ответ 1

Вы можете создавать несколько кнопок отправки и предоставлять каждому из них разные значения:

<% form_for(something) do |f| %>
    ..
    <%= f.submit 'A' %>
    <%= f.submit 'B' %>
    ..
<% end %>

Это выведет:

<input type="submit" value="A" id=".." name="commit" />
<input type="submit" value="B" id=".." name="commit" />

Внутри вашего контроллера представленное значение кнопки будет идентифицироваться параметром commit. Проверьте значение для выполнения необходимой обработки:

def <controller action>
    if params[:commit] == 'A'
        # A was pressed 
    elsif params[:commit] == 'B'
        # B was pressed
    end
end

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

Ответ 2

Существует также другой подход, используя атрибут formaction на кнопке submit:

<% form_for(something) do |f| %>
    ...
    <%= f.submit "Create" %>
    <%= f.submit "Special Action", formaction: special_action_path %>
<% end %>

Код остается чистым, поскольку стандартная кнопка создания не нуждается в каких-либо изменениях, вы вставляете только путь маршрутизации для специальной кнопки:

formaction:
URI программы, обрабатывающей информацию, представленную элементом ввода, если это кнопка отправки или изображение. Если указано, он переопределяет атрибут действия владельца формы элемента. Источник: MDN

Ответ 3

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

<% form_for(something) do |f| %>
    ..
    <%= f.submit 'A', name: 'a_button' %>
    <%= f.submit 'B', name: 'b_button' %>
    ..
<% end %>

Немного неудобно, потому что вам нужно проверить наличие ключей params, а не просто проверить значение params[:commit]: вы получите params[:a_button] или params[:b_button] в зависимости от того, какой из них был нажат.

Ответ 4

Аналогичное решение для одного из предложенных @vss123 без использования каких-либо драгоценных камней:

resources :plan do
  post :save, constraints: lambda {|req| req.params.key?(:propose)}, action: :propose
  post :save, constraints: lambda {|req| req.params.key?(:finalize)}, action: :finalize
end

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

Ответ 5

Мы решили использовать расширенные ограничения в рельсах.

Идея состоит в том, чтобы иметь один и тот же путь (и, следовательно, один и тот же маршрут и действие), но с ограничениями, связанными с различными действиями.

resources :plan do
  post :save, constraints: CommitParamRouting.new("Propose"), action: :propose
  post :save, constraints: CommitParamRouting.new("Finalize"), action: :finalize
end

CommitParamRouting - это простой класс, который имеет метод matches?, который возвращает true, если параметр commit соответствует данному экземпляру attr. значение.

Это доступно как драгоценный камень commit_param_matching.

Ответ 6

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

class SearchController < ApplicationController
  SEARCH_TYPES = {
    :searchABC => "Search ABCs",
    :search123 => "Search 123s"
  }

  def search
    [...]
    if params[:commit] == SEARCH_TYPES[:searchABC]
      [...]
    elsif params[:commit] == SEARCH_TYPES[:search123]
      [...]
    else
      flash[:error] = "Search type not found!"]
      [...]
    end
  end
  [...]          
end

И затем в представлении:

<% form_for(something) do |f| %>
    [...]
    <%= f.submit SearchController::SEARCH_TYPES[:searchABC] %>
    <%= f.submit SearchController::SEARCH_TYPES[:search123] %>
    [...]
<% end %>

Таким образом, текст живет только в одном месте - как константа в контроллере. Однако я не пытался понять, как это сделать.

Ответ 7

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