Question

J'ai une application Ruby / Rails qui comporte deux ou trois "sections" principales. Lorsqu'un utilisateur visite cette section, je souhaite afficher une sous-navigation. Les trois sections utilisent la même présentation, je ne peux donc pas "coder en dur". la navigation dans la mise en page.

Je peux penser à différentes méthodes pour le faire. Je pense que pour aider les gens à voter, je vais les mettre en réponse.

Avez-vous d'autres idées? Ou que votez-vous pour?

Était-ce utile?

La solution

Vous pouvez facilement le faire en utilisant des partiels, en supposant que chaque section possède son propre contrôleur.

Supposons que vous disposiez de trois sections intitulées Posts , Utilisateurs et Admin , chacune avec son propre contrôleur: PostsController , UsersController et AdminController .

Dans chaque répertoire views correspondant, vous déclarez un _subnav.html.erb partial:

/app/views/users/_subnav.html.erb
/app/views/posts/_subnav.html.erb
/app/views/admin/_subnav.html.erb

Dans chacune de ces sous-partitions partielles, vous déclarez les options propres à cette section. /users/_subnav.html.erb peut contenir:

<ul id="subnav">
  <li><%= link_to 'All Users', users_path %></li>
  <li><%= link_to 'New User', new_user_path %></li>
</ul>

Bien que /posts/_subnav.html.erb puisse contenir:

<ul id="subnav">
  <li><%= link_to 'All Posts', posts_path %></li>
  <li><%= link_to 'New Post', new_post_path %></li>
</ul>

Enfin, une fois cela fait, il vous suffit d’inclure le sous-fichier partiel dans la présentation:

<div id="header">...</div>    
<%= render :partial => "subnav" %>
<div id="content"><%= yield %></div>
<div id="footer">...</div>

Autres conseils

  1. Rendu partiel . Ceci est très similaire à la méthode helper sauf peut-être que la mise en page aurait des déclarations if ou les transmettrait à un helper ...

En ce qui concerne le contenu de vos sous-menus, vous pouvez y accéder de manière déclarative dans chaque contrôleur.

class PostsController < ApplicationController
#...
protected
  helper_method :menu_items
  def menu_items
    [
      ['Submenu 1', url_for(me)],
      ['Submenu 2', url_for(you)]
    ]
  end
end

Désormais, chaque fois que vous appelez menu_items depuis une vue, vous aurez la bonne liste pour parcourir le contrôleur spécifique.

Cela me semble être une solution plus nette que de placer cette logique dans les modèles de vue.

Notez que vous pouvez également déclarer un élément de menu par défaut (vide?) dans ApplicationController également.

Avertissement: astuces avancées à venir!

Rendez-les tous . Cachez ceux dont vous n'avez pas besoin avec CSS / Javascript, qui peut être initialisé de manière triviale de plusieurs façons. (Javascript peut lire l'URL utilisée, les paramètres de requête, quelque chose dans un cookie, etc.) Cela présente l'avantage de jouer potentiellement beaucoup mieux avec votre cache (pourquoi mettre en cache trois vues et les faire expirer toutes simultanément lorsque vous pouvez en mettre une en cache ?), et peuvent être utilisés pour présenter une meilleure expérience utilisateur.

Par exemple , supposons que vous ayez une interface de barre de tabulation commune avec navigation secondaire. Si vous restituez le contenu des trois onglets (c’est-à-dire qu’il est écrit en HTML) et que vous en masquez deux, basculer entre deux onglets est javascript et ne frappe même pas votre serveur . Grande victoire! Pas de latence pour l'utilisateur. Aucune charge de serveur pour vous.

