Notes posted to Ruby on Rails

RSS feed
September 13, 2008
0 thanks


Some usages:

Code example

Time.new.months_ago(1) # => Wed Aug 13 10:56:32 -0300 2008

Date.today.month_ago(7) # => Qua, 13 Fev 2008

Time.new.months_ago(1).to_s(:db) # => “2008-08-13 10:57:56”

September 11, 2008 - (<= v2.1.0)
4 thanks

Information on 'ModelName.transaction'

If you are looking for information about:

ModelName.transaction do


transaction do

see ActiveRecord::Transactions::ClassMethods

September 11, 2008 - (<= v2.1.0)
4 thanks

Information on 'ModelName.transaction'

If you are looking for information about:

ModelName.transaction do


transaction do

see ActiveRecord::Transactions::ClassMethods

September 11, 2008
1 thank

CSS columns

You can also use this in a partial to create blocks of content into columns without setting a fixed height. This one is two columns.

.clear { clear: both;}
.block { float:left;width:200px;}

<div class="block">

<p>Content Item</p>

<%= cycle("", "<div class=\"clear\"></div>") -%>
September 10, 2008
4 thanks

Be careful with overriding dynamic attribute based finders

don’t try something like this:

class Foo < ActiveRecord::Base
  def self.find_by_bar(*args)
    foo = super(*args)
    raise SomeCustomException unless foo

In newer versions of rails, method_missing defines find_by_bar when you first use it. By calling super, you’re triggering method_missing and overwriting your custom definition! It will work the first time then break! Manually write the call to find!

September 9, 2008 - (<= v2.1.0)
4 thanks

Reset a form

To reset a form easily you can do the following:

September 5, 2008
6 thanks

Custom collection local variable name

Regarding the previous note from hoodow about using :variable_name to create a custom local variable name when rendering a collection with a partial, the argument should be :as instead of :variable_name, so:

render :partial => “video_listing”, :collection => @recommendations, :as => :video

September 5, 2008 - (v1.0.0 - v2.0.3)
3 thanks

This method has moved

To help anyone else looking, this method is now on the ActionView::Template class.

September 4, 2008
5 thanks

Testing protected controllers

When testing controllers which are protected with #authenticate_or_request_with_http_basic this is how you can supply the credentials for a successful login:

@request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("username:password")

Must be set before the request is sent through #get or whatever method.

September 3, 2008
1 thank

Creating additional cache stores

This method can be used to create additional cache stores for your application:

# creates a new Memory Store
mem_store = ActiveSupport::Cache.lookup_store
# creates a new MemCache Store
mem_cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store, 'localhost:11212', :namespace => 'other_stuff'

The method takes the same arguments as the cache_store config. For more information about that go to ActionController::Caching.

September 2, 2008
5 thanks

Useful in migrations

The most common usage pattern for this method is probably in a migration, when just after creating a table you want to populate it with some default values, eg:

class CreateJobLevels < ActiveRecord::Migration
  def self.up
    create_table :job_levels do |t|
      t.integer :id
      t.string :name


    %w{assistant executive manager director}.each do |type|
      JobLevel.create(:name => type)

  def self.down
    drop_table :job_levels
September 1, 2008 - (>= v2.1.0)
5 thanks


From Rails 2.1 onwards, the variable


affects how the JSON is generated. If this is true (default), then the JSON isn’t like the one above. Instead you’ll get:

konata = User.find(1)
# => { "user": { "id": 1, "name": "Konata Izumi", "age": 16,
      "created_at": "2006/08/01", "awesome": true}}

(Note the model name is included as a root of the JSON object)

For Rails 2.1 generated projects, you’ll see this in the config/initializers/new_rails_defaults.rb file. You’ll need to set the value to false if you want the old behaviour.

ActiveRecord::Base.include_root_in_json = false
August 29, 2008
10 thanks

Always pass a block

I highly recommend always taking a block and passing it back up the chain if you use alias_method_chain, even if the original method does not. Otherwise you’re keeping anyone later in the chain from adding support for blocks.


August 29, 2008
6 thanks

Brazilian Real (R$ 1.200,95)


def number_to_currency_br(number)
  number_to_currency(number, :unit => "R$ ", :separator => ",", :delimiter => ".")
August 28, 2008
10 thanks

Get year to show in descending order (Today to 1920 for example)

The way people think of time start and end would be 1920 to today. This made me think “but I want it show the current year first then down.” Well it’s as simple as swapping the start_year and end_year.

date_select :date, :start_year => Date.current.year, :end_year => 1920

# => 2008, 2007, 2006, 2005 ... 1920
August 28, 2008
3 thanks

Moved to ActiveRecord::Calculations::ClassMethods

It appears that this method has simply been moved to the module ActiveRecord::Calculations::ClassMethods. You can still use the example listed in the docs here, it will simply call the method ActiveRecord::Calculations::ClassMethods#count.

August 28, 2008 - (v2.1.0)
3 thanks

When using RESTful routes

I had issues using expire_page with RESTful controllers when expiring anything other than the index action because I was basing my expire_page calls off this example.

The solution is to use my_resource_path for example when User with id 5 is updated, you would have to do:

expire_page user_path(user) # or
expire_page formatted_user_path(user, :xml)

This may apply to early versions but I have only tested on v2.1.0

August 27, 2008
2 thanks


In Edge Rails you can do something like this to change the local variable name when rendering a collection:

render :partial => “video_listing”, :collection => @recommendations, :variable_name => “video”

