Qualcuno può spiegarmi collection_select in termini chiari e semplici?


146

Sto esaminando i documenti API di Rails per collection_selecte sono terribili.

L'intestazione è questa:

collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})

E questo è l'unico codice di esempio che danno:

collection_select(:post, :author_id, Author.all, :id, :name_with_initial, :prompt => true)

Qualcuno può spiegare, usando una semplice associazione (ad esempio Userhas_many Planse a Planappartiene a a User), cosa voglio usare nella sintassi e perché?

Modifica 1: Inoltre, sarebbe fantastico se spiegassi come funziona all'interno di un form_helpermodulo normale. Immagina di spiegarlo a uno sviluppatore web che capisce lo sviluppo web, ma è "relativamente nuovo" per Rails. Come lo spiegheresti?


50
Sì. Questa è la documentazione più terribile che abbia mai visto
Jaseem il

1
Ad essere sinceri, la documentazione è abbastanza ok, ma non nel FormBuilderma in FormOptionsHelper: api.rubyonrails.org/classes/ActionView/Helpers/…
amiuhle

1
La mia parte preferita è quando usi collection_select in un modulo e questo cambia l'intera firma in modo che l'oggetto non faccia parte dell'elenco dei parametri ma invece collection_select sia chiamato come metodo sull'oggetto. Non pensare che lo menzionino nei documenti ...
user3670743

1
Questo è un progetto open source: se la documentazione è scarsa, abbiamo solo noi stessi da incolpare; potrebbe essere sorprendente se solo facessimo del nostro meglio per renderlo migliore. Le PR piccole / semplici vanno molto lontano.
BKSpurgeon,

Risposte:


305
collection_select(
    :post, # field namespace 
    :author_id, # field name
    # result of these two params will be: <select name="post[author_id]">...

    # then you should specify some collection or array of rows.
    # It can be Author.where(..).order(..) or something like that. 
    # In your example it is:
    Author.all, 

    # then you should specify methods for generating options
    :id, # this is name of method that will be called for every row, result will be set as key
    :name_with_initial, # this is name of method that will be called for every row, result will be set as value

    # as a result, every option will be generated by the following rule: 
    # <option value=#{author.id}>#{author.name_with_initial}</option>
    # 'author' is an element in the collection or array

    :prompt => true # then you can specify some params. You can find them in the docs.
)

Oppure il tuo esempio può essere rappresentato come il seguente codice:

<select name="post[author_id]">
    <% Author.all.each do |author| %>
        <option value="<%= author.id %>"><%= author.name_with_initial %></option>
    <% end %>
</select>

Questo non è documentato in FormBuilder, ma inFormOptionsHelper


32
Questa è facilmente una delle migliori spiegazioni di una complessa struttura di Rails che ho visto. Hai usato un linguaggio chiaro, insieme ai costrutti di base di Rails per solidificarlo. Grazie mille !!
marcamillion

2
Perché dovresti mai chiamarlo "post [author_id]"?
Jaseem,

@alexkv grazie - saresti in grado di approfondire il significato di: post, # field namespace e: author_id, # field name parametri (i primi due) - Non capisco il loro scopo nello schema delle cose - Can ' vengono omessi?
BKSpurgeon,

1
Il primo parametro può davvero essere nullo. Se stai creando un modulo oggetto, sarà quell'oggetto in modo che la selezione abbia lo stesso spazio dei nomi del resto del modulo. Se ciò non è necessario, lasciare 1 come zero. Il secondo è il nome del controllo, quindi se si tratta di aggiornare un campo su un oggetto (1 ° parametro), il nome del campo è il secondo parametro. Se si sta creando un modulo per altri usi, il secondo parametro è quello che si desidera che il controllo del modulo sia denominato e identificato. Perché usarlo con zero 1? Probabilmente perché vuoi collection_select per le opzioni: prompt.
Elc,

1
Dovrei anche notare che è possibile ottenere lo stesso effetto applicando un parametro prompt su un select_tag che utilizza options_for_select, che probabilmente risponderebbe allo stesso modo di collection_select con un oggetto nullo.
Elc,

21

Ho trascorso un bel po 'di tempo sulle permutazioni dei tag select da solo.

collection_selectcrea un tag di selezione da una raccolta di oggetti. Tenendo presente questo,

object: Nome dell'oggetto. Viene utilizzato per generare il nome del tag e per generare il valore selezionato. Questo può essere un oggetto reale o un simbolo: in quest'ultimo caso, la variabile di istanza con quel nome viene cercata nell'associazione diActionController (ovvero :postcerca un'istanza var chiamata @postnel controller).

method: Nome del metodo Questo è usato per generare il nome del tag. In altre parole, l'attributo dell'oggetto che stai cercando di ottenere dalla selezione

collection : La raccolta di oggetti

value_method : Per ciascun oggetto nella raccolta, questo metodo viene utilizzato per il valore

text_method : Per ciascun oggetto nella raccolta, questo metodo viene utilizzato per visualizzare il testo

Parametri opzionali:

options: Opzioni che puoi passare. Questi sono documentati qui , sotto la voce Opzioni.

html_options: Qualunque cosa venga passata qui, viene semplicemente aggiunta al tag html generato. Se si desidera fornire una classe, un ID o qualsiasi altro attributo, va qui.

La tua associazione potrebbe essere scritta come:

collection_select(:user, :plan_ids, Plan.all, :id, :name, {:prompt => true, :multiple=>true })

Per quanto riguarda l'utilizzo form_for, sempre in termini molto semplici, per tutti i tag che rientrano nel campo form_for, ad es. f.text_field, non è necessario fornire il primo objectparametro ( ). Questo è tratto dalla form_forsintassi.


2
Grazie per aver dedicato del tempo ... l'unico problema però è, in tutta onestà, la tua spiegazione non aiuta a chiarire le cose nella mia testa. Hai usato molti termini nella definizione attuale. Apprezzo il fatto che tu abbia dedicato del tempo, quindi per questo ho votato.
marcamillion

4
Per le ragioni così chiaramente dichiarate da marcamillion, ho votato a fondo.
Jamie
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.