Frage

Ich habe ein Ruby-/ Rails-Anwendung, die zwei oder drei „Abschnitte“ hat. Wenn ein Nutzer dieser Abschnitt möchte ich einige Unternavigation angezeigt werden soll. Alle drei Abschnitte verwenden das gleiche Layout, so kann ich nicht „hard-Code“ die Navigation in das Layout.

kann ich von ein paar verschiedene Methoden denken, dies zu tun. Ich denke, um ich Leute stimmen zu helfen, werden sie als Antworten setzen.

Jede andere Ideen? Oder was für Sie stimmen?

War es hilfreich?

Lösung

Sie können dies mit partials leicht tun, jeden Abschnitt vorausgesetzt, es hat seinen eigenen Controller.

Angenommen, Sie haben drei Abschnitte genannt Beiträge , Nutzer und Admin , die jeweils mit einem eigenen Controller. PostsController, UsersController und AdminController

In jedem entsprechenden views Verzeichnis deklarieren Sie eine _subnav.html.erb Teil:

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

In jedem dieser Unternavigation partials erklären Sie die Optionen spezifisch für diesen Abschnitt, so /users/_subnav.html.erb könnte enthalten:

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

Während /posts/_subnav.html.erb könnte enthalten:

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

Schließlich, sobald Sie dies getan haben, müssen Sie nur die Unternavigation teilweise in das Layout aufzunehmen:

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

Andere Tipps

  1. Partial machen . Dies ist sehr ähnlich wie die Hilfsmethode, außer vielleicht das Layout einig, wenn Aussagen haben würde, oder dass an einen Helfer abgehen ...

Wie für den Inhalt Ihrer Untermenü man es in einer deklarativen Weise in jedem Controller gehen kann.

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

Nun, wenn Sie menu_items aus einer Ansicht aufrufen, werden Sie die richtige Liste haben für die spezifische Controller iterieren.

Das erscheint mir als eine sauberere Lösung als diese Logik Innenansicht Vorlagen setzen.

Beachten Sie, dass Sie auch eine Standard deklarieren möchten (leer?) Menu_items innerhalb Application auch.

Achtung: Erweiterte Tricks vor

Render sie alle . Wie bitte diejenigen, die Sie nicht brauchen, CSS / Javascript verwenden, die trivialerweise in einer beliebigen Anzahl von Möglichkeiten, initialisiert werden kann. (Javascript kann die URL lesen verwendet, Abfrageparameter, etwas in einem Cookie, etc. etc.) Dies hat den Vorteil, möglicherweise spielt viel besser mit Ihrem Cache (Cache, warum drei Ansichten und müssen sie dann verfallen alle gleichzeitig, wenn Sie eine cachen ?), und verwendet werden kann, eine bessere Benutzererfahrung zu präsentieren.

Beispiel: , lassen Sie uns so tun, als Sie eine gemeinsame Tableiste Schnittstelle mit Unternavigation haben. Wenn Sie den Inhalt aller drei Registerkarten machen (das heißt seine im HTML geschrieben) und verstecken zwei von ihnen, das Umschalten zwischen zwei Registerkarten ist trivial Javascript und nicht einmal getroffen dem Server . Großer Gewinn! Keine Latenz für den Benutzer. Keine Serverbelastung für Sie.

Möchten Sie ein weiterer großer Sieg ? Sie können eine Variation dieser Technik verwenden, auf den Seiten zu betrügen, das könnte aber 99% gemeinsam über Benutzer aber noch Benutzerstatus enthalten. Zum Beispiel könnten Sie eine Titelseite einer Website, die für alle Benutzer ist relativ häufig, aber sagen „Hiya Bob“, wenn sie angemeldet sind. Setzen Sie den nicht gemeinsamen Teil ( „Hiya, Bob“) in einem Cookie. Haben, dass ein Teil der Seite gelesen werden in über Javascript, um das Cookie zu lesen. Cache die gesamte Seite für alle Benutzer unabhängig von Login-Status in Seiten-Caching. Das ist buchstäblich die Lage Schneiden 70% der Zugriffe ab von der gesamten Rails auf einigen Seiten stapeln.

Wer kümmert sich, wenn Rails skaliert werden kann oder nicht, wenn Ihre Website ist wirklich Nginx dient statischen Vermögenswerte mit neuen HTML-Seiten gelegentlich geliefert bekommen von einigen Ruby on jedem tausendsten Zugang läuft oder so;)

Sie könnten so etwas wie die Navigation Plugin unter http: // rpheath. com / posts / 309-Schienen-Plugin-Navigation-Helfer

Es ist nicht Unterabschnitt macht die Navigation aus der Box, aber mit ein wenig Feintuning könnte man wahrscheinlich es einrichten etwas ähnliches zu tun.

Ich schlage vor, Sie partials verwenden. Es gibt ein paar Möglichkeiten, wie Sie darüber gehen kann. Wenn ich partials schaffen, die ein bisschen wählerisch sind, dass sie bestimmte Variablen benötigen, schaffe ich auch eine Hilfsmethode für sie.

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

Nun hat der Teil eine lokale Variable mit dem Namen menu_items, über die Sie durchlaufen können Ihren Untermenü zu erstellen. Beachten Sie, dass ich vorschlagen, eine verschachtelte Array anstelle eines Hash, weil ein Hash-Befehl nicht vorhersehbar ist.

Beachten Sie, dass die Logik der Entscheidung, welche Elemente sollten auch im Menü angezeigt werden innerhalb render_submenu sein könnte, wenn das mehr Sinn macht für Sie.

Ich fragte so ziemlich die gleiche Frage ich: Frage: Struktur von Rails Ansichten für Untermenü? Die beste Lösung wahrscheinlich war partials zu verwenden.

Es gibt eine andere Art und Weise, dies zu tun: Verschachtelte Layouts

Ich erinnere mich nicht, wo ich diesen Code so Entschuldigungen an den ursprünglichen Autor gefunden.

Erstellen Sie eine Datei nested_layouts.rb in Ihrem lib-Ordner und den folgenden Code genannt:

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

Erstellen Sie dann Ihre verschiedenen Layouts im Layout-Ordner (zB 'admin.rhtml' und 'application.rhtml').

Jetzt in Ihrem Controller fügen Sie diese nur innerhalb der Klasse:

include NestedLayouts

Und schließlich am Ende Ihres Handelns dies zu tun:

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

die Reihenfolge der Layouts in der Anordnung ist wichtig. Das Admin-Layout wird in der Anwendung des Layout gemacht werden, wo die ‚yeild‘ ist.

Diese Methode kann wirklich gut funktionieren, in Abhängigkeit von der Gestaltung der Website und wie die verschiedenen Elemente organisiert. zum Beispiel eines der mitgelieferten Layouts kann nur eine Reihe von div-Tags enthalten, die den Inhalt enthalten, die für eine bestimmte Aktion, und die CSS auf einer höheren Layout angezeigt werden muss, könnte kontrollieren, wo sie positioniert sind.

Es gibt nur wenige Ansätze für dieses Problem.

Sie möchten für jeden Abschnitt unterschiedliche Layouts verwenden.

Sie mögen vielleicht eine teilweise von allen Ansichten in einem bestimmten Verzeichnis aufgenommen verwenden.

Sie mögen vielleicht content_for verwenden, die entweder durch einen Blick oder einen Teil und rief im globalen Layout gefüllt ist, wenn Sie eine haben.

Ich persönlich glaube, dass Sie mehr Abstraktion in diesem Fall vermeiden sollten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top