Here is a list of quick tips that I find helpful using Ruby and Rails, inspired by the Railscasts Contest
1. Access view helpers from the console
Sometimes I need a quick reminder of the syntax of view helpers – like is it truncate(length, text) or truncate(text, length)? When this happens I just fire up a script/console and use the “helper” method. For example:
1 2 |
helper.truncate "Big sentence", 5 => "Bi..." |
2. Word Wrap
Speaking of view helpers, you probably know about pluralize, truncate and simple_format, but did you know that rails can word wrap for you? Frequently I find that I have a column of text that just doesn’t look good when some lines are a lot longer than others, and I need to have more fine-grained control over the output. Word wrap comes to the rescue. You can test this in script/console by doing the following:
1 2 3 |
text = "This is some very very long text that needs to be word wrapped" helper.word_wrap text, 50 => "This is some very very long text that needs to be\nword wrapped" |
Notice that it inserts a newline, not a br element. If you want to convert that newline to an html br element, you can always use simple_format. What I particularly like about word_wrap is that it only breaks on whitespace characters, so you’ll never end up with a half-word.
3. Partial Counter
Let’s say you need to render a partial for a collection, and that you need to generate a sequential number that can’t be inferred from the database, like “Post #0, Post #1, Post #2” etc. where the numbers will always start with 0 and always be sequential. To start you might try something like this:
1 2 3 |
@posts.each_with_index do |post, index| render :partial => "post", :object => post, :locals => {:index => index} end |
Then from your partial, you would reference it like:
1 |
Post #<%= index %> |
However, if you render a partial from a collection, Rails keeps track of the index for you auto-magically, in a local variable named partial_counter (in this case it would be post_counter). Refactored, it would look like this:
1 |
render :partial => @posts |
And from the partial itself:
1 |
Post #<%= post_counter %> |
Remember that partial_counter is zero-based. For regular partials, called with just an object, it will return 0.
4. Keep selects and model validations in sync with constants
The problem: you have a field in your model that validates_inclusion_of some array of values. You want to provide a dropdown list in your UI that matches these values, but provides a human readable description beyond what “humanize” can provide.
The solution: Constants. Create a constant in your model that has a hash with the names and the descriptions like so:
1 2 3 4 |
class Page < ActiveRecord::Base VISIBILITIES = {"Anyone can see it"=>"public", "Nobody can see it"=>"private"} validates_inclusion_of :visibility, :in => VISIBILITIES.values end |
Notice how you can validate the inclusion of the field just in the values. Then in the view just add a select field helper and pass it the constant:
1 |
select :page, :visibility, Page::VISIBILITIES |
This keeps the code simple, readable and DRY.
5. Safely render environment-specific content
I like to use google analytics to keep track of my client’s site visitors. However, I don’t want to track my development machine, or the staging version of the site – just the production site. Rails makes this easy by making the RAILS_ENV environmental variable available. So anywhere in your rails app you can execute code conditionally – like this snippet from a view:
1 2 3 |
<%- if "production" == RAILS_ENV -%> some google analytics javascript... <%- end -%> |
If you’re not careful, however, you can actually change the rails environment! Take this snippet of code, for example:
1 2 3 |
<%- if RAILS_ENV = "development" -%> output some super-secret code trace... <%- end -%> |
Can you spot what’s wrong? Notice the ”=” instead of the ”==” – when the view execute this code it will actually change the rails_env to development, potentially wreaking all kinds of havoc on your app. In script/console this outputs a warning, and I haven’t tried it on production mode, but just to be safe always put the “production” part before the RAILS_ENV part – even if you forget an ”=” it will just throw an error.
Another great use of this is creating a banner to alert users to what environment they are looking at. Since staging sites often look exactly like production sites, I like to output a banner at the top of my page to say “hey – you’re on the staging site”. In my application.html.erb file I often have the following snippet:
1 2 3 4 5 |
<%- unless 'production' == RAILS_ENV -%> <div style="padding:.5em;font-weight:bold;text-align:center;background:orange;"> YOU ARE CURRENTLY ON THE <%= RAILS_ENV.upcase %> SITE </div> <%- end -%> |
In edge rails this is a little easier with the Rails object – stay tuned for more on that later.
6. Locals with default values in partials
You can pass locals to partials, making partials very flexible. But sometimes you want to be able to optionally pass a local variable to a partial. You can accomplish this a variety of ways, but my favorite is just to use a simple ||= block at the top. For example if you have an optional “author” local you want to pass in, you can just write:
1 2 |
<%- author ||= nil -%> Written by <%= author %> |
The added benefit of this method is that the partial is self documenting, since you see all of the optional locals you can pass into it right at the top. You can optionally add comments for the required locals as well – depending on how busy you like your partials to be.
Thanks for the tips, specially the optional locals variables in partial.
Fours tip is nice, but usually it is desirable to have values sorted in some human-defined order, it’s quite hard with Hash#values
If order is important to you, you can use an array as well.
VISIBILITIES = [[“Anyone can see it”,”public”], [“Nobody can see it”,”private”]]
Thanks for the excellent tips. Thanks also for your examples on Github. I learn a lot from them!
for the optional locals – checkout http://gmarik.blogspot.com/2007/09/rails-optional-locals-values-in.html