Llamada funciones con parametros de entrada

Hola a todo el foro!

Necesito una manilla con esto de rails, soy novato y bueno, poco a poco
y gracias al AGILE y a estos foros voy empapándome del asunto.
El problema es el siguiente:
En mi aplicacion tengo una opción en la que cualquier usuario puede
hacer una busqueda filtrada sobre una base de datos de coches.

  1. Tengo una función en el controlador ‘coches’ (busqueda) que recoge
    los datos del filtro. (mediante la vista de esta funcion)
  2. Tengo otra funcion en el controlador ‘coches’ ( encontrar(coche) )
    que recibe el coche que se ha creado en la vista de la funcion anterior.
    Con esto hace una consulta y en su vista muestra los coches que ha
    encontrado con esas caracteristicas.

Se me entiende? Se nota que soy novato,no? Si quereis os pongo el poco
codigo que tengo.

Bien, el problema esta en que no se como hacer para que desde la vista
de la funcion ‘busqueda’ haya un link o boton que llame a la función
‘encontrar’ pasandole como parametro el sitio que se crea en ‘busqueda’.

Llevo como unos 20 días intentando cosas, leyendome foros, etc.
He probado haciendo rutas nuevas:
map.encontrar ‘/BUSQUEDA’ , :controller => ‘coches’,
:action=>‘encontrar(cocheB)’)

Pero asi se va directamente a la VISTA, porque esa es otra, el archivo
.html.erb se llama igual que la funcion es decir:
encontrar(coche).html.erb (no se si será este el fallo)
He leido el API de Rails, para el LINK_TO…

No se, he leido bastantes cosas pero aun no he conseguido nada.

Espero que me podais echar una mano. Muchas Gracias!!

Saludos.

2008/7/1 Javier H. [email protected]:

encontrado con esas caracteristicas.
No estoy seguro de entender todo el flujo, pero te paso un par pautas
que quiza puedan servirte para situarte:

  • Una accion por definicion no tiene parametros en su signatura, esta
    es siempre vacia

    def encontrar

    end

Los parametros que necesite normalmente vienen en params y la accion
que genero la vista de la que se viene es responsable de que sea asi.
Naturalmente puede delegar a metodos privados del controlador mismo
que si reciban parametros, pero esto es organizacion del codigo, esos
metodos no serian acciones.

  • Tienes dos acciones que parece que van en secuencia y la primera
    necesita pasar un modelo coche a la segunda o una lista de ellos. Ahi
    entras en matenimiento de estado y las dos soluciones canonicas son
    poner los IDs en la vista intermedia ya sea en campos ocultos de form
    o de algun modo en enlaces dependiendo de los detalles, o bien usar la
    sesion (disponible como session en Rails). Te recomiendo la primera
    opcion. En ese caso la accion encontrar recupera el o los IDs de
    params y construye los modelos a partir de ellos.

Buenos dias!

Muchas gracias por contestarme tan rápido Xavier, he tardado un poco en
contestar porque me gusta indagar un poquillo en las cosas nuevas que
voy aprendiendo antes de pedir consejo de nuevo.
Bien, he estado estudiando esto del ‘params’ y si lo he entendido bien,
delata mi bajo conocimiento en rails respecto a la primera pregunta de
este topic…jejjee…bueno voy aprendiendo que es lo importante.

Ok. En AGILE pone que: “Params es un objeto importante dentro de las
aplicaciones Rails. Contiene todos los parámetros pasados en una
solicitud. Por convenio, params[:id] contiene el id o clave primaria del
objeto que va a ser utilizado. Hemos establecido el id cuando
utilizamos :id => producto en el button_to que llama a nuestra vista”

1ª/ Una pregunta que me surge es: el objeto que se crea en la solucitud,
¿tiene que ser almacenado en la base de datos? … Te explico lo que he
entendido: Params es un objeto que se crea al poner: params[:id], y
sabe que tipo de objeto crear y sus atributos porque le pasamos el ‘id’
del objeto. Lo que no me queda claro es: Ese ‘id’ es realmente un
identificador de un objeto almacenado en la base de datos y params lo
único que hace es copiar el objeto con ese id. O por el contrario con el
‘id’ lo que hacemos es pasarle el objeto entero. No lo termino de
comprender!!

