Rails: кнопки мульти-отправки в одной форме - PullRequest
58 голосов
/ 26 июля 2010

Скажем, у меня есть модель Article, а в представлении "new" статьи у меня есть две кнопки, "Опубликовать" и "Сохранить черновик".

Мой вопрос: как узнать, какая кнопка нажата в контроллере?

У меня уже есть решение, но я думаю, что должен быть лучший способ. То, что я сейчас использую в представлении:

<div class="actions">
  <%= f.submit "Publish" %>
  <%= f.submit "Save Draft", :name => "commit" %>
</div>

Так что в контроллере я могу использовать строку params [: commit] для обработки этого действия.

def create
  @article = Article.new(params[:article])
  if params[:commit] == "Publish"
    @article.status = 'publish'
    // detail omitted
  end

  @article.save
end

Но я думаю, что использование строки, связанной с представлением, не очень хорошо. Не могли бы вы сказать мне еще один способ сделать это?

ОБНОВЛЕНИЕ : Поскольку эти кнопки находятся в одной форме, они все переходят к действию «создать», и это нормально для меня. Я хочу обработать это в действии create, например присвоить модели Article столбец «status» и содержать «public» или «draft».

Ответы [ 6 ]

64 голосов
/ 26 июля 2010

Это было рассмотрено в эпизоде ​​Railscast 38 . Использование хеша params для определения, какая кнопка была нажата, является правильным подходом:

Вид:

<%= submit_tag 'Create' %>
<%= submit_tag 'Create and Add Another', name: 'create_and_add' %>

Контроллер:

if params[:create_and_add]
  # Redirect to new form, for example.

else
  # Redirect to show the newly created record, for example.
end
7 голосов
/ 27 октября 2013

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

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

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

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

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

6 голосов
/ 24 октября 2015

это также можно сделать с помощью помощника form_for , как этот

 <%= f.submit "Publish",name: "publish", class: "tiny button radius success" %>
 <%= f.submit 'Mark as Draft', name: "draft", class: "tiny button radius " %>

, и логика на контроллере та же

   if params[:publish]
      // your code
   elsif params[:draft]
      // your code
   end
1 голос
/ 26 июля 2010

Я помню, что однажды сталкивался с этой проблемой. Вы не можете удерживать две кнопки и затем вызывать какое-либо действие, основанное на параметрах [: commit]. кнопка отправки onclick будет вызывать URL, на который ссылается форма. Есть определенные плохие способы получить желаемое поведение. Удерживая кнопку, чтобы вызвать действие, к которому относится форма, и чтобы получить другую кнопку для вызова действия, я использовал link_to, а затем изменил стили, чтобы соответствовать кнопке. Кроме того, в качестве альтернативы вы можете использовать jQuery, чтобы изменить URL-адрес, который будет вызывать форма, следовательно, решить, какое действие вызывается во время выполнения. Надеюсь, это поможет.

0 голосов
/ 16 мая 2015

обычно я пользуюсь предложением Джона Топли (см. Ответ выше). Другой способ - использование JQuery / JS для изменения атрибута действия формы - после нажатия кнопки «Отправить». Пример:

form_tag({} ,:method => 'post', :id => 'reports_action') do 
   .......
   ....... 
  submit_tag 'submit',  :onclick => "return changeAction();"
end

а потом .....

function changeAction(){
   $('#reports_action').attr('action','my_new_action');
}   
0 голосов
/ 21 июля 2014

Вы также можете установить некоторые атрибуты data для кнопок отправки и использовать JavaScript для изменения действия form при нажатии одной из кнопок

...