Rails에서 동일한 양식에 대해 여러 제출 버튼을 생성하려면 어떻게해야합니까?


98

제출 버튼이 여러 개 필요합니다.

Contact_Call 인스턴스를 만드는 양식이 있습니다.

버튼 하나로 정상적으로 생성됩니다.

다른 버튼은이를 생성하지만 기본값과 다른 : attribute 값을 가져야하며 컨트롤러에서 사용되는 다르지만 관련 모델에 속성을 설정해야합니다.

어떻게하나요? 경로를 변경할 수 없는데 [: params]에 의해 선택되는 다른 변수를 보내는 방법이 있습니까?

그렇다면 컨트롤러에서 무엇을해야합니까? case 문을 설정해야합니다.



3
이것은 더 오래되었고 더 많은 표를 가지고 있습니다. 무엇이든은 위 ...이의 중복으로 폐쇄 할 필요가있는 경우
타린 동

답변:


129

여러 제출 버튼을 만들고 각각에 다른 값을 제공 할 수 있습니다.

<% 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

그러나 이것은 그다지 바람직하지 않을 수있는 컨트롤러와 당신의 관점을 밀접하게 결합 시킨다는 것을 기억하십시오.


1
이제 그것은 새로운 것입니다. 감사합니다 @Anurag!
Shripad Krishna

1
그래서 그냥 'A'를 넣으면 자동으로 매개 변수 이름 = '커밋'이 생성됩니까?
Timothy T.

뷰를 컨트롤러에 단단히 연결하지 않는 방법이 있습니까? 예를 들어 제출 버튼이 URL을 변경하려면? 보인다 는 사용자 입력하면 했나 컨트롤러의 동작을 변경할 수 있습니다 양식을 제출 변수, 전자 버튼의 선택 인, 벤 때문에 반드시 나쁜 아니라고?
Timothy T.

1
지저분한 js 해킹 없이는 양식 작업 속성을 변경할 수 없습니다.
Ben Orozco

즉석에서 양식 작업 속성을 변경하는 것이 더 취약한 솔루션입니다. 커밋 속성을 사용하는 것은 덜합니다. 대안으로 두 번째 제출 버튼을 다른 양식에 래핑하고 동일한 작업으로 변경해야하는 매개 변수를 전달할 수 있습니다. 그러나 2 개의 제출 버튼의 값에 의존하는 것과 크게 다르지 않습니다. 이 일을 어떻게 설정했는지 더 많이 알지 못하면 지금까지 가장 좋은 솔루션은 2 개의 제출 버튼을 사용하는 것입니다.
Anurag

75

제출 버튼의 formaction 속성을 사용하는 또 다른 방법이 있습니다.

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

표준 생성 버튼은 변경이 필요하지 않으므로 코드는 깔끔하게 유지되며 특수 버튼에 대한 라우팅 경로 만 삽입하면됩니다.

formaction :
제출 버튼 또는 이미지 인 경우 입력 요소에서 제출 한 정보를 처리하는 프로그램의 URI입니다. 지정된 경우 요소 양식 소유자의 작업 속성을 재정의합니다 . 출처 : MDN



8
나는 질문이 오래되었다는 것을 알고 있지만 독자들에게이 간결한 솔루션이 더 나은 고려를 할 가치가 있다고 조언합니다.
Jerome

2
나는이 같은 질문을 처음했을 때이 대답을 찾았 으면 좋았을 것이다. 이번에는 좀 더 깊이 들여다보기로해서 다행입니다. 훌륭한 솔루션입니다.
rockusbacchus

1
이 솔루션이 정말 마음에 듭니다. 그러나 이미 폼 헬퍼를 사용 중이거나 Rails가 토큰을 수락하지 않더라도 CSRF 토큰으로 숨겨진 필드를 추가해야했습니다. 더 나은 해결 방법을 찾을 수 없었고 정확히 왜 이런 일이 발생하는지 확실하지 않거나 토큰을 다시 추가하면 문제가 해결됩니다.
irruputuncu