2ª/ Aun sin entenderlo bien he estado indagando un poco en el código. Te
pongo el código y te lo voy explicando:


** Controlador Coches **

def NuevaBusqueda
@coche= Coche.new
end

def encontrar
@coche = params[:id]
@coches = Coche.find_by_sql [“SELECT * FROM coches WHERE
(coches.marca = ?)”, @coche.marca]
end


** Vista de NuevaBusqueda **

Nueva Busqueda

<%= error_messages_for :cocheBusqueda %>

<% form_for @coche do |f| %>

Nombre
<%= f.text_field :marca %>

Calle
<%= f.text_field :color %>

<% end %>

<%= button_to “EncontrarCoche”, { :action => “encontrar”, :id => @coche
} %>


** Vista de Encontrar **

Listing sitios

<% for coche in @coches%> <% end %>
Marca Color
<%=h coche.marca %> <%=h coche.color %>
______________________________________________________________________________

Bueno es bastante sencillito.
De esta forma creo que el error que me da es en la consulta:

NoMethodError in CochesController#encontrar

You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.marca

He probado a poner consultas más sencillas, sin interrogantes y funciona
bien, pero como no termino de entender como funciona el params, no se
como probar si lo hago bien.

Todo esto es solo para que me digas, por favor, si utilizo bien el
params y si estoy en lo cierto con lo que he entendido del AGILE.

Muchas Gracias de nuevo Xavier.

Un saludo.

Buenos dias!

Muchas gracias por contestarme tan rápido Xavier, he tardado un poco en
contestar porque me gusta indagar un poquillo en las cosas nuevas que
voy aprendiendo antes de pedir consejo de nuevo.
Bien, he estado estudiando esto del ‘params’ y si lo he entendido bien,
delata mi bajo conocimiento en rails respecto a la primera pregunta de
este topic…jejjee…bueno voy aprendiendo que es lo importante.

Ok. En AGILE pone que: “Params es un objeto importante dentro de las
aplicaciones Rails. Contiene todos los parámetros pasados en una
solicitud. Por convenio, params[:id] contiene el id o clave primaria del
objeto que va a ser utilizado. Hemos establecido el id cuando
utilizamos :id => producto en el button_to que llama a nuestra vista”

1ª/ Una pregunta que me surge es: el objeto que se crea en la solucitud,
¿tiene que ser almacenado en la base de datos? … Te explico lo que he
entendido: Params es un objeto que se crea al poner: params[:id], y
sabe que tipo de objeto crear y sus atributos porque le pasamos el ‘id’
del objeto. Lo que no me queda claro es: Ese ‘id’ es realmente un
identificador de un objeto almacenado en la base de datos y params lo
único que hace es copiar el objeto con ese id. O por el contrario con el
‘id’ lo que hacemos es pasarle el objeto entero. No lo termino de
comprender!!

2ª/ Aun sin entenderlo bien he estado indagando un poco en el código. Te
pongo el código y te lo voy explicando:


** Controlador Coches **

def NuevaBusqueda
@coche= Coche.new
end

def encontrar
@coche = params[:id]
@coches = Coche.find_by_sql [“SELECT * FROM coches WHERE
(coches.marca = ?)”, @coche.marca]
end


** Vista de NuevaBusqueda **

Nueva Busqueda

<%= error_messages_for :cocheBusqueda %>

<% form_for @coche do |f| %>

Marca
<%= f.text_field :marca %>

Color
<%= f.text_field :color %>

<% end %>

<%= button_to “EncontrarCoche”, { :action => “encontrar”, :id => @coche
} %>


** Vista de Encontrar **

Listing coches

