Forum: Rails-ES recursividad en los menus de navegación

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.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2008-05-27 17:08
(Received via mailing list)
Hola a todos, tengo lo siguiente en

#application.html.erb
                <% @tabs.each do |page| -%>
                    <li <%= "id='current'" if @page && (@page == page ||
@page.parent == page) %>><%= link_to page.navlabel,
view_page_path(page.name
)-%></li>
                <% end -%>
lo que hace el código ruby que esta dentro de <li> es determinar si la
pagina que esta en el menu de navegación es la "current"

Esto funciona bien con dos niveles de profundidad, pero si hay más ya no
se
aplica el estilo "current" a la pestaña que le corresponde.

ej.:
tengo un página de coches (por ejemplo. no es mi caso :) )
mi menu es el siguiente

1-coches deportivos

2-coche antiguos
   coches antiguos europeos
        coches antiguos europeos diesel
        coches antiguos europeos gasolina
   coches antiguos americanos

3-coches familiares

como veis tengo tres tabs principales (coches deportivos, coches
antiguos,
coches familiares). El que interesa es coches antiguos. este tiene dos
niveles por debajo.
Bien, en el primer nivel (coches antiguos europeos) , con el código de
arriba, (coches antiguos) recibe el id="current", pero cuando bajamos al
segundo nivel (coches antiguos europeos diesel ó coches antiguos
europeos
gasolina) esto se pierde.

PREGUNTA: ¿Cómo hago para que no se pierda?

Gracias
49b6123803e4f327144e991daab62f77?d=identicon&s=25 Daniel Rodriguez Troitiño (Guest)
on 2008-05-27 18:03
(Received via mailing list)
2008/5/27 Andrés gutiérrez <andresgutgon@gmail.com>:
>
> PREGUNTA: ¿Cómo hago para que no se pierda?
>

Si estás utiizando acts_as_tree la condición de se podría sustituir por:

<li <%= "id='current'" if @page && (@page == page ||
@page.ancestors.include?(page) %>>

Pero no te recomendaría aumentar mucho los niveles de tu menú, porque
por cada nivel hasta las raíces es una nueva consulta a la base de
datos que ancestors tiene que hacer.

Suerte.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2008-05-27 18:21
(Received via mailing list)
>>Si estás utiizando acts_as_tree la condición de se podría sustituir por:

No lo utilizo

>> Pero no te recomendaría aumentar mucho los niveles de tu menú, porque
>>por cada nivel hasta las raíces es una nueva consulta a la base de
>>datos que ancestors tiene que hacer.

¿cómo lo harias de forma eficiente?

Tengo que aclarar lo que hago en mi modelo para conseguir "parent"

#page.rb

class Page < ActiveRecord::Base
    acts_as_textiled :body
    has_many :subpages, :class_name => 'Page', :foreign_key =>
'parent_id'
    belongs_to :parent, :class_name => 'Page', :foreign_key =>
'parent_id'

    def self.find_main
        Page.find(:all, :conditions => ['parent_id IS NULL'], :order =>
'position')
    end

    def self.find_main_public
        Page.find(:all, :conditions => ["parent_id IS NULL and admin !=
?",
true], :order => 'position')
    end
end

Como ves Page tienen a sus ancestros en el mismo modelo y esas dos
funciones
(find_main y find_main_public) las uso en:

#application.rb
  before_filter :get_pages_for_tabs

  def get_pages_for_tabs
    if logged_in?
        @tabs = Page.find_main
    else
        @tabs = Page.find_main_public
    end
  end

De aquí saco @tabs (las generales de la app) para mi layout
(application.html.erb)
#application.html.erb
                <% @tabs.each do |page| -%>
                    <li <%= "id='current'" if @page && (@page == page ||
@page.parent == page) %>>....</li>
                <% end -%>
Asi se las que su parent es NULL lo que quiere decir que son las
principales, las que esta condición no se cumpla, querrá decir que son
hijas
de alguna de esta.
El día 27 de mayo de 2008 18:03, Daniel Rodriguez Troitiño <
notzcoolx@yahoo.es> escribió:
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2008-05-27 18:39
(Received via mailing list)
ya se lo que quiero:
<% @tabs.each do |page| -%>
                    <li <%= "id='current'" if @page && (@page == page ||
@page.parent == page) %>>....</li>
                <% end -%>

si te fijas, lo que me hace falta es averiguar a cual de las paginas
padre
pertenece la pagina en la que me encuentro y una vez sabiendolo, la
asigno a
una variable:

@el_principal_de_mi_pagina_actual
<% @tabs.each do |page| -%>
                    <li <%= "id='current'" if @page && (@page == page ||
@page.parent == page || @el_principal_de_mi_pagina_actual == page )
%>>....</li>
                <% end -%>

Espero se entienda, lo que no se es como retroceder desde la pagina que
estoy hasta saber cual es su tab principal


y esta variable la meto en las condiciones de arriba para determianr
cual de
las principales es la que debe de llevar id="current"

El día 27 de mayo de 2008 18:20, Andrés gutiérrez
<andresgutgon@gmail.com>
escribió:
5c15703984caa012845b3cea129da936?d=identicon&s=25 Manuel González Noriega (Guest)
on 2008-05-27 18:56
(Received via mailing list)
2008/5/27 Andrés gutiérrez <andresgutgon@gmail.com>:
> ya se lo que quiero:

>
> y esta variable la meto en las condiciones de arriba para determianr cual de
> las principales es la que debe de llevar id="current"
>

No sé si exactamente se ajusta a tu problema, no me da tiempo a leer
todo el hilo, pero ¿no sería mejor que simplemente asignases ids a tus
tabs y un id o clase al body en cada página? De ese modo solucionas el
estilado sólo con css. Además de que el identificador del body te dará
oportunidad de hacer muchas más cosas

Es decir

li#foo
li#bar

body#body_foo
body#body_bar

body#body_foo li#foo, body#body_bar li#bar {
  // Estilos para #current
}



