2010-04-12 9 views
23

C'è un modo che io possa creare un modulo personalizzato di supporto in modo che invece di:modulo personalizzato aiutanti

special_field_tag :object, :method 

posso realizzare qualcosa di simile:

form.special_field :method 

risposta

47

Sì, è possibile aggiungere alla Classe FormBuilder e accesso all'oggetto passato in form_for. Ho fatto questo per un sacco di cose: date, orari, misure, ecc Ecco un esempio:

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 

che è possibile utilizzare in questo modo:

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

Ci sono alcune variabili d'istanza create da Rails che è possibile accedere a questi metodi di supporto:

  • @object - l'oggetto del modello specificato dal modulo
  • @object_name - il nome della classe di th e oggetto
  • @template - Penso che sia un'istanza di ActionView, è possibile ignorare tutti gli include che ho aggiunto chiamando i metodi sul modello. Non l'ho ancora provato.
  • @options - opzioni passate al FormBuilder quando il suo creati dal form_for chiamare

ho scritto le field_id e FIELD_NAME metodi per creare questi attributi sugli elementi di input HTML allo stesso modo gli aiutanti regolari fanno, I' Sono sicuro che ci sia un modo per legare gli stessi metodi usati da Rails, ma non l'ho ancora trovato.

Il cielo è il limite di ciò che si può fare con questi metodi di supporto, semplicemente restituiscono stringhe. Puoi creare intere tabelle HTML o pagine in una, ma è meglio avere una buona ragione per farlo.

Questo file deve essere aggiunto in app/cartella aiutanti

+3

È inoltre possibile creare una sottoclasse di FormBuilder e quindi utilizzare il builder personalizzato in base al modulo: <% form_for @person,: builder => MyFormBuilder do | f | %> ... <% end %> – nfm

+1

O globalmente, ActionView :: Base.default_form_builder = MyFormBuilder – graywh

+0

Dove si inserisce questo file? Vuoi antropizzare la classe? – jackyalcine

6

@Tilendor, grazie mille per i puntatori. Ecco un esempio di un tag aiutante enum_select modulo che utilizza Rails 4.1 enumerazioni per inserire automaticamente le opzioni di un tag 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 

Il costrutto più delicata è @object.class.send(name.to_s.pluralize) che produce un hash di valori disponibili (ad esempio, Company.time_zones). Inserendolo in helpers/application_helper.rb lo rende automaticamente disponibile. Viene utilizzato come:

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

La nostra app stava visualizzando i numeri di telefono nei campi di testo e volevamo omettere il codice del paese per i numeri nazionali. Stavo usando aiutanti di forma. Dopo aver letto questo e rotaie fonte un po ', sono venuto a questa soluzione:

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 

ho messo questo su app/aiutanti/application_helper.rb e utilizzarlo come io uso text_field() aiutante. Spero che questo aiuti qualcuno.

Problemi correlati