<% for coche in @coches%> <% end %>
Marca Color
<%=h coche.marca %> <%=h coche.color %>
______________________________________________________________________________

Bueno es bastante sencillito.
De esta forma creo que el error que me da es en la consulta:

NoMethodError in CochesController#encontrar

You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.marca

He probado a poner consultas más sencillas, sin interrogantes y funciona
bien, pero como no termino de entender como funciona el params, no se
como probar si lo hago bien.

Todo esto es solo para que me digas, por favor, si utilizo bien el
params y si estoy en lo cierto con lo que he entendido del AGILE.

Muchas Gracias de nuevo Xavier.

Un saludo.

He cambiado una cosa y parece que no peta, pero no funciona…snif,snif.

Cuando te escribia el post me dado cuenta que en la linea, @coche =
params[:id] de la funcion encontrar no estaba creando el objeto, asique
lo e cambiado por:
@coche = Coches.new(params[:id])

He cambiado una cosa y parece que no peta, pero no funciona…snif,snif.

Cuando te escribia el post me dado cuenta que en la linea, @coche =
params[:id] de la funcion encontrar no estaba creando el objeto, asique
lo e cambiado por:

 @coche = Coches.new(params[:id])

De esta forma creo un objeto con los datos de params. (sigo sin entender
bien lo de params)

Ahora no peta, pero cuando pongo una marca para que me busque los
coches…no saca ningun resultado…

Un saludete. Gracias!

 @coche = Coches.new(params[:id])

De esta forma creo un objeto con los datos de params. (sigo sin entender
bien lo de params)

params no tiene nada que ver con la base de datos.

params es un objeto que contiene todos los parámetros que hayas enviado
a tu página, tanto por get como por post. Es decir, si a una página le
llega una
petición
http://localhost:3000/coche/busca?marca=seat&ruedas=4

en params[:marca] te llegará “seat” y en params[:ruedas] te llegará “4”.
Lo que te llega por params son siempre cadenas.

Si en lugar de esa petición via get (los parámetros van en la url
separados con un ?) los hubieras mandado con un formulario vía post, lo
que tendrías en params sería una entrada por cada campo de tu formulario,

La gracia del asunto es que rails da alguna ayuda adicional y te deja
agrupar parámetros. Si usas los helpers de rails para formularios
(text_field y demás) de esta forma

text_field(:coche,:marca)
text_field(:coche,:ruedas)

cuando llegan a la acción, estos parámetros realmente se encuentran en
params[:coche][:marca] y params[:coche][:ruedas]

es decir, que en params[:coche] tienes una hash que contiene todos los
parámetros relativos a ese formulario.

Rails proporciona métodos que permiten inicializar un objeto completo a
partir de una hash. De esta forma en tu acción puedes hacer
Coche.new(params[:coche])

Y eso te crea EN MEMORIA un objeto del tipo Coche con los atributos que
vengan en params[:coche] (los que hayas puesto en tu formulario)

Ahora no peta, pero cuando pongo una marca para que me busque los
coches…no saca ningun resultado…

efectivamente… porque Coche.new crea un objeto EN MEMORIA. Si ese
objeto lo quieres pasar a la base de datos tendrás que usar el método
.save sobre el objeto creado.

Comentabas que tienes el libro de Rails. Puede que antes de ponerte a
hacer tu propio desarrollo sea mejor si vas siguiendo los ejemplos del
Agile para irte familiarizando con Rails.

saludos,

javier ramírez

En el controlador que busca prueba esto (NOTA: soy novatisimo, pero por
probar…)

def encontrar
@coche = Coche.find*(params[:id])
@marca = @coche.marca

  • end

porque lo que vas a buscar es un solo coche no?

El día 3 de julio de 2008 20:54, Javier H. <
[email protected]> escribió:

Perfecto… el params esta entendio, muchas gracias por la explicación
Javier, estoy siguiendo el Agile pero en muchas ocasiones no entiendo
como lo explica.
Gracias a la explicación y releyendome este librito he podido concluir
que lo único que necesito es una linea.
No me hace falta crear un objeto en memoria con
Coche.new(params[:coche]), con el propio objeto params accediendo al
parametro ‘marca’ es suficiente, es decir:

