¿Alguien me puede explicar collection_select en términos claros y simples?

146

Estoy revisando los documentos de la API de Rails collection_selecty son horribles.

El encabezado es este:

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

Y este es el único código de muestra que dan:

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

¿Alguien puede explicar, usando una asociación simple (digamos Userhas_many Plansy a Planpertenece a a User), qué quiero usar en la sintaxis y por qué?

Edición 1: Además, sería increíble si explicaras cómo funciona dentro de una form_helperforma regular. Imagine que está explicando esto a un desarrollador web que comprende el desarrollo web, pero que es "relativamente nuevo" para Rails. ¿Cómo lo explicarías?

marcamillion
fuente
50
Si. Esa es la documentación más horrible que he visto nunca
Jaseem
1
Para ser justos, la documentación está bastante bien, pero no en el FormBuildersino en FormOptionsHelper: api.rubyonrails.org/classes/ActionView/Helpers/…
amiuhle
1
Mi parte favorita es cuando usas collection_select en un formulario y eso cambia toda la firma para que el objeto no forme parte de la lista de parámetros, sino que se llama collection_select como método en el objeto. No creo que mencionen eso en los documentos ...
user3670743
1
Este es un proyecto de código abierto: si la documentación es deficiente, solo tenemos la culpa de nosotros mismos; podría ser increíble si solo hiciéramos nuestro gran esfuerzo para mejorarlo. Las relaciones públicas pequeñas / simples son muy útiles.
BKSpurgeon

Respuestas:

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.
)

O su ejemplo se puede representar como el siguiente código:

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

Esto no está documentado en el FormBuilder, pero en elFormOptionsHelper

alexkv
fuente
32
Esto es fácilmente, una de las mejores explicaciones de una estructura compleja de Rails que he visto. Usó un lenguaje claro, junto con construcciones básicas de Rails para solidificarlo. ¡¡Muchas gracias!!
marcamillion
2
¿Por qué lo llamarías "post [author_id]"?
Jaseem
@alexkv gracias - ¿podría explicar el significado de: post, # field namespace y: author_id, # field name parameter (los dos primeros) - No entiendo su propósito en el esquema de las cosas - can ' ¿Se pueden omitir?
BKSpurgeon
1
El primer parámetro puede ser nulo. Si está creando un formulario de objeto, será ese objeto para que la selección tenga el mismo espacio de nombres que el resto del formulario. Si eso no es necesario, deje primero como nulo. El segundo es el nombre del control, por lo que si se trata de actualizar un campo en un objeto (primer parámetro), el nombre del campo es el segundo parámetro. Si está haciendo algún formulario para otros usos, el segundo parámetro es lo que quiera que se nombre e identifique el control de formulario. ¿Por qué usar esto con nil 1st? Probablemente porque desea collection_select para: opciones de solicitud.
elc
1
También debo tener en cuenta que puede obtener el mismo efecto al agregar un parámetro de solicitud en una etiqueta select_tag que usa options_for_select, que probablemente respondería lo mismo que una colección_select con un objeto nulo.
elc
21

He pasado bastante tiempo en las permutaciones de las etiquetas seleccionadas yo mismo.

collection_selectcrea una etiqueta de selección de una colección de objetos. Teniendo esto en cuenta,

object: Nombre del objeto. Esto se usa para generar el nombre de la etiqueta, y se usa para generar el valor seleccionado. Este puede ser un objeto real o un símbolo; en este último caso, la variable de instancia de ese nombre se busca en el enlace deActionController (es decir, :postbusca una instancia var llamada @posten su controlador).

method: Nombre del método. Esto se utiliza para generar el nombre de la etiqueta. En otras palabras, el atributo del objeto que intenta obtener de la selección

collection : La colección de objetos

value_method : Para cada objeto de la colección, este método se utiliza para el valor

text_method : Para cada objeto de la colección, este método se utiliza para mostrar texto

Parámetros opcionales

options: Opciones que puedes pasar. Estos se documentan aquí , bajo el título Opciones.

html_options: Lo que se pasa aquí, simplemente se agrega a la etiqueta html generada. Si desea proporcionar una clase, id o cualquier otro atributo, va aquí.

Su asociación podría escribirse como:

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

Con respecto al uso form_for, nuevamente en términos muy simples, para todas las etiquetas que vienen dentro de form_for, por ejemplo. f.text_field, no necesita proporcionar el primer objectparámetro ( ). Esto se toma de la form_forsintaxis.

zsquare
fuente
2
Gracias por tomarse el tiempo ... aunque el único problema es, con toda honestidad, su explicación no ayuda a aclarar las cosas en mi cabeza. Usaste muchos de los términos en la definición real. Sin embargo, aprecio que te hayas tomado el tiempo, así que por eso, lo voté.
marcamillion
44
Por las razones tan claramente declaradas por marcamillion, lo rechacé.
Jamie