Notes posted to Ruby on Rails

RSS feed
September 16, 2012
This note might be spam Show
September 11, 2012 - (>= v3.1.0)
1 thank

Custom serialization

It is possible to supply a class with own (de)serialization logic to the serialize call. Given object must respond to load and dump calls.

Following example serializes symbols into their string representation and store them in database as raw strings instead of their YAML representation, i.e. :pumpkin would be stored as ‘pumpkin’, and not as ‘--- :pumpkin\n’


clas SomeModel < ActiveRecord::Base
  class SymbolWrapper
    def self.load(string)

    def self.dump(symbol)

  serialize :value, SymbolWrapper
September 5, 2012 - (v3.2.1 - v3.2.8)
1 thank


Note that in the example shown in the documentation, `user.assign_attributes({ :name => ‘Josh’, :is_admin => true })` would raise a `ActiveModel::MassAssignmentSecurity::Error` and would not actually update user.name, contrary to what the example seems to demonstrate.

September 5, 2012 - (>= v3.0.0)
0 thanks

Don't allow mass assignments on model

To block all mass assignments on a model, it’s as simple as having an empty list of accessible attributes.

class Users < ActiveRecord::Base
   attr_accessible #none
August 30, 2012
3 thanks


In Rails 3.X console:

August 30, 2012
0 thanks

How to handle dynamic controller class evaluation based on params

Possible with following snippet of code (for instance if each branch has some different controller logic, but if the controller is not present, it should fallback to default controller).

Advantages are so we do not have to make blank inherited controllers and routes for them, to do it with plain inheritance.

class ActionDispatch::Routing::RouteSet::CustomDispatcher < ActionDispatch::Routing::RouteSet::Dispatcher
  # These are the controllers that we should attempt fallbacks on
  FALLBACK_CONTROLLERS = /customer\/branch\/(projects|events)$/

  def controller(params, default_controller=true)
    # This defines when we want to attempt fallbacks pattern
    super unless params[:branch_id] && params[:controller].try(:match, FALLBACK_CONTROLLERS)
    controller_param = params[:controller]

    # Having these supplied, we handle controller evaluation by our own method...
    controller_reference_with_fallbacks(params[:branch_id], controller_param)
  rescue NameError => e
    raise ActionController::RoutingError, e.message, e.backtrace if default_controller


  def controller_reference_with_fallbacks(branch_id, controller_param)
    # This is how fallbacks are evaluated       
    controller_name = "#{controller_param.sub('/branch', "/branch/#{branch_id}").camelize}Controller"

    controller = ActiveSupport::Dependencies.reference(controller_name)

    rescue NameError => e  # If there is no specific class for given branch, fallback to original class

ActionDispatch::Routing::Mapper::Mapping.class_eval do

  # We do overwrite dispatcher class, that is used to evaluate controller classes from params
  def app
        to.respond_to?(:call) ? to : ::ActionDispatch::Routing::RouteSet::CustomDispatcher.new(:defaults => defaults),
August 24, 2012
0 thanks

Specify :host option in emails

Emails need a fully qualified URL (with domain). Use the :host parameter.

But note also that you need to specify a value that is not dependent upon the request context. http://api.rubyonrails.org/classes/ActionMailer/Base.html recommends setting a default host in application.rb For those of us who have development, test, staging and production environments, set in the environment-specific files, or in the :default hash in the mailer.

This applies to both +url_for(:host => “example.com”)+ and when using named routes as in +widgets_url(:host => “example.com”)+

August 22, 2012 - (>= v3.0.0)
0 thanks

Rails Guides

There is an excellent guide on the use of this method located here:


August 22, 2012 - (v3.2.8)
0 thanks

Using Amazon Simple Email Service with ActionMailer

First of all, get all the necessary SES credentials and verify your email address.