단일 책임 원칙을 존중하고 각 버튼이 컨트롤러의 논리를 단순하게 유지하면서 자체 작업을 수행한다는 것을 명확하게 유지하기 때문에 이것이 더 나은 솔루션이라고 생각합니다.
Khalil Gharbaoui

29

또는 속성 이름을 변경하여 눌러 진 버튼을 인식 할 수 있습니다.

<% 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]에 따라 하나를 눌렀습니다.


2
여전히 컨트롤러에서 뷰를 분리하지 않습니다.
slowpoison 2013 년

1
예, 디커플링이 옳은 최종 작업으로 라우팅하기 위해 작업에서 일부 논리를 피하는 것을 의미한다면 여전히 연결되어 있습니다. 그 논리에서 name 속성을 사용하면 컨트롤러가 버튼에 표시된 것과 독립적이라는 것을 의미합니다. 덕분에, 편집
masciugo

4
이것은 "값"이 표시되고 유니 코드 문자를 표시하는 경우 지저분해질 것이기 때문에 i18n 상황에서 허용되는 것보다 나은 것 같습니다.
xji

2
그러나 매개 변수가 통과되지 않습니다. 나는 simple_form gem을 사용하고 있습니다. 상관 관계가 있습니까?
xji

1
이것은 컨트롤러에서 뷰를 분리하지는 않지만 적어도 컨트롤러에서 표시되는 텍스트를 분리합니다. 훨씬 더 나은 IMO.
Mic Fok 2015 년

13

보석을 사용하지 않고 @ 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

제출 버튼 값은 종종 국제화 / 번역되므로 값 사용을 피하고 대신 입력 이름을 사용합니다. 또한 경로 파일을 빠르게 복잡하게 만들 수 있으므로 너무 많이 사용하지 않습니다.


9

레일에서 고급 제약 조건 을 사용하여 해결했습니다 .

아이디어는 동일한 경로 (따라서 동일한 이름의 경로 및 작업)를 가지지 만 제약 조건이 다른 작업으로 라우팅되는 것입니다.

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

CommitParamRoutingmatches?commit param이 주어진 인스턴스 attr과 일치하면 true를 반환 하는 메서드가있는 간단한 클래스입니다 . 값.

이것은 gem commit_param_matching 으로 사용할 수 있습니다 .


3

오래된 질문이지만 같은 상황을 다루기 때문에 솔루션을 게시 할 것이라고 생각했습니다. 컨트롤러 로직과보기 버튼 사이에 불일치가 발생하지 않도록 컨트롤러 상수를 사용하고 있습니다.

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 %>

이런 식으로 텍스트는 컨트롤러에서 상수로 한곳에 만 있습니다. 그러나 나는 이것을 i18n하는 방법을 아직 알아 내지 못했습니다.


"i18n"이란 무엇을 의미합니까?
skrrgwasme 2014

경로에 제약 조건을 사용하는 것보다 이것이 더 낫습니까? 감사!
Timothy T.

@Scott : i18n은 '국제화'를 의미합니다. 기본적으로 어떻게 여러 언어를 지원할까요? 나는 그것을 실제로 조사하지 않았기 때문에 그것이 어떻게 작동하는지 또는 어떻게 구현하는지에 대해 잘 모릅니다.
Draknor 2014-08-14

@Angela-아마도 아닙니다 :) 그리고 실제로, 내 코드를 리팩토링 한 후, 관련없는 여러 양식을 포함하는 단일 모 놀리 식 양식이 아니라 각각 다른 작업을 가진 여러 양식을 만들었습니다.
Draknor 2014-08-14

1

nested_form_fields 덕분에 양식에 다양한 수의 제출 버튼이 있으므로 이름을 사용하는 것만으로는 충분하지 않았습니다. 양식에 숨겨진 입력 필드를 포함하고 양식 제출 버튼 중 하나를 눌렀을 때 Javascript를 사용하여 채웠습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.