Como faço para criar vários botões de envio para o mesmo formulário no Rails?

Eu preciso ter vários botões de envio.

Eu tenho um formulário que cria uma instância de Contact_Call.

Um botão cria como normal.

O outro botão cria, mas precisa ter um valor de atributo diferente do padrão, e também precisa definir o atributo em um modelo diferente, mas relacionado, usado no controlador.

Como faço isso? Eu não posso mudar a rota, então existe uma maneira de enviar uma variável diferente que é pega por [: params]?

E se eu fizer isso, o que eu faço no controlador, defina uma instrução de caso?

Você pode criar vários botões de envio e fornecer um valor diferente para cada um:

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

Isto irá produzir:

   

Dentro do seu controlador, o valor do botão submetido será identificado pelo parâmetro commit . Verifique o valor para fazer o processamento necessário:

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

No entanto, lembre-se de que isso acopla sua visão ao controlador, o que pode não ser muito desejável.

Há também outra abordagem, usando o atributo de formação no botão enviar:

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

O código permanece limpo, como o botão de criação padrão não precisa de nenhuma alteração, você só insere um caminho de roteamento para o botão especial:

formação:
O URI de um programa que processa as informações enviadas pelo elemento de input, se for um botão ou imagem de envio. Se especificado, substitui o atributo de ação do proprietário do formulário do elemento . Fonte: MDN

Alternativamente, você pode reconhecer qual botão foi pressionado alterando seu nome de atributo.

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

É um pouco desconfortável porque você precisa checar a presença das teclas params em vez de simplesmente verificar o valor params[:commit] : você receberá params[:a_button] ou params[:b_button] dependendo de qual foi pressionado.

Solução semelhante a sugerida por @ vss123 sem usar gemas:

 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 

Observe que evito usar valor e usar o nome de input, pois o valor do botão de envio geralmente é internacionalizado / traduzido. Além disso, eu evitaria usá-lo muito, pois ele rapidamente sobrecarregará seu arquivo de rotas.

Nós resolvemos usar restrições avançadas em rails.

A idéia é ter o mesmo caminho (e, portanto, a mesma rota e ação nomeadas), mas com restrições de roteamento para diferentes ações.

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

CommitParamRouting é uma class simples que possui um método matches? que retorna true se o parâmetro de confirmação corresponder à attr da instância especificada. valor.

Isto está disponível como uma gem commit_param_matching .

Uma pergunta antiga, mas desde que eu tenho lidado com a mesma situação, pensei em postar minha solução. Estou usando constantes do controlador para evitar a introdução de uma discrepância entre a lógica do controlador e o botão de visualização.

 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 

E então na visão:

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

Desta forma, o texto só vive em um lugar – como uma constante no controlador. Ainda não tentei descobrir como fazer isso ainda.

Eu tenho um número variável de botões de envio no meu formulário, graças a nested_form_fields, então apenas usando o nome não foi suficiente para mim. Acabei incluindo um campo de input oculto no formulário e usando o Javascript para preenchê-lo quando um dos botões de envio do formulário foi pressionado.