Testimony Part IV: Catching up….
First, let’s cover the layout changes. As we all know, when it comes time to render a view, Rails will look for a layout of the same name, unless otherwise directed. The layout that’s being used here is called testimonial.rhtml, lives in the views/layouts folder and looks something like the following:
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"> <head> <meta http-equiv=\"content-type\" content=\"text/html;charset=UTF-8\" /> <title>Testimonial: <%= controller.action_name %></title> <%= stylesheet_link_tag 'scaffold' %> <%= stylesheet_link_tag 'testimony' %> </head> <body> <div id=\"wrap\"> <div id=\"banner\" > <p>Testimonials</p> </div> <!-- banner --> <div id=\"content\"> <p style=\"color: green;\"><%= flash[:notice] %></p> <%= yield %> </div> <!-- content --> </div> <!-- wrap --> </body> </html>
What I’ve done here is add a wrapper div around all of the page content so that we can easily establish a fixed-width body (line 10). I’ve also added a banner div (lines 11-13) with some text inside to act as a banner. When this app is deployed, this div will be replace with a snazzy graphic, complete with all of the web 2.5 decorations.
Note the lack of inline styling… all the CSS relating to this page are in two files, scaffold.css and testimonial.css. Note how easy Rails makes it to add another stylesheet… no path information hardcoded in the link (line 7). CSS files in a Rails application are assumed to be in public/css. Line 15 starts our content div; this section of the page is where our generated content goes. The call to yield on line 17 is where the magic happens - whatever content our view generates will be inserted right there. Oh, and one more thing; I’ve set the page to have a minimum height of 700px but to get it to work on IE6, I had to use the min height fast hack (with credit to Dustin Diaz of course!). I’ve kept the base css file that was generated as part of the scaffolding for now but it will be merged into our main css file at some point.
On to the content changes now. Back in Part II when discussing the partial _form.html, we had a problem where if we removed the approved fields, we’d have no way for Julie (our site owner, see Part III) to approve or disapprove testimonials. Well, now that we have a user model, we can address this issue now.
<%= error_messages_for 'testimonial' %> <!--[form:testimonial]--> <p><label for=\"testimonial_email\">Email</label><br/> <%= text_field 'testimonial', 'email' %></p> <p><label for=\"testimonial_testimony\">Testimony</label><br/> <%= text_area 'testimonial', 'testimony' %></p> <% if logged_in? %> <p><label for=\"testimonial_approved\">Approved</label><br/> <select id=\"testimonial_approved\" name=\"testimonial[approved]\"><option value=\"false\">False</option><option value=\"true\">True</option></select></p> <% end -%><!--[eoform:testimonial]-->
Look at line 8.. if our user is logged in, we show the dropdown for changing the approved status of the testimonial. If the user is not logged in, it won’t be shown as all. Remember that in this application, only administrators can log in.
As I mentioned earlier, the main page no longer displays the testimonials in the default table layout that the scaffold script generated for us. I created a new view called all.rhtml that displays each approved testimonial in a nice div all to itself, one after another:
<h2>Look what our customers are saying!</h2>
<% for testimonial in @testimonials %>
<% if testimonial.approved? -%>
<div class=\"testimonial\">
<h5>On <%=h testimonial.created_on.strftime(\"%B %d %Y\") -%>, <%=h testimonial.email -%> said:</h5>
<p><%=h testimonial.testimony %></p>
<% if logged_in? -%>
<div class=\"tools\">
<p><%= link_to 'Edit', :action => 'edit', :id => testimonial %>
<%= link_to 'Destroy', { :action => 'destroy', :id => testimonial }, :confirm => 'Are you sure?', :method => :post %>
</p>
</div>
<% end %>
</div>
<% end %>
<% end %>
<%= link_to 'Previous page', { :page => @testimonial_pages.current.previous } if @testimonial_pages.current.previous %>
<%= link_to 'Next page', { :page => @testimonial_pages.current.next } if @testimonial_pages.current.next %>
<br />
<%= link_to 'Add your testimonial', :action => 'new' %>
Line 4 prevents unapproved testimonials from being output, but note the div named tools on line 9 — it’s only shown if Julie is logged in. It allows her to manage the approved testimonials without having to go to a separate administration page. I think it’s a nice usability feature.
I didn’t have to add any methods to TestimonialController to fetch the data that backs this view. I used the existing list method but rendered the new show_all template by changing TestimonialController:Index. However, if I want an action for show_all, then I need to write one. Fortunately, we have a nice DRY codebase to use.
def index
list
render :action => 'all'
end
def all
list
end
I’m keeping the list view around for use in the administrative interface. We’ll get to that later.
That’s about it for now. Next time, we’ll make our display a little friendlier to our users and not so friendly for email harvesting bots by adding the customer’s name to the testimonial object and not displaying the email address on the non-administrative pages.
Oh, keep those comments coming! They’re a great help to keep this series focused on what you want it to cover.
Filed under: Rails, walkthrough

Leave a Reply