Then, just edit your config/environments/*.rb files:

config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
    address: 'email-smtp.us-east-1.amazonaws.com',
    user_name: 'your-ses-smtp-user-name',
    password: 'your-ses-smtp-password',
    authentication: :login,
    enable_starttls_auto: true

And that’s it!

August 22, 2012
0 thanks

in rails3 StatusCodes have been moved to Rack::Utils

in rails3 StatusCodes have been moved to Rack::Utils

August 20, 2012
0 thanks

To use class attribute with a hash

You can use a setter with merge:

self.settings = settings.merge(key => value)
August 19, 2012
0 thanks

On destroying data

Reply to tvle83 and pgmcgee: the destructiveness of this method depends on your database. Some databases are better at converting between disparate types than others. For example, when changing a column from a numeric type to a string type, some databases drop the data where others will turn the numbers into their string representations.

Essentially, YMMV.

August 3, 2012
0 thanks

a misprint?

In section ‘Bi-directional associations’ an example:

d = Dungeon.first

t = d.traps.first

d.level == t.dungeon.level # => true

d.level = 10

d.level == t.dungeon.level # => false

Then use has_many associations, but lower than written ‘for belongs_to associations has_many inverse associations are ignored.’

July 24, 2012
1 thank

rest of code is in Object#try

The logic for #try is shared between this method and Object#try – “Show source” here doesn’t show the whole story. Both methods are currently implemented in the file activesupport/lib/active_support/core_ext/object/try.rb .

July 24, 2012
3 thanks

rest of code is in NilClass#try

If you click “Show source” here, you may get confused. The logic for #try is shared between this method and NilClass#try . Both versions are currently implemented in the file activesupport/lib/active_support/core_ext/object/try.rb .

July 23, 2012
0 thanks



# Method using returning can replaced
def foo
  returning Hash.new do |h|
    h[:foo] = "bar"
# By method using tap  
def foo
  Hash.new.tap do |h|
    h[:foo] = "bar"
July 20, 2012
1 thank

Skipping validation - follow up

For Rails 2.x use #save(false) for Rails 3.x use #save(:validate => false)

July 20, 2012
0 thanks

Set ids when using a collection of values (cont.)

Regarding schmidt’s post.

The following will not have the expected behavior:

<% Car.each do |c| %>
  <%= check_box_tag "car_ids[]", c.id, :id => "car_ids_#{c.id}" %>
<% end %>

But, if you put the “checked” option to false (or true), it will.

<% Car.each do |c| %>
  <%= check_box_tag "car_ids[]", c.id, false, :id => "car_ids_#{c.id}" %>
<% end %>
July 20, 2012 - (v3.0.0 - v3.2.3)
2 thanks

Changing the Message

For Change the default message:

Code example

validates :invoice_number, :presence => {:message => 'The invoice number must be informed.'}
July 12, 2012
1 thank

conditional rescue_from

Would it be possible to do something like:

rescue_from Exception, :with => my_handler, :unless => request.local?
July 10, 2012
0 thanks

Checking content_for

@tordans You asked your question 3 years ago, but in any case, should anyone have that same issue, you can manage that with:

- unless content_for(:footer).blank?
- else
  == render "layouts/footer_big"

content_for(:x) defaults to an empty string, that’s why you need to check for blank? not nil?.

July 9, 2012
0 thanks

this has been deprecated; replace with Memoist

In Rails 3.2, memoize has been deprecated. In edge Rails, it has been removed.

The commit when it was deprecated: http://github.com/rails/rails/commit/36253916b0b788d6ded56669d37c96ed05c92c5c

A Stack Overflow question about this change: http://stackoverflow.com/q/9132197/578288

I personally disagree with the removal of memoize, and don’t recommend using the `||=` pattern Rails now suggests. The exception is if your entire program only memoizes something once or twice, so it’s not worth including a gem for.

The easiest way to keep using memoize is to use the Memoist gem (http://github.com/matthewrudy/memoist , http://rubygems.org/gems/memoist), which is a simple extraction of ActiveSupport::Memoizable into its own gem.

June 25, 2012 - (<= v2.3.8)
0 thanks

Adding Additional Parameters to form_for

If you want to add additional parameters to the form_for helper, but still want to use one form for both your “create” and your “update” actions, you can add the additional parameters to the :url option, but you need to omit the :controller and :action keys.

form_for(@user, :url => {:param1 => "value1", :param2 => "value2"}) do |f|


form_for([@post, @comment], :url => {:param1 => "value1", :param2 => "value2"}) do |f| 

where param1 and param2 are not :controller or :action

June 20, 2012 - (v2.2.1 - v3.2.3)
1 thank

Another usage example

given: order active record class with “state” string field

class Order < ActiveRecord::Base
  def state
    @state ||= ActiveSupport::StringInquirer.new(read_attribute(:status))

order = Order.new(state: "initial")
order.state.initial? #=> true
order.state.paid? #=> false
June 20, 2012 - (>= v3.0.0)
1 thank

add_to_base in Rails 3

In addition to stevo’s note, in Rails 3 you can also do:

model_instance.errors.add(:base, "Msg") 
June 15, 2012 - (<= v3.2.3)
1 thank

Month-first date string no longer parses correctly

The following date format won’t be parsed correctly:


Use this instead:

Date.strptime("6/15/2012", '%m/%d/%Y')
June 13, 2012
0 thanks

Example of usage


str = ActiveSupport::StringInquirer.new('test')

str.test? # => true
str.foobar? # => false
June 7, 2012 - (>= v3.2.3)
2 thanks

:disable_with is deprecated

Or you can use this way:

<%= submit_tag "Login", data: { disable_with: "Please wait.." } %>
June 5, 2012
1 thank

:disable_with is deprecated

Since version 3.2.5 you should not use :disable_with.

Use this:

<%= submit_tag "Login", 'data-disable-with' => "Please wait.." %>