@coches = Coche.find_by_sql([“SELECT * FROM coches WHERE marca = ?”,
params[:marca]])

Pero aun hay algo que falla, porque no encuentra nada. Tras varias
pruebas cocnluyo que el objeto params esta vacio:

def encontrar
if(params[:coche] == nil)
render :text => “Es Nil”
else
@coches = Coche.find_by_sql([“SELECT * FROM coches WHERE marca =
?”, params[:marca]])
end
end

No se ni por donde cogerlo, teoricamente debería ser tan intuitivo como
la accion ‘new’, es decir, rellenas unos campos y aceptas, solo que en
vez de llamar a ‘create’, llamo a otra función.
Para ello sigo al pie de la letra al AGILE poniendo en la vista que
recoje los datos un:

<%= button_to “EncontrarCoche”, { :action => :encontrar , :id => @coche
} %>

La vista completa que recoge los datos es la siguiente:


** Vista de NuevaBusqueda **

Nueva Busqueda

<%= error_messages_for :cocheBusqueda %>

<% form_for @coche do |f| %>

Marca
<%= f.text_field :marca %>

Color
<%= f.text_field :color %>

<% end %>

<%= button_to “EncontrarCoche”, { :action => :encontrar , :id => @coche
} %>

No entiendo porque mi objeto params esta vacio…

Muchas gracias a todos!

Un saludo.

Eureca!!

Por fin lo he conseguido!..Os comento y cierro el Topic.

El problema era: Necesitaba hacer una busqueda filtrada sobre una base
de datos de coches, es decir, que el usuario introdujera o bien marca o
bien color y el buscador sacase los coches con esas características.

La forma de hacerlo es: Tengo dos acciones: ‘NuevaBusqueda’ y
‘Encontrar’. Primero se ejecuta ‘NuevaBusqueda’ recoge los datos de la
busqueda (marca y/o color) y lo envia a la accion ‘encontrar’. Esta hace
una consulta y muestra los resultados en su vista.

Debido a mi baja experiencia en Rails, pense que el problema radicaba en
los parametros de entrada de la accion ‘encontrar’, puesto que yo
pensaba que se hacia como en los demas lenguajes de programacion (por lo
menos los que yo se), es decir, encontrar(marca, color). Esto quedo
aclarado con lo que me explico Xavier y Javier. (me costo …pero lo
consegui asimilar el objeto params).

Os pongo el código. he cambiado cosas de la vista de ‘NuevaBusqueda’,
especifico la url de la accion y en la accion ‘encontrar’ cosas nuevas:

def encontrar
@coches= Coche.find_by_sql([“SELECT * FROM coches WHERE marca= ?”,
params[:coche][:marca]])
end


** Vista de NuevaBusqueda **

Nueva Busqueda

<%= error_messages_for :cocheBusqueda %>

<% form_for :coche, :url => { :action => :encontrar } do |f| %>

Marca
<%= f.text_field :marca %>

Color
<%= f.text_field :color %>

<%= f.submit%>

<% end %>

Estube mirando los Helpers como me recomendasteis y bueno…he cambiado
cosillas como veis.
Solo queda retocar un poco la consulta…

Bueno muchas gracias a todos!!..Me habeis echado una gran mano, de
verdad.

Andres también probe lo tuyo, pero no funcionó. Muchas gracias de todas
formas.

Un saludete!

2008/7/3 Javier H. [email protected]:

@coches = Coche.find_by_sql([“SELECT * FROM coches WHERE marca = ?”,
params[:marca]])

Un detalle ahi.

Por lo general solo se usa find_by_sql en casos complicados. Active
Record ofrece metodos de mas alto nivel para hacer queries y moverse
por relaciones. Para ese caso por ejemplo:

@coches = Coche.find_all_by_marca(params[:marca])