[ruby-on-rails] 레일 위의 루비 f. 사용자 정의 속성이있는 옵션 선택

다음과 같은 양식 선택 문이 있습니다.

= f.select :country_id, @countries.map{ |c| [c.name, c.id] }

이 코드는 다음과 같습니다.

...
<option value="1">Andorra</option>
<option value="2">Argentina</option>
...

하지만 다음과 같이 내 옵션에 사용자 정의 HTML 속성을 추가하고 싶습니다.

...
<option value="1" currency_code="XXX">Andorra</option>
<option value="2" currency_code="YYY">Argentina</option>
...



답변

Rails는 기존 options_for_select 도우미를 사용하여 사용자 지정 속성을 추가하여 옵션을 선택할 수 있습니다. 귀하의 질문에 거의 코드가 있습니다. html5 데이터 속성 사용 :

<%= f.select :country_id, options_for_select(
    @countries.map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] }) %>

초기 선택 추가 :

<%= f.select :country_id, options_for_select(
    @countries.map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] },
    selected_key = f.object.country_id) %>

그룹화 된 옵션이 필요한 경우 다음과 같이 grouped_options_for_select 도우미를 사용할 수 있습니다 (@continents가 각 대륙 메서드가있는 대륙 개체의 배열 인 경우).

<%= f.select :country_id, grouped_options_for_select(
    @continents.map{ |group| [group.name, group.countries.
    map{ |c| [c.name, c.id, {'data-currency_code'=>c.currency_code}] } ] },
    selected_key = f.object.country_id) %>

신용은 문서가 아니라 레일 소스를 읽음으로써 이것을 발견하는 것에 대해 게시 한 paul @ pogodan에게 가야합니다. https://web.archive.org/web/20130128223827/http://www.pogodan.com/blog/2011/02/24/custom-html-attributes-in-options-for-select


답변

다음과 같이 할 수 있습니다.

= f.select :country_id, @countries.map{ |c| [c.name, c.id, { 'data-currency-code' => c.currency_code} ] }


답변

이것은 Rails에서 직접 가능하지 않으며, 사용자 지정 속성을 생성하기 위해 자신 만의 헬퍼를 생성해야합니다. 즉, 원하는 작업을 수행하는 방법에는 두 가지가 있습니다.

(1) HTML5에서 사용자 정의 속성 이름 사용. HTML5에서는 사용자 정의 속성 이름 을 가질 수 있지만 앞에 ‘data-‘를 추가해야합니다. 이러한 사용자 정의 속성은 양식과 함께 제출되지 않지만 Javascript에서 요소에 액세스하는 데 사용할 수 있습니다. 이 작업을 수행하려면 다음과 같은 옵션을 생성하는 도우미를 만드는 것이 좋습니다.

<option value="1" data-currecy-code="XXX">Andorra</option>

(2) 사용자 지정 분할과 함께 값을 사용하여 추가 데이터를 제출합니다. 실제로 통화 코드를 제출하려면 다음과 같이 선택 상자를 만드는 것이 좋습니다.

= f.select :country_id, @countries.map{ |c| [c.name, "#{c.id}:#{c.currency_code}"] }

이렇게하면 다음과 같은 HTML이 생성됩니다.

<option value="1:XXX">Andorra</option>
<option value="2:YYY">Argentina</option>

그런 다음 컨트롤러에서 구문 분석 할 수 있습니다.

@id, @currency_code = params[:country_id].split(':')


답변

추가 속성 해시는 Rails 3에서만 지원됩니다.

Rails 2.x 를 사용 중이고 재정의하려는 경우options_for_select

기본적으로 Rails 3 코드를 복사했습니다. 다음 세 가지 방법을 재정의해야합니다.

def options_for_select(container, selected = nil)
    return container if String === container
    container = container.to_a if Hash === container
    selected, disabled = extract_selected_and_disabled(selected)

    options_for_select = container.inject([]) do |options, element|
      html_attributes = option_html_attributes(element)
      text, value = option_text_and_value(element)
      selected_attribute = ' selected="selected"' if option_value_selected?(value, selected)
      disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled)
      options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}#{disabled_attribute}#{html_attributes}>#{html_escape(text.to_s)}</option>)
    end

    options_for_select.join("\n").html_safe
end

def option_text_and_value(option)
  # Options are [text, value] pairs or strings used for both.
  case
  when Array === option
    option = option.reject { |e| Hash === e }
    [option.first, option.last]
  when !option.is_a?(String) && option.respond_to?(:first) && option.respond_to?(:last)
    [option.first, option.last]
  else
    [option, option]
  end
end

def option_html_attributes(element)
  return "" unless Array === element
  html_attributes = []
  element.select { |e| Hash === e }.reduce({}, :merge).each do |k, v|
    html_attributes << " #{k}=\"#{ERB::Util.html_escape(v.to_s)}\""
  end
  html_attributes.join
end

좀 지저분하지만 옵션입니다. 이 코드를라는 도우미 모듈에 RailsOverrides넣은 다음 ApplicationHelper. 원하는 경우 플러그인 / 젬을 사용할 수도 있습니다.

한 가지 문제점은 이러한 메서드를 활용하려면 항상 options_for_select직접 호출해야한다는 것 입니다. 다음과 같은 단축키

select("post", "person_id", Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] })

오래된 결과를 얻을 것입니다. 대신 다음과 같아야합니다.

select("post", "person_id", options_for_select(Person.all.collect {|p| [ p.name, p.id, {"data-stuff"=>"html5"} ] }))

다시 한 번 훌륭한 솔루션은 아니지만 매우 유용한 데이터 속성을 얻을 가치가있을 수 있습니다.


답변

이 문제도 만났고이 문제를 해결하기 위해 “enhanced_select”Ruby Gem을 만들었습니다. 여기에서 찾을 수 있습니다.

https://github.com/bkuhlmann/enhanced_select


답변