--
Manuel, que
piensa que eres una excelente persona y medra en torno a
http://simplelogica.net y/o http://simplelogica.net/logicola/
Recuerda comer mucha fruta y verdura.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2008-05-27 19:01
(Received via mailing list)
No sé si exactamente se ajusta a tu problema, no me da tiempo a leer
todo el hilo, pero ¿no sería mejor que simplemente asignases ids a tus
tabs y un id o clase al body en cada página? De ese modo solucionas el
estilado sólo con css. Además de que el identificador del body te dará
oportunidad de hacer muchas más cosas

con esto quieres decir que asigne un id por cada body-bar de cada página
que
cree??
si es esto, no me gusta la idea, ya que lo que estoy haciendo lo estoy
pillando de un tutorial que pantean la app de tal forma que pueda crear
todas las paginas
que quiera, y luego decir si esta pagina es un subpagina o si es una
principal (paren is NULL)



El día 27 de mayo de 2008 18:55, Manuel González Noriega <
manuel.gonzalez.noriega@gmail.com> escribió:
49b6123803e4f327144e991daab62f77?d=identicon&s=25 Daniel Rodriguez Troitiño (Guest)
on 2008-05-27 21:58
(Received via mailing list)
En realidad "sí" estás utilizando acts_as_tree... ¡pero te lo has
currado a mano! (bueno, excepto un par de cosas adicionales extras que
tiene acts_as_tree).

Lo más sencillo, sin casi tener que cambiar nada de tu código va a ser
que te bajes el plugin acts_as_tree y modifiques un poco tu modelo:

class Page < ActiveRecord::Base
    acts_as_textiled :body
    acts_as_tree :order => 'position'

    # Este método no lo he comprobado pero creo que debería funcionar
    def self.public_roots
      with_scope(:find => { :conditions => ['admin != ?', true] }) do
        roots
      end
    end
end

Y bueno, cambian algunos de tis métodos cambian de nombre: subpages se
convierte en children, parent sigue como parent, find_main se
convierte en roots y find_main_public se convierte en public_roots (lo
he cambiado de nombre para ajustarse a acts_as_tree).

De esta forma tendrías el método ancestors disponible (a parte de
root, siblings y self_and_siblings).

La otra es implementar el método ancestor en tu modelo. La
implementación del plugin
<http://dev.rubyonrails.org/browser/plugins/acts_as...
te sirve perfectamente (creo).

Mi recomendación, aunque implique un poco más de trabajo es que
utilices el plugin en vez de duplicar su código.

Suerte.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2008-05-28 10:04
(Received via mailing list)
Dios!!!
que bueno eres, me ha funcionado. No se casi nada, pero he conseguido
que
funcione!!!!
Te confieso que no he implementado acts_as_tree, porque todavía estoy
aprendiendo y siguiendo los tutoriales más o menos al pie de la letra,
pero a veces, me pregunto cosas y quiero saber como se podría hacer.
Este
caso es uno de esos casos.
Te explicaré (aunque seguro que se puede, que tu sabes, se puede hacer
mejor) como lo he hecho (PARA LA VIDA REAL USARÍA el PLUGIN)
pero para aprender, esto que he hecho me vale y me sobra.

Bien, al lio. Siguiendo tu link [1] y no haciendote caso :-), he cogido
un
metodo del plugin, el que me interesaba
1- Lo he pegado en mi application.rb

before_filter :get_root
  def get_root

    @page = Page.find_by_name(params[:name])
    if @page != NIL
        @root = @page
         @root = @root.parent while @root.parent
         @root
     end
   end

y luego he usado @root en mi application.html.erb
<% @tabs.each do |page| -%>
      <li <%= "id='current'" if @page && (@page == page || @page.parent
==
page || @root == page) %>>.....</li>
<% end -%>

de esta forma tengo los tabs principales siempre iluminados cuando
navego
hacia abajo dentro de ellos.

Gracias, de verdad. Era exactamente lo que quería. Aunque sea una
porquería
de codigo, lo importante es que funciona!!!

Un saludo


[1]
http://dev.rubyonrails.org/browser/plugins/acts_as...

