Подтвердить что ты не робот

Помощники произвольной формы

Есть ли способ создать пользовательский помощник формы, чтобы вместо:

special_field_tag :object, :method

Я могу добиться чего-то вроде:

form.special_field :method
4b9b3361

Ответ 1

Да, вы можете добавить к классу FormBuilder и получить доступ к объекту, переданному в form_for. Я сделал это для многих вещей: даты, время, измерения и т.д. Вот пример:

class ActionView::Helpers::FormBuilder
  include ActionView::Helpers::TagHelper
  include ActionView::Helpers::FormTagHelper
  include ActionView::Helpers::FormOptionsHelper
  include ActionView::Helpers::CaptureHelper
  include ActionView::Helpers::AssetTagHelper

  # Accepts an int and displays a smiley based on >, <, or = 0
  def smile_tag(method, options = {})
    value = @object.nil? ? 0 : @object.send(method).to_i
    options[:id] = field_id(method,options[:index])
    smiley = ":-|"
    if value > 0
      smiley = ":-)"
    elsif smiley < 0
       smiley = ":-("
    end
    return text_field_tag(field_name(method,options[:index]),options) + smiley
  end

  def field_name(label,index=nil)
    output = index ? "[#{index}]" : ''
    return @object_name + output + "[#{label}]"
  end

  def field_id(label,index=nil)
    output = index ? "_#{index}" : ''
    return @object_name + output + "_#{label}"
  end

end

Что вы можете использовать следующим образом:

<% form_for @quiz do |f| %>
  <%= f.smile_tag(:score) %>
<% end %>

Есть несколько переменных экземпляра, созданных Rails, которые вы можете получить в этих вспомогательных методах:

  • @object - объект модели, заданный формой
  • @object_name - имя класса объекта
  • @template - я думаю, что это экземпляр ActionView, вы можете обойти все включенные мной добавления, вызвав методы в шаблоне. Пока не пробовал.
  • @options - параметры, переданные FormBuilder, когда они созданы с помощью формы для вызова

Я написал методы field_id и field_name для создания этих атрибутов на элементах ввода HTML так же, как обычные помощники, я уверен, что есть способ связать те же методы, что и Rails, но у меня нет нашел его еще.

Небо - это предел того, что вы можете сделать с помощью этих вспомогательных методов, они просто возвращают строки. Вы можете создавать целые HTML-таблицы или страницы в одном, но у вас есть все основания.

Этот файл должен быть добавлен в папку приложения/помощников

Ответ 2

@Tilendor, большое спасибо за указатели. Ниже приведен пример помощника тега enum_select, который использует списки Rails 4.1 для автоматического заполнения опций тега select:

# helpers/application_helper.rb
module ApplicationHelper
  class ActionView::Helpers::FormBuilder
    # http://stackoverflow.com/a/2625727/1935918
    include ActionView::Helpers::FormTagHelper
    include ActionView::Helpers::FormOptionsHelper
    def enum_select(name, options = {})
      # select_tag "company[time_zone]", options_for_select(Company.time_zones
      #   .map { |value| [value[0].titleize, value[0]] }, selected: company.time_zone)
      select_tag @object_name + "[#{name}]", options_for_select(@object.class.send(name.to_s.pluralize)
        .map { |value| [value[0].titleize, value[0]] }, selected: @object.send(name))
    end
  end
end

Самая сложная конструкция - @object.class.send(name.to_s.pluralize), которая создает хэш доступных значений (например, Company.time_zones). Ввод его в helpers/application_helper.rb делает его автоматически доступным. Он используется как:

<%= f.label :billing_status %>:
<%= f.enum_select :billing_status %><br />

Ответ 3

В нашем приложении отображались номера телефонов в текстовых полях, и мы хотели опустить код страны для внутренних номеров. Я использовал помощников формы. После прочтения этого и рельсов источник немного, я пришел к этому решению:

class ActionView::Helpers::FormBuilder
  def phone_text_field name, options = {}
    value = object.public_send(name).to_s
    if value.start_with? "9" # national number
      value = value[1..-1]
      options["value"] = value
    end
    text_field name, options
  end
end

Я помещаю это в app/helpers/application_helper.rb и использую его, как я использую text_field() помощник. Надеюсь, это поможет кому-то.