I was recently working on a website built using Rails that needed to render different content for certain user agents. Specifically, we needed simpler versions of certain pages for BlackBerry devices. Here's how I accomplished.
First, I added a new mime-type for BlackBerry by adding the following line to config/initializers/mime_types.rb:
Mime::Type.register_alias "text/html", :blackberry
Next, I added two utility methods to app/controllers/application.rb:
# Checks UserAgent def is_blackberry? ua = request.user_agent return false if ua.nil? return false if ! ua.downcase.index('blackberry') # Don't call the BlackBerry 9800 a BlackBerry, since it has a modern browser # based on WebKit: # Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1+ return false if ua.downcase.index('webkit') # Must be a BlackBerry! true end # Sets the respond_to format to blackberry if blackberry def set_blackberry_format if !request.xhr? && is_blackberry? request.format = :blackberry end end
With that in hand, it's easy to render BlackBerry specific content on specific pages:
set_blackberry_format respond_to do |format| format.blackberry format.html format.js { render :layout => false } end
Sometimes you just want to use an Enum. Unfortunately, if you're a Ruby developer, Ruby does not offer a native enum structure. Here's a simple approach using a mixin module:
module Enum def const_missing(key) @enum_hash[key] end def add_enum(key, value) @enum_hash ||= {} @enum_hash[key] = NameValuePair.new(value, key.to_s.downcase) end def each @enum_hash.each {|key, value| yield(key, value) } end def enums @enum_hash.keys end def enum_values @enum_hash.values end def get_enum_hash @enum_hash end def find_by_key(key) @enum_hash[key.upcase.to_sym] end end
The Enum mixin depends on a NameValuePair class to hold the data:
class NameValuePair attr_reader :label, :value def initialize(label, value) @label = label @value = value end def first @label end def last @value end end
I included first and last methods to better support the select and options_for_select helper methods in Rails. Here's how you might use it:
class FooEnum extend Enum self.add_enum(:APPLE, "Apple") self.add_enum(:PEAR, "Pear") self.add_enum(:ALL, "All Fruit") end FooEnum::APPLE ==> #<NameValuePair @value="apple", @label="Apple"> FooEnum::ALL.value ==> "all" FooEnum::ALL.label ==> "All Fruit" FooEnum.find_by_key('apple') ==> #<NameValuePair @value="apple", @label="Apple">
I found a nice little article from a few months ago on The Rails Way. Written by koz, Assocation Proxies talks about some Best Practices for using assocations within Rails. I really felt the suggestions hit the proverbial nail on the head in terms of following the DRY principles. The first suggestion was on the best way to restrict access to user specific information. It's incredibly useful to take advantage your RESTful patterns and make a single call like:
When deploying a Rails application using Capistrano, I discovered I needed a way to specify the username and password for Subversion and I didn't want to hardcode this information. I found an excellent suggestion on Jonathan.inspect. I didn't follow his advice exactly, but I ended up with something fairly close that I added to my deploy.rb script:
The basic idea is to setup one or more instances of Mongrel to handle the Ruby/Rails content and have Apache handle static content. In addition, Apache will act as a proxy and load-balance the request to Mongrel. The best resource I found was a page on Mongrel's site titled Apache Best Practice Deployment.
Here's the basics of how I set it up:
Software:
Recent comments
1 year 40 weeks ago