El día 27 de mayo de 2008 21:58, Daniel Rodriguez Troitiño <
notzcoolx@yahoo.es> escribió:
49b6123803e4f327144e991daab62f77?d=identicon&s=25 Daniel Rodriguez Troitiño (Guest)
on 2008-05-28 10:21
(Received via mailing list)
2008/5/28 Andrés gutiérrez <andresgutgon@gmail.com>:
>         @root = @page
>          @root = @root.parent while @root.parent
>          @root
>      end
>    end

El método root (o como lo quieras llama) estaría mejor situado en el
modelo Page. Ahí, en el controlador, no sirve para mucho más que para
lo que lo utilizas, y ya
está.
> y luego he usado @root en mi application.html.erb
> <% @tabs.each do |page| -%>
>       <li <%= "id='current'" if @page && (@page == page || @page.parent ==
> page || @root == page) %>>.....</li>
> <% end -%>
>

Metiendo el método en el modelo Page esa parte del código te quedaría:

<% @tabs.each do |page| -%>
  <li <%= 'id="current"' if @page && (@page == page || @page.parent ==
page || @page.root == page) %>>...</li>
<% end -%>

Bueno, aún no entiendo bien qué tabs quieres destacar: el que estás,
el que estás y todos sus antecedentes, el padre de primer nivel... Si
es esto último únicamente necesitarías la última parte del OR (la de
@page.root == page), pero lo que estoy un poco seguro de que es
innecesaria es la de @page.parent == page.

Suerte.
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2008-05-28 11:13
(Received via mailing list)
pero lo que estoy un poco seguro de que es
innecesaria es la de @page.parent == page.

Ahora que tengo lo de root si claro

 >>El método root (o como lo quieras llama) estaría mejor situado en el
>>modelo Page. Ahí, en el controlador, no sirve para mucho más que para
>>lo que lo utilizas, y ya está
Lo he puesto asi en page.rb
    def root

    @page = Page.find_by_name(params[:name])

        @root = @page
         @root = @root.parent while @root.parent
         @root
     end
Pero me da este ERROR:

undefined local variable or method `params'


¿como puedio saber lo que vale @page desde el modelo?

Antes de ponerlo en Page.rb, lo he usado en el controlador de pages tal
cual
lo tenía en applicaton.rb y me ha funcionado, pero en el modelo, me peta

UN SALUDO
C9d9473fe763d83ddb95650a3b64726e?d=identicon&s=25 Fernando Martinez (nanonano)
on 2008-05-28 12:12
(Received via mailing list)
lo que tienes que hacer, es en le controlador, donde llamas al metodo
root, pasarle el params como parametro, y en el modelo definir el metodo
root con un parametro, más o menos así:

en el modelo :
 Page.root params[:name]

y en el controlador:

def root name

  @page = Page.find_by_name(name)

  @root = @page
  @root = @root.parent while @root.parent
  @root
end

ten en cuenta que en los modelos no puedes acceder a la variable params,
pero siempre puedes pasarsela a los metodos como un parametro.
Suerte.
El mié, 28-05-2008 a las 11:13 +0200, Andrés gutiérrez escribió:
C9d9473fe763d83ddb95650a3b64726e?d=identicon&s=25 Fernando Martinez (nanonano)
on 2008-05-28 12:18
(Received via mailing list)
perdón , al reves:
en el controlador :
 Page.root params[:name]

y en el modelo:

def root name

  @page = Page.find_by_name(name)

  @root = @page
  @root = @root.parent while @root.parent
  @root
end

El mié, 28-05-2008 a las 12:11 +0200, fernando.martinezgil escribió:
49b6123803e4f327144e991daab62f77?d=identicon&s=25 Daniel Rodriguez Troitiño (Guest)
on 2008-05-28 12:29
(Received via mailing list)
2008/5/28 fernando.martinezgil <fernando.martinezgil@colabora.es>:
>  @root = @page
>  @root = @root.parent while @root.parent
>  @root
> end
>

No necesitas pasar parámetros de un lado a otro, al fin y al cabo el
parámetro que mandas es el objeto que recibe el mensaje:

class Page
#...
def root
  root = self
  root = root.parent while root.parent
  root
end
#...
end

Suerte.
C9d9473fe763d83ddb95650a3b64726e?d=identicon&s=25 Fernando Martinez (nanonano)
on 2008-05-28 13:02
(Received via mailing list)
tienes razón, no tienes que hacer el find pues ya tienes el objeto..
ni me fije en para que estaba usando el params...
la próxima vez estaré más atento ;)
El mié, 28-05-2008 a las 12:27 +0200, Daniel Rodriguez Troitiño
escribió:
Adce10d7f1dbabcdab8f525a59cec32f?d=identicon&s=25 Andrés Gutiérrez (andresgutgon)
on 2008-05-28 14:54
(Received via mailing list)
Muchas gracias a los dos. Gracias por la lección

Un saludo

El día 28 de mayo de 2008 13:01, fernando.martinezgil <
fernando.martinezgil@colabora.es> escribió:
This topic is locked and can not be replied to.