Forum: Rails-ES Problema con select y validate

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
443634dc3959443c6a32afd78cf8291d?d=identicon&s=25 Hernán Pérez (henryos)
on 2008-11-24 12:03
Hola gente del foro, estoy haciendo una aplicación que me permite crear
un producto con diferentes datos(titulo,descripcion,image_url y
categoria). La categoria se la debe seleccionar mediante un combobox que
carga las categorias disponible de la tabla "Categorias" de la base de
datos. El problema surge cuando activo el validates para el modelo
"Producto", ya que cuando no ingreso algun dato(es decir no se cumple la
condición de validación) en vez de marcarme los campos erróneos me
muestra el siguiente error:

NoMethodError in Productos#create

Showing productos/new.html.erb where line # raised:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each

app/views/productos/new.html.erb:26:in
`_run_erb_47app47views47productos47new46html46erb'
app/views/productos/new.html.erb:5:in
`_run_erb_47app47views47productos47new46html46erb'
app/controllers/productos_controller.rb:53:in `create'
app/controllers/productos_controller.rb:47:in `create'
:1:in `start'

Lo que yo entiendo de este error es que hubo un problema al recargar la
página new debido a que el array que estoy recorriendo para formar el
combobox de categorías disponibles me devolvió un nulo. Agradecería
cualquier ayuda. Saludos.
98ee355266e55690050a20fd76ee8c67?d=identicon&s=25 Jose Antonio Parra (pikislabis)
on 2008-11-24 12:10
Hernán Pérez wrote:

> Showing productos/new.html.erb where line # raised:
>
> You have a nil object when you didn't expect it!
> You might have expected an instance of Array.
> The error occurred while evaluating nil.each
>
> app/views/productos/new.html.erb:26:in
> `_run_erb_47app47views47productos47new46html46erb'
> app/views/productos/new.html.erb:5:in
> `_run_erb_47app47views47productos47new46html46erb'
> app/controllers/productos_controller.rb:53:in `create'
> app/controllers/productos_controller.rb:47:in `create'
> :1:in `start'

 ¿Podrias poner el codigo del metodo create?
443634dc3959443c6a32afd78cf8291d?d=identicon&s=25 Hernán Pérez (henryos)
on 2008-11-24 12:35
> Jose Antonio Parra wrote:
> ¿Podrias poner el codigo del metodo create?
Por supuesto, ahí va:

def create
    @producto = Producto.new(params[:producto])

     respond_to do |format|
      if @producto.save
        flash[:notice] = 'Producto was successfully created.'
        format.html { redirect_to(@producto) }
        format.xml  { render :xml => @producto, :status => :created,
:location => @producto }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @producto.errors, :status =>
:unprocessable_entity }
      end
    end
end

La linea 47 corresponde a respond_to do |format|
y la linea 53 corresponde a format.html { render :action => "new" }
443634dc3959443c6a32afd78cf8291d?d=identicon&s=25 Hernán Pérez (henryos)
on 2008-11-24 12:43
Hernán Pérez wrote:
> Jose Antonio Parra wrote:
> ¿Podrias poner el codigo del metodo create?
  ah me olvidaba, también te paso el del new
  <p>
    <b>Categoria</b><br />
      <select name="producto[categoria_id]">
        <% @categoria.each do |categoria| %>
          <option value="<%= categoria.id %>"
                  <%= ' selected' if categoria.id ==0 %>>
                  <%= categoria.nombre_categoria %>
                  </option>
        <% end %>
      </select>
  </p>

la linea 26 es <% @categoria.each do |categoria| %>
y la 5 se encuentra bién arriba y dice <% form_for(@producto) do |f| %>
5c15703984caa012845b3cea129da936?d=identicon&s=25 Manuel González Noriega (Guest)
on 2008-11-24 12:48
(Received via mailing list)
2008/11/24 Hernán Pérez <ruby-forum-incoming@andreas-s.net>

>                  <%= categoria.nombre_categoria %>
>                  </option>
>        <% end %>
>      </select>
>  </p>
>
> la linea 26 es <% @categoria.each do |categoria| %>
> y la 5 se encuentra bién arriba y dice <% form_for(@producto) do |f| %>
>


Cuando hay errores, caes en el else de product.save, y haces render
:action
=> 'new', donde intentas recorrer @categoria, pero es nil porque en el
método create no lo creas en ningún momento.