August 27, 2008
16 thanks

Only attr_accessible attributes will be updated

If your model specified attr_accessible attributes, only those attributes will be updated.

Use attr_accessible to prevent mass assignment (by users) of attributes that should not be editable by a user. Mass assignment is used in create and update methods of your standard controller.

For a normal user account, for example, you only want login and password to be editable by a user. It should not be possible to change the status attribute through mass assignment.

class User < ActiveRecord::Base
  attr_accessible :login, :password

So, doing the following will merrily return true, but will not update the status attribute.

@user.update_attributes(:status => 'active')

If you want to update the status attribute, you should assign it separately.

@user.status = 'active'
August 26, 2008
6 thanks

Prototype hinted_text_field application_helper

Place this in your helper. It will show a message inside the text box and remove it when someone clicks on it. If they don’t enter a value when they leave the field it’ll replace the message. (Requires javascript :defaults).

def hinted_text_field_tag(name, value = nil, hint = "Click and enter text", options={})
  value = value.nil? ? hint : value
  text_field_tag name, value, {:onclick => "if($(this).value == '#{hint}'){$(this).value = ''}", :onblur => "if($(this).value == ''){$(this).value = '#{hint}'}" }.update(options.stringify_keys)

# inside form_for example

hinted_text_field_tag :search, params[:search], "Enter name, brand or mfg.", :size => 30  
# => <input id="search" name="search" onblur="if($(this).value == ''){$(this).value = 'Enter name, brand or mfg.'}" onclick="if($(this).value == 'Enter name, brand or mfg.'){$(this).value = ''}" size="30" type="text" value="Enter name, brand or mfg." />
August 26, 2008
11 thanks

Customizing prompt

The :prompt option not only accepts a boolean value. It can also be given a string to define another than the standard prompt ‘Please select’. Referring to the example it could read:

collection_select(:post, :author_id, Author.find(:all),
                  :id, :name_with_initial,
                 {:prompt => 'Please select the author of this post'})
August 25, 2008 - (v1.1.6 - v2.1.0)
3 thanks

Delete collections with check box tags

Following autonomous’ directions works wonders on /edit but needs slight modifications when dealing with pagination on /index.

In a /index type listing page we can no longer assume that the list of ids coming back represents changes to all objects so we need to provide some context, that the list of object modifications in our params array is a list of modifications for some set of objects.

We can only assume subsets because pagination or filtering may reduce the set of objects we’re working on.

In our case we had a user management page which listed all users and showed whether they were activated or not. The following code is what we used to ensure that modifications to the first page of objects wouldn’t affect all the other pages.


<% @users.each do |user| %>
  <%= hidden_field_tag('seen[]', user.id) -%>
  <%= check_box_tag 'activated[]', user.id -%>
<% end %>


def index
  if request.post?
    activated_ids = params[:activated].collect {|id| id.to_i} if params[:activated]
    seen_ids = params[:seen].collect {|id| id.to_i} if params[:seen]

    if activated_ids
      seen_ids.each do |id|
        r = User.find_by_id(id)
        r.activated = activated_ids.include?(id)
August 25, 2008 - (>= v2.1.0)
6 thanks

Rake tasks for gem dependencies

You can manage installation and other tasks for these dependencies with rake tasks, for example:

rake gems:install              # Installs all required gems for this application
rake gems:unpack               # Unpacks the specified gem into vendor/gems

To get all rake tasks about gems:

rake -T gems
August 25, 2008 - (v2.1.0)
5 thanks

Disable default date

If you want a date selector that initially doesn’t have a date selected you can pass it the option :include_blank.

date_select("project", "due_date", :include_blank => true)
August 25, 2008
5 thanks

%w(true false) != [true, false]

Don´t confuse the right:

validates_inclusion_of :published, :in => [true, false]

with the wrong:

validates_inclusion_of :published, :in => %w(true false)


%w(true false) == ["true", "false"]
August 23, 2008
3 thanks

Include two level has many model example

class Issue < ActiveRecord::Base

  has_many :journals

class Journal < ActiveRecord::Base
  belongs_to :issue
  has_many :details, :class_name => "JournalDetail", :dependent => :delete_all

class JournalDetail < ActiveRecord::Base
  belongs_to :journal


issue = Issue.find(:first, :include => {:journals => :details}

log record follow:

SELECT * FROM `issues` LIMIT 1
SELECT `journals`.* FROM `journals` WHERE (`journals`.`journalized_id` IN (1) and `journals`.`journalized_type` = 'Issue' AND (dustbin <> 1))
SELECT `journal_details`.* FROM `journal_details` WHERE (`journal_details`.journal_id IN (1,2,876177898,935815637))

when execute follow code, then not build sql sentent:

August 22, 2008
4 thanks

Doesn't add an index

Typically you will want to have an index on foreign keys but this method doesn’t assume that. Outside of the create_table block you should follow this with add_index :

add_index :table_name, :goat_id
# and, if polymorphic:
add_index :table_name, :goat_type
August 22, 2008
2 thanks

Response to created_at/created_on and find(:first).map

A couple of comments on the comments:

The created_at/created_on thing clearly relates to the columns that have been defined in your model – it’s got nothing to do with Rails 2.1 (although the Rails 2 “timestamp” method adds the created_at column).

And find(:first), find(:last) return model objects, rather than arrays/result sets, which is why you can’t do a map on them – you can’t do anything that you would do on an Enumerable, unless the model object itself is Enumerable.