Flowdock

Good notes posted by rob-twf

RSS feed
May 27, 2009 - (>= v1_8_6_287)
3 thanks

map_with_index

If you want to access the element index when using map, you can do it with enum_for:

(1..6).enum_for(:each_with_index).map { |v, i| "index: #{i} value: #{v}" }
#=> ["index: 0 value: 1", "index: 1 value: 2", "index: 2 value: 3", "index: 3 value: 4", "index: 4 value: 5", "index: 5 value: 6"]
February 18, 2009
4 thanks

Turn off for individual controllers/actions

To disable protection for all actions in your controller use skip_before_filter:

skip_before_filter :verify_authenticity_token

You can also pass :only and :except to disable protection for specific actions, e.g:

skip_before_filter :verify_authenticity_token, :only => :index
January 16, 2009 - (>= v2.2.1)
4 thanks

Remember to mixin the ActiveSupport::Memoizable module

To use memoize in your model you need to extend the model class with the module, like this:

class Person < ActiveRecord::Base
  # Mixin the module
  extend ActiveSupport::Memoizable

  def expensive_method
    # do something that is worth remembering
  end
  memoize :expensive_method
end

If you use memoizable in most of your models you could consider mixing the module into all ActiveRecord models by doing this in an initializer:

ActiveRecord::Base.extend(ActiveSupport::Memoizable) 
November 26, 2008
10 thanks

Types array shorthand

You can have respond_to blocks that look like this:

respond_to do |format|
  format.html
  format.xml
end

Here each individual format doesn’t receive a block and so Rails automatically tries to render the appropriate view for the mime type (e.g. action.html.erb, action.xml.erb or as a last resort action.erb)

You can do exactly the same thing by passing an array of Mime types to respond_to like this:

respond_to(:html, :xml)
October 30, 2008
7 thanks

Can be extended but only with a module

Although not documented, belongs_to does support Association Extensions however it doesn’t accept a block like has_many does. So you can’t do this:

class Account < ActiveRecord::Base
  belongs_to :person do
    def do_something_funky
      # Some exciting code
    end
  end
end

but you can do this:

module FunkyExtension
  def do_something_funky
    # Some exciting code
  end
end

class Account < ActiveRecord::Base
  belongs_to :person, :extend => FunkyExtension
end

And then call it like this:

@account = Account.first
@account.person.do_something_funky
October 24, 2008
10 thanks

Back it up with a unique index

As mentioned briefly above, as well as using this validation in your model you should ensure the underlying database table also has a unique index to avoid a race condition.

For example:

class User < ActiveRecord::Base
  validates_uniqueness_of :login_name
end

The index can be specified in the migration for the User model using add_index like this:

add_index :users, :login_name, :unique => true

You do a similar thing when using the :scope option:

class Person < ActiveRecord::Base
  validates_uniqueness_of :user_name, :scope => :account_id
end

Should have a migration like this:

add_index :people, [ :account_id, :user_name ], :unique => true

Note that both the attribute being validated (:user_name) and the attribute(s) used in the :scope (:account_id) must be part of the index.

For a clear and concise explanation of the potential for a race condition see Hongli Lai’s blog.

July 21, 2008 - (v2.0.3 - v2.1.0)
10 thanks

Is it really deprecated?

I think the deprecation notice is in the wrong place, it is actually the instance method ActiveRecord::Validations#validate that has been deprecated.

The same applies to ActiveRecord::Validations#validate_on_create and ActiveRecord::Validations#validate_on_update: they have both been deprecated in favour of the class methods validate_on_create and validate_on_update.