Rails: кнопки Multi-submit в одной форме

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

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

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

<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

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

UPDATE. Поскольку эти кнопки находятся в одной и той же форме, все они идут в действие "create", и это нормально для меня. Я хочу обработать это в действии create, например, предоставить модели статьи столбец "статус" и удерживать "public" или "draft".

Ответ 1

Это было описано в эпизоде ​​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

Ответ 2

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

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

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.

Ответ 3

это также можно сделать с помощью помощника 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

Ответ 4

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

Ответ 5

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

Ответ 6

обычно я использую предложение Джона Толли (см. ответ выше). другим способом является использование 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');
}