P.S. Y no utilicéis <b> y <br>, por Alá :)
90ea347c45cdfbc1c5767dd6304d9c10?d=identicon&s=25 Borja Martín (Guest)
on 2008-11-24 12:48
(Received via mailing list)
Buenas,
entiendo que en tu método new tendrás algo parecido a esto:
def new
 @producto = Producto.new
 @categorias = Categorias.all
end

de tal manera a que tu vista new.html.erb le llega el array de
categorías, pero cuando te falla la validación, estás cargando esa misma
vista sin haber inicializado el listado. Lo que tendrías que hacer sería
volver a cargarlo dentro del método create(ya sea al principio o sólo
cuando no se guarde el objeto).
Otra opción es hacerlo de manera automática:

before_filter :set_categorias
private
def set_categorias
  @categorias = Categorias.all
end

Y así tendrías el array con las categorías siempre disponible. si sólo
lo necesitas para determinados métodos, puedes usar las opciones :only o
:except:
http://api.rubyonrails.org/classes/ActionControlle...

Saludos

Hernán Pérez escribió:
90ea347c45cdfbc1c5767dd6304d9c10?d=identicon&s=25 Borja Martín (Guest)
on 2008-11-24 12:54
(Received via mailing list)
Por cierto, ¿hay alguna razón para hacer el select a mano?
Creo que sería mejor hacerlo con el helper:
<% for_form @producto do |f| %>
<%= f.select :categoria, @categorias.map {|cat| [cat.nombre, cat.id]} %>
<% end %>

salud!

Hernán Pérez escribió:
443634dc3959443c6a32afd78cf8291d?d=identicon&s=25 Hernán Pérez (henryos)
on 2008-11-24 13:11
Manuel González Noriega  wrote:
> P.S. Y no utilicéis <b> y <br>, por Alá :)
Gracias por tu respuesta, y perdón por lo de los <b> y <br> recién me
estoy iniciando en la programación web

Borja Martín wrote:
> Por cierto, ¿hay alguna razón para hacer el select a mano?
> Creo que sería mejor hacerlo con el helper:
> <% for_form @producto do |f| %>
> <%= f.select :categoria, @categorias.map {|cat| [cat.nombre, cat.id]} %>
> <% end %>
>
> salud!
La verdad a ese select lo copié de un tutorial q encontré por la red,
pero también encontré el que me pasaste solo q al otro le entendía
mejor.
Por cierto Borja Martín muchas gracias por tu respuesta, muy explicativa
y concisa. Me sirvió muchisimo.
Por cierto les agradezco a todos sus consejos de programación, ya q uno
se lleva de los minitutoriales q hay en la red y después terminas
programando cualquier cosa. Saludos.
90ea347c45cdfbc1c5767dd6304d9c10?d=identicon&s=25 Borja Martín (Guest)
on 2008-11-24 13:20
(Received via mailing list)
Por cierto, me bailó el tag del formulario. Sería form_for

Salud!

Hernán Pérez escribió:
443634dc3959443c6a32afd78cf8291d?d=identicon&s=25 Hernán Pérez (henryos)
on 2008-11-24 13:50
Borja Martín wrote:
> Buenas,
> entiendo que en tu método new tendrás algo parecido a esto:
> def new
>  @producto = Producto.new
>  @categorias = Categorias.all
> end
>
> de tal manera a que tu vista new.html.erb le llega el array de
> categorías, pero cuando te falla la validación, estás cargando esa misma
> vista sin haber inicializado el listado. Lo que tendrías que hacer sería
> volver a cargarlo dentro del método create(ya sea al principio o sólo
> cuando no se guarde el objeto).

Me quedó una duda en la parte:
> pero cuando te falla la validación, estás cargando esa misma
> vista sin haber inicializado el listado
por que debo inicializar el listado y no el producto, si estoy cargando
una nueva vista?
443634dc3959443c6a32afd78cf8291d?d=identicon&s=25 Hernán Pérez (henryos)
on 2008-11-24 13:54
Hernán Pérez wrote:
> Me quedó una duda en la parte:
>> pero cuando te falla la validación, estás cargando esa misma
>> vista sin haber inicializado el listado
> por que debo inicializar el listado y no el producto, si estoy cargando
> una nueva vista?

Perdón, si estaba inicializada al comienzo de create como:

@producto = Producto.new(params[:producto])

Saludos.
This topic is locked and can not be replied to.