16: Clean-Up




Learning Rails show

Summary: <h2>Goals</h2> <p>In this lesson we’re taking a break from adding features to do a little cleanup:</p> <ul> <li>Get the page title logic out of the application layout</li> <li>Add page titles for admin and login pages</li> <li>Make navigation buttons indicate which is the current page</li> <li>Add a ‘back to previous’ navigation link on subpages</li> <li>Add a little styling to subnav links</li> <li>Set the focus for the login field</li> </ul> <p>Please note that, while we’ve tried to make these notes complete, they aren’t the full tutorial; that’s in the screencast, which you can access via the link on the left.</p> <h2>Setup</h2> <p>We begin with the code with which we ended Lesson 15. These zip files contain the beginning and ending states of the code:</p> <ul> <li><a href="/learningrails_15.zip">Learning Rails example app code as of the end of Lesson 15</a></li> <li><a href="/learningrails_16.zip">Learning Rails example app code as of the end of Lesson 16</a></li> </ul> <h2>Fix up Page Title Handling</h2> <p>Several lessons ago, as we were building the core of our content management system, we put a quick hack in the application layout (views/layouts/application.html.erb) that put this logic in the wrong place; we want to keep logic out of our views as much as practical. So let’s replace this line:</p> <pre> &lt;title&gt;&lt;%= @pagetitle || (@page &amp;&amp; @page.title) || 'Learning Rails Sample Application' %&gt;&lt;/title&gt; </pre> <p>with the much simpler:</p> <pre> &lt;title&gt;&lt;%= @pagetitle %&gt;&lt;/title&gt; </pre> <p>Now we need to set this instance variable appropriately for each view. First, in the viewer_controller show method, insert the line (after @page is set):</p> <pre> @pagetitle = @page.title </pre> <p>That takes care of all pages that come from the content management system. Now we need to take care of the admin and login pages. Add to users_controller:</p> <pre> before_filter :set_pagetitle def set_pagetitle @pagetitle = 'User Administration' end </pre> <p>This before filter will run before every action, so the page title will be set (to the same thing) for all of them.</p> <p>In page controller, we already made a very similar addition in a previous lesson, but we called it <code>set_metadata</code>, so for consistency we’ll rename it to <code>set_pagetitle</code></p> <p>Finally, the sessions controller needs some attention. Add to the (empty) <code>new</code> action in sessions_controller:</p> <pre> @pagetitle = 'Please Log In'</pre> <p>And after the <code>else</code> in the sessions_controller’s <code>create</code> method:</p> <pre> @pagetitle = "Login was not successful"</pre> <p>You could do more to customize page titles for the various admin pages, but this is enough for us.</p> <h2>Highlight Current Nav Button</h2> <p>Next problem: make the appropriate nav button highlight to indicate the current page.</p> <p>First, we need to identify which nav button to highlight by using some Ruby code to conditionally insert an ID. We’ll insert the following code in the application layout, in the <code>&lt;li&gt;</code> tag that begins each nav button:</p> <pre> &lt;li &lt;%= "id = 'current'" if @page &amp;&amp; @page == page %&gt;&gt;</pre> <p>Now we need a <span class="caps">CSS</span> rule, in public/stylesheets/learningrails.css, to style the button for the current page:</p> <pre> #navbar #current a { background-color: #000; } </pre> <p>Now the navigation button for the current page is highlighted.</p> <h2>Provide a Link Back to Parent Page</h2> <p>When we added subpages in the previous lesson, we didn’t provide any indication when you’re on a subpage as to what the parent page is. There’s several things we might do about this; here’s two possibilities:</p> <p>We could use the subnav div area to show a “Return to About Us” link, for example, on subpages of About Us. To do so, replace the code at the top of views/viewer/show.html.erb with the following:</p> <pre> &lt;% if !@subpages.empty? %&gt; &lt;div id='subnav'&gt; &lt;ul&gt; &lt;% for page in @subpages %&gt; &lt;li&gt;&lt;%= link_to page.navlabel, view_page_path(page.name) %&gt;&lt;/li&gt; &lt;% end %&gt; &lt;/div&gt; &lt;% elsif @page.parent %&gt; &lt;div id='subnav'&gt; &lt;ul&gt; &lt;li&gt;&lt;%= link_to "Return to #{@page.parent.navlabel}", view_page_path(@page.parent.name) %&gt; &lt;/li&gt; &lt;/ul&gt; &lt;/div&gt; &lt;% end %&gt; </pre> <p>If there are subpages, then this code displays the subpage nav. If not, then if there is a parent page, it displays a link back to the parent page. (Note that you’d want to do something a little different if you had multiple levels of subpages.)</p> <p>Now the subpages of About Us show the link back.</p> <h2>Add a Little Style</h2> <p>The subnav lists are pretty ugly, so let’s style them a little to make them look like buttons. Add the following to public/styles/learningrails.css:</p> <pre> #subnav { width: 160px; float: left; margin: 0 20px 50px -10px; } #subnav ul { list-style: none; font-weight: bold; font-size: 13px; margin: 0; padding: 0; } #subnav ul li { background-color: #999; border-bottom: 1px solid #333; border-top: 1px solid #333; } #subnav ul li a { padding: 5px 10px; display:block; color:white; text-decoration: none; } #subnav ul li a:hover { background-color: #333; color: #fff; } </pre> <h2>Retain Parent Button Highlight On Subpages</h2> <p>Another way we could indicate the parent page would be to keep its navigation button highlighted. We can do this with a small change to the current page id logic in the application layout, adding a test for the parent of the current page:</p> <pre> &lt;li &lt;%= "id = current" if @page &amp;&amp; (@page == page or @page.parent == page) %&gt;&gt;&lt;%= link_to page.navlabel, view_page_path(page.name) %&gt;&lt;/li&gt; </pre> <p>Now when you’re viewing one of the subpages of the About Us page, the About Us button is highlighted.</p> <p>Note that we’ve let some logic creep back into our application controller here, but it is really presentational logic, so it doesn’t feel too bad.</p> <h2>Set Form Field Focus</h2> <p>One last bit of cleanup. On our login page, it’s annoying that you can’t just begin typing; neither of the form fields have focus until you click in one of them. We can fix that by adding a little bit of JavaScript to the bottom of views/sessions/new.html.erb:</p> <pre> &lt;%= javascript_tag "$('login').focus()" %&gt; </pre> <p>And now you can start typing as soon as the login page is displayed.</p> <h2>Moving On</h2> <p>We could go on for several more lessons tuning up our little content management system, but it’s time to move on. Next lesson, we’ll create the resources database and use that to drive the Resources page.</p>