紳士なブログ

紳士すぎてすみません

ActionViewのselectメソッドのソースコード読んでみた

普段Ruby on Railsを利用しているのですが、

その中にあるActionViewについて実はあまりよくわかっていなかったので、

ソースコードを読んでみました。


Railsのバージョンは少し古くて2.3.12ですm(_ _)m


selectメソッドの引数は、method, choices, options, html_optionsの順番。

choicesはHashで渡してもto_aされる。

html_optionsはSymbolで渡してもstringify_keysされる。


actionpack-2.3.12/lib/action_view/helpers/form_options_helper.rb
module FormOptionsHelper
  include ERB::Util

  def select(object, method, choices, options = {}, html_options = {})
    InstanceTag.new(object, method, self, options.delete(:object)).to_select_tag(choices, options, html_options)
  end

  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|
      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_escape(text.to_s)}</option>)
    end

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

class InstanceTag #:nodoc:
  include FormOptionsHelper

  def to_select_tag(choices, options, html_options)
    html_options = html_options.stringify_keys
    add_default_name_and_id(html_options)
    value = value(object)
    selected_value = options.has_key?(:selected) ? options[:selected] : value
    disabled_value = options.has_key?(:disabled) ? options[:disabled] : nil
    content_tag("select", add_options(options_for_select(choices, :selected => selected_value, :disabled => disabled_value), options, selected_value), html_options)
  end

  private

  def add_options(option_tags, options, value = nil)
    if options[:include_blank]
      option_tags = "<option value=\"\">#{options[:include_blank] if options[:include_blank].kind_of?(String)}</option>\n" + option_tags
    end
    if value.blank? && options[:prompt]
      prompt = options[:prompt].kind_of?(String) ? options[:prompt] : I18n.translate('support.select.prompt', :default => 'Please select')
      option_tags = "<option value=\"\">#{prompt}</option>\n" + option_tags
    end
    option_tags.html_safe
  end
end