Рельсы: несколько кнопок отправки в одной форме
скажем, у меня есть модель статьи, и в представлении статьи "Новый" у меня есть две кнопки: "Опубликовать"и" сохранить Черновик".
мой вопрос в том, как я могу узнать, какая кнопка нажата в контроллере.
у меня уже есть решение, но я думаю, что там должен быть лучший способ. Что я в настоящее время используется в вид:
<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, например, дать модели статьи столбец "статус" и содержит "public" или "черновик".
6 ответов:
Это было написано в Railscast эпизод 38. Используя
params
хэш, чтобы определить, какая кнопка была нажата правильный подход:View:
<%= 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
мы решили с помощью дополнительные ограничения в рельсы.
идея состоит в том, чтобы иметь один и тот же путь (и, следовательно, одно и то же имя route & action), но с ограничениями маршрутизации на разные действия.
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.
Он также может быть сделано на 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
Я помню, как однажды столкнулся с этой проблемой. Вы не можете сохранить две кнопки, а затем вызвать какое-либо действие на основе параметров[:commit]. кнопка отправки onclick будет вызывать url-адрес, на который ссылается форма. Есть определенные плохие способы получить желаемое поведение. Держите кнопку для вызова действия, на которое ссылается форма, и чтобы получить другую кнопку для вызова действия, я использовал link_to, а затем изменил стили, чтобы соответствовать кнопке. Кроме того, в качестве альтернативы вы можете использовать jQuery для изменения url-адреса формы вызов, следовательно, решая, какое действие вызывается во время выполнения. Надеюсь, это поможет.
вы также можете установить некоторые
data
атрибуты на кнопках отправки и использовать JavaScript, чтобы изменитьform
действие при нажатии одной из кнопок
обычно я использую предложение, данное Джоном Топли (см. ответ выше). другим способом является использование 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'); }