Vous souhaitez une autre grande victoire ? Vous pouvez utiliser une variante de cette technique pour tricher sur des pages qui pourraient être communes à 99% entre utilisateurs mais qui contiendraient toujours un état utilisateur. Par exemple, la page d'accueil d'un site peut être relativement commune à tous les utilisateurs, mais vous pouvez indiquer "Hiya Bob". lorsqu'ils sont connectés. Placez la partie non commune ("Hiya, Bob") dans un cookie. Demandez à cette partie de la page d'être lue via Javascript en lisant le cookie. Mettez en cache la totalité de la page pour tous les utilisateurs, quel que soit leur statut de connexion dans la mise en cache des pages. : cela permet littéralement de couper 70% des accès de l'ensemble de la pile Rails sur certains sites.

Qui se soucie de savoir si Rails peut s’adapter ou non lorsque votre site Web sert réellement des actifs statiques avec de nouvelles pages HTML livrées occasionnellement par Nginx, certains Ruby fonctionnant à chaque millième d’accès environ;)

Vous pouvez utiliser le plug-in de navigation à l'adresse http: // rpheath. com / posts / 309-rails-plugin-navigation-helper

La navigation dans les sous-sections n'est pas prête à l'emploi, mais avec quelques modifications, vous pouvez probablement la configurer pour faire quelque chose de similaire.

Je vous suggère d'utiliser des partiels. Il y a plusieurs façons de s'y prendre. Lorsque je crée des partiels un peu pointilleux dans la mesure où ils ont besoin de variables spécifiques, je crée également une méthode d'assistance.

module RenderHelper
  #options: a nested array of menu names and their corresponding url
  def render_submenu(menu_items=[[]])
    render :partial => 'shared/submenu', :locals => {:menu_items => menu_items}
  end
end

Le partiel a maintenant une variable locale nommée menu_items sur laquelle vous pouvez effectuer une itération pour créer votre sous-menu. Notez que je suggère un tableau imbriqué au lieu d'un hachage, car l'ordre d'un hachage est imprévisible.

Notez que la logique permettant de choisir les éléments à afficher dans le menu peut également figurer dans le sous-menu render_si si cela vous semble plus logique.

J'ai moi-même posé à peu près la même question: Besoin de conseils: Structure des vues Rails pour les sous-menus? La meilleure solution consistait probablement à utiliser des partiels.

Il existe un autre moyen de procéder: les dispositions imbriquées

Je ne me souviens pas où j'ai trouvé ce code, donc je m'excuse auprès de l'auteur d'origine.

créez un fichier appelé nested_layouts.rb dans votre dossier lib et incluez le code suivant:

module NestedLayouts
  def render(options = nil, &block)
    if options
      if options[:layout].is_a?(Array)
        layouts = options.delete(:layout)
        options[:layout] = layouts.pop
        inner_layout = layouts.shift
        options[:text] = layouts.inject(render_to_string(options.merge({:layout=>inner_layout}))) do |output,layout|
          render_to_string(options.merge({:text => output, :layout => layout}))
        end
      end
    end
    super
  end
end

Créez ensuite vos différentes mises en page dans le dossier des mises en page (par exemple, 'admin.rhtml' et 'application.rhtml').

Maintenant, dans vos contrôleurs, ajoutez ceci juste à l'intérieur de la classe:

include NestedLayouts

Et enfin, à la fin de vos actions, faites ceci:

def show
  ...
  render :layout => ['admin','application']
end

l'ordre des présentations dans le tableau est important. La présentation de l'administrateur sera rendue dans la présentation de l'application, où que se trouve le "yeild".

Cette méthode peut très bien fonctionner en fonction de la conception du site et de la manière dont les différents éléments sont organisés. Par exemple, une des mises en page incluses pourrait simplement contenir une série de divs contenant le contenu devant être affiché pour une action particulière, et le CSS d'une mise en page supérieure pourrait contrôler leur positionnement.

Il existe peu d'approches à ce problème.

Vous pouvez utiliser différentes dispositions pour chaque section.

Vous pouvez utiliser un partiel inclus par toutes les vues d’un répertoire donné.

Vous pouvez utiliser content_for , qui est rempli par une vue ou par une vue partielle, et appelé dans la présentation globale, si vous en avez une.

Personnellement, j'estime que vous devriez éviter plus d'abstraction dans ce cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top