Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Luke Redpath http://www.lukeredpath.co.uk

« Newer Snippets
Older Snippets »
Showing 1-4 of 4 total  RSS 

Accessing Subversion repository information in Ruby

   1  
   2  require 'yaml'
   3  svn_info = YAML.load(`svn info /my/working/copy`)
   4  puts svn_info['URL']
   5  #=> "svn://some-remote-repository.com/svn"
   6  puts svn_info['Revision']
   7  #=> "133"


Should also work with svk info as well. Credit to htonl in #caboose for the YAML tip.

Helper to display Rails flashes

If you use the convention of using :notice, :warning and :error with your flashes, then this simple helper will allow you to display your flashes easily, and it supports the storage of ActiveRecord::Errors in flash[:error] as well.

   1  
   2    def display_standard_flashes(message = 'There were some problems with your submission:')
   3      if flash[:notice]
   4        flash_to_display, level = flash[:notice], 'notice'
   5      elsif flash[:warning]
   6        flash_to_display, level = flash[:warning], 'warning'
   7      elsif flash[:error]
   8        level = 'error'
   9        if flash[:error].instance_of? ActiveRecord::Errors
  10          flash_to_display = message
  11          flash_to_display << activerecord_error_list(flash[:error])
  12        else
  13          flash_to_display = flash[:error]
  14        end
  15      else
  16        return
  17      end
  18      content_tag 'div', flash_to_display, :class => "flash #{level}"
  19    end
  20  
  21    def activerecord_error_list(errors)
  22      error_list = '<ul class="error_list">'
  23      error_list << errors.collect do |e, m|
  24        "<li>#{e.humanize unless e == "base"} #{m}</li>"
  25      end.to_s << '</ul>'
  26      error_list
  27    end

Using Ruby hashes as keyword arguments, with easy defaults

Similar to many Rails helpers/methods, a lot of the methods I write often use an optional hash of options, or sometimes just a hash only, to simulate keyword arguments (often using symbols).

The only downside to doing this is you lose out on easily setting default values using Ruby's default method argument values. You might use code something similar to the following to make up for this:

   1  
   2  def some_method(opts={})
   3    my_foo =  opts[:foo] || 'mydefaultfoo'
   4  end


However, as you have more and more keyword options, setting defaults in this way gets rather tedious. Fortunately, Ruby's Hash#merge comes to our rescue (almost) - it allows you to merge the contents of one hash with another. The only problem - any duplicate keys in the hash you are merging will overwrite your original hash values - when it comes to setting default values, we want this to work the other way around; we only want values in the defaults hash to be merged if they do not exist in the original hash. Again, Ruby comes to our rescue - Hash#merge takes a block as an argument and will pass any duplicate values that crop up into the block - we can use this block to decide which value to keep.

Using the simple monkey patch to the Hash class below, you will no longer have to set each default individually:

   1  
   2  class Hash
   3    def with_defaults(defaults)
   4      self.merge(defaults) { |key, old, new| old.nil? ? new : old } 
   5    end
   6  
   7    def with_defaults!(defaults)
   8      self.merge!(defaults) { |key, old, new| old.nil? ? new : old }
   9    end
  10  end


Of course, sticking with Ruby naming conventions, with_defaults() will return a new hash whilst with_defaults!() will change the original hash directly.

See http://www.lukeredpath.co.uk/index.php/2006/07/27/using-ruby-hashes-as-keyword-arguments-with-easy-defaults/ for further discussion and alternatives.

Creating navigation bars with current section highlight in Rails

UPDATE: I have since packaged this functionality up as a Rails plugin - more information can be found at http://opensource.agileevolved.com

*THE CODE BELOW HAS BEEN DISCOVERED TO HAVE PROBLEMS RUNNING IN PRODUCTION MODE - THIS HAS BEEN FIXED IN THE PLUGIN VERSION OF THIS SNIPPET. PLEASE SEE THE URL ABOVE*

There are many ways of creating navigation bars using XHTML and CSS but the most common method is to create an unordered list of links which are then formatted in a variety of ways using CSS. There are also many ways of highlighting the tab for the current page, some using server-side logic, some using CSS.

This method enables you to create as many navigation lists as you like in your Rails views, giving each navigation list a unique ID which is then referenced using a simple macro in your controller to set the highlighted link.

First of all, we have the main helper function that lets us create our navigation lists - add the following to your application helper:

   1  
   2  def navigation_list(links, options={})
   3    link_html = ''
   4    links.each do |link|
   5      class_name = 'navlink'
   6      class_name << ' current' if current_section(options[:id], link[:text])
   7      link_html << content_tag('li', link_to(link[:text], link[:url]),
   8        :id => "nav_#{link[:text].rubify}", :class => class_name)
   9    end
  10    content_tag('ul', link_html, :id => "navbar_#{options[:id]}" || 'navigation')
  11  end
  12  
  13  private
  14    def current_section(navigation_id, link_text)
  15      link_name = link_text.rubify.to_sym
  16      navigation_id = navigation_id.rubify.to_sym
  17      return true if (@controller.current_section?(navigation_id, link_name))
  18    end


As a small aside, you'll notice the above code relies on a small extension to the Ruby String class - create a file called string.rb to your Rails lib/ folder and add the following monkey patch:

   1  
   2  class String 
   3    def rubify
   4      self.downcase.strip.gsub(' ', '_')
   5    end
   6  end


Some of the above functionality will become apparent later, but essentially what it does is take an array of links in a specific format (see below) and turn them into an unordered list of links. The function takes an optional :id parameter (which otherwise defaults to 'navigation') which is used as both the HTML ID on the UL element and as an identifier when using the navigation mappings functionality below. Each LI element is given a class of 'navlink' and also a class of 'current' if it is the current link (see below). This provides plenty of hooks for styling in your CSS.

Here is an example usage of the above function:

   1  
   2  <%=	navigation_list [
   3  		{ :text => 'Dashboard', :url => { :controller => 'dashboard' },
   4  		{ :text => 'Admin', :url => { :controller => 'admin', :action => 'login' } }
   5  	], :id => 'main_nav' %>


The :text key is the actual link text, and the :url key is the standard set of Rails url_for options. You can create as many of these navigation lists on a page as you want - just be sure to give each one a unique ID.

The other step is to create a way of storing your "navigation mappings" - a hash of navigation list to current link pairs. Add the following to your ApplicationController:

   1  
   2  @@navigation_mappings = {}
   3  
   4  def self.navigation_section(mapping)
   5    @@navigation_mappings.merge!(mapping)
   6  end
   7    
   8  def current_section?(navigation_id, link_name)
   9    return (@@navigation_mappings[navigation_id] == link_name)
  10  end


You can use the navigation_section macro to specify which link to set as current for a particular navigation list. Using the example navigation list above, if we wanted to set the Dashboard link as current for all the actions in our DashboardController, we would add the following to our controller code:

   1  
   2  class DashboardController < ApplicationController
   3    navigation_section :main_nav => :dashboard
   4  end


Again, you can add as many navigation_section declarations to your controller if you have many navigation lists on your page that you want to control. The key is the ID of the navigation list and the value is a symbol version of the particular link text - for example, 'This is a link' would become :this_is_a_link.

Adding this mapping will add a 'current' class to the LI element for that particular link - you can now use this in your stylesheet to style the current page link appropriately.
« Newer Snippets
Older Snippets »
Showing 1-4 of 4 total  RSS