2010-04-12 4 views
23

Est-il possible que je peux créer une aide de formulaire personnalisé de sorte qu'au lieu de:aides formulaire personnalisés

special_field_tag :object, :method 

Je peux obtenir quelque chose comme:

form.special_field :method 

Répondre

47

Oui, vous pouvez ajouter à la FormBuilder et accéder à l'objet passé dans le formulaire_for. Je l'ai fait pour beaucoup de choses: les dates, les heures, les mesures, etc. Voici un exemple:

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 

que vous pouvez utiliser comme ceci:

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

Il y a quelques variables d'instance créées par Rails que vous pouvez accéder à ces méthodes d'assistance:

  • @object - l'objet modèle spécifié par la forme
  • @object_name - le nom de classe e e objet
  • @template - Je pense que c'est une instance de l'ActionView, vous pouvez éventuellement contourner tous les includes que j'ai ajoutés en appelant des méthodes sur le template. Je n'ai pas encore essayé.
  • @options - options passées FormBuilder lorsque son créé par le form_for appel

J'ai écrit les méthodes de FIELD_ID et field_name pour créer ces attributs sur les éléments d'entrée HTML de la même manière les collaborateurs réguliers font, je Je suis sûr qu'il existe un moyen de lier les mêmes méthodes que Rails utilise, mais je ne l'ai pas encore trouvé.

Le ciel est la limite sur ce que vous pouvez faire avec ces méthodes auxiliaires, ils retournent simplement des chaînes. Vous pouvez créer des tables ou des pages HTML entières en une seule, mais il vaut mieux avoir une bonne raison de le faire.

Ce fichier doit être ajouté dans l'application/helpers dossier

+3

Vous pouvez également sous-classer FormBuilder, puis utiliser votre générateur personnalisé par formulaire: <% form_for @person,: builder => MyFormBuilder do | f | %> ... <% end %> – nfm

+1

Ou globalement, ActionView :: Base.default_form_builder = MyFormBuilder – graywh

+0

Où mettez-vous ce fichier? Voulez-vous duckify la classe? – jackyalcine

6

@Tilendor, merci beaucoup pour les pointeurs. Voici un exemple d'une aide de balise form enum_select qui utilise Rails 4.1 énumérations pour remplir automatiquement les options d'une balise 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 

La plus délicate construction est @object.class.send(name.to_s.pluralize) qui produit un hachage de valeurs disponibles (par exemple, Company.time_zones). Le mettre dans helpers/application_helper.rb le rend automatiquement disponible. Il est utilisé comme:

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

Notre application affichait des numéros de téléphone dans les champs de texte, et nous voulions omettre le code du pays pour les numéros domestiques. J'utilisais des aides de forme. Après avoir lu cela et rails sources un peu, je suis venu à cette solution:

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 

Je mets cela sur app/helpers/application_helper.rb et l'utiliser comme je l'utilise aide text_field(). J'espère que cela aide quelqu'un.

Questions connexes