Notes posted to Ruby on Rails

RSS feed
August 25, 2010 - (>= v2.3.8)
4 thanks

Validating presence of parent in child

When creating a parent and its children using nested attributes, you can use the :inverse_of option on the association to correctly set the parent back references:

class Parent < ActiveRecord::Base
  has_many :children, :inverse_of => :parent
  accepts_nested_attributes_for :children

class Child < ActiveRecord::Base
  belongs_to :parent
  validates_presence_of :parent
August 24, 2010 - (>= v2.3.2)
0 thanks


Instead of using:


Now use:

August 16, 2010
0 thanks

update_all and serialized attributes

If you use update_all to change an attribute marked as serialized ( using ActiveRecord::Base.serialize ), you need to call to_yaml yourself:

User.update_all({ :preferences => { :first_name => 'John',
                                     :last_name  => 'Doe' }.to_yaml })
August 13, 2010
10 thanks

add_to_base in Rails 3


model_instance.errors[:base] << "Msg" 

instead of depracated


for Rails 3

August 13, 2010
0 thanks

Depracated add_to_base


model_instance.errors[:base] << "Msg" 

instead of depracated


for Rails 3

August 13, 2010
1 thank

Confusing log output

If you do a single Rails.cache.read('my_key'), your will usually see in your log something like

Cache read: my_key
Cache read: my_key
Cache write: my_key

Don’t worry about this.

What happens here is this: Before going to memcached, rails will first ask a local MemoryStore cache (which is responsible for the first and third line in the log), before falling through to memcached. This local cache is destroyed after each request.

Source is in activesupport/lib/active_support/cache/strategy/local_cache.rb.

August 11, 2010
3 thanks

In Rails3 use "unscoped" instead

The with_exclusive_scope examples no longer work in Rails3 because with_exclusive_scope is now a protected method which can and should not be used in a controller. Use the new unscoped method instead:


For mor details and examples have a look at: http://github.com/rails/rails/commit/bd1666ad1de88598ed6f04ceffb8488a77be4385.

August 9, 2010
2 thanks

When using enumerables

When using enumerables and storing them as strings in the database don’t forget to use .to_s or the select helper won’t automatically select your choice when viewing your data after save.


dates = 1900..Date.today.year
f.select(:year, dates.collect {|d| [d.to_s,d.to_s]}, {:include_blank => "Select"}, {:class => "some_class"} )
August 8, 2010
0 thanks

Path Segments

url_options Returns a hash with path segments.


{:_path_segments=>{:action=>"show", :location=>"los-angeles-ca", :controller=>"city"}, :script_name=>"", :protocol=>"http://", :host=>"localhost:3000"}
August 4, 2010 - (>= v2.0.0)
1 thank

Testing Named Scopes

Thanks for the example of testing named_scopes. Being new to Rails, I struggled to find examples that I could understand. Here is another “simple” test for a named_scope

Mine differs slightly from the one above in that I had to remove a set of {} in the :conditions in my test to avoid an “odd number list for Hash” error. I also replace the param-binding “?” with the number I expect to send in as an argument. My test would did know what args[0] was. I got an “undefined local variable” error.

The named scope in my model:

named_scope :up_to_and_including_year, lambda{ |*args| {

:conditions => [“to_char(grad_dt1,‘YYYY’) <= ?”, args[0]] }}

The test:

test "named_scope :up_to_and_including_year" do
  expected_options = { :conditions =>  ["to_char(grad_dt1,'YYYY') <= ?", '2010'] }
  assert_equal expected_options, Sso::CourseTaken.up_to_and_including_year('2010').proxy_options
August 3, 2010
1 thank

Inverse function

String#underscore is inverse for the camelize.

“active_record”.camelize.underscore # => “active_record”

August 2, 2010
0 thanks

assert_select negative with regex

(also, you can use instance vars)

assert_select "div#event_#{assigns[event].id}", { :count => 0, :html => /something/ }
August 2, 2010 - (<= v2.3.8)
1 thank

label DOES translate

Maybe it used to not translate but I know it does as of 2.3.8. It is first lookup on the key:


If that doesn’t return anything it will use the human_attribute_name method on ActiveRecord::Base to translated which uses:


I generally use both of these keys even when I don’t want to translate but just to have a single place where all my adjusted labels are stored.

If any form will need to use the same adjustment given the same object and attribute then I put in on the activerecord key. If the adjustment is form specific then I put it on the helpers key. Here is an example from real working code:

        name: Page name
        testimonial_enabled: Enabled

Note that my AR object is a namespaced object (Content::RichText). In the activerecord key I need to change this to content/rich_text so if can find the correct key and put it in quotes to make it valid YAML. At the helper level on the other hand the namespace simply becomes an _.

July 26, 2010 - (<= v2.3.8)
2 thanks

:confirm, :popup, and :method override :onclick

upplying any combination of :confirm, :popup, and/or :method options to the link_to method results the :onclick option being overridden.


link_to "Delete", '#', :confirm=>"Are you sure?", :onclick=>"destroyJsFunction()"
# expected output
# => <a href="#" onclick="if(confirm('Are you sure?')) {destroyJsFunction()}; return false;">Delete</a>
# actual output
# => <a href="#" onclick="return confirm('Are you sure?');">Delete</a>

Note that the actual output doesn’t include any mention of the “destroyJsFunction()” passed to the link_to method.

Rails 3 will use unobtrusive JavaScript, and I haven’t tested how that will interact with the :onclick option.

July 26, 2010
0 thanks

Using strings as association names - beware of HashWithIndifferentAccess

If you merge a normal Hash into a HashWithIndifferentAccess, then the keys will convert to strings…

This will likely bite you if the merge is passed to AR find: as netmaniac said “Beware, that using strings as association names, when giving Hash to :include will render errors”.

Beware that params from your controller are HashWithIndifferentAccess like.

July 24, 2010
2 thanks

If your add_index is being ignored in your migration, see this

My add_index command was producing no change in my MySQL 5.0 database:

add_index :designations, [ :scope_type, :scope_id, :role_id, :user_id ], :unique => true

By just adding an index name, the problem was solved:

add_index :designations, [ :scope_type, :scope_id, :role_id, :user_id ], :unique => true, :name => 'my_index'

This happens when the autogenerated index name gets too long. For more info see:

July 23, 2010
2 thanks

To use in testing

If you want to use this in a test, add the following to test_helper.rb:

include ActionDispatch::TestProcess

(If using factory_girl, you can call it in your Factory, like so:

f.photo { fixture_file_upload 'test.png', 'image/png' }
July 23, 2010
3 thanks

Moved in Rails 3

In Rails 3, this has moved to ActionDispatch::TestProcess

(Which means, if you want to use it in a test, you need to add the following to test_helper.rb:)

include ActionDispatch::TestProcess
July 20, 2010
4 thanks

When scripts don't end in .js

For example, Google Custom Search’s URL is http://www.google.com/jsapi

It’s an ugly hack, but works:

= javascript_include_tag('http://www.google.com/jsapi').sub('.js', '')
July 20, 2010 - (>= v1.2.6)
0 thanks
July 17, 2010
0 thanks

redirect_to :root

You can redirect to your main page using

redirect_to :root

Make sure to configure to root route first:


July 16, 2010
4 thanks

to set NULL => NO

use :null => false

change_column :my_table, :my_column, :integer, :default => 0, :null => false
July 16, 2010
2 thanks

Changing to MySql:BIGINT

I can change a column type from INT to BIGINT with this command:

change_column :my_table, :my_column, :bigint
July 15, 2010 - (<= v2.3.8)
2 thanks
July 15, 2010
0 thanks

Doesn't output into STDOUT

Oddly enough it runs a rake task without any sort of output. To get around it you can simple substitute it with:

puts run('rake your_task')

Unless somebody has a better idea?

July 14, 2010
2 thanks
July 14, 2010
0 thanks

If you need to pass a value

In the above example ‘value’ happens to be either true or false depending if the option was passed in or not. If you wish to capture an actual value you’ll want something like this:

def add_options!(opt)
  opt.on('-option=value') { |value| options[:option] = value }
July 14, 2010
6 thanks


You can scope uniqueness as well

validates :user_name, :presence => true, :uniqueness => {:scope => :account_id}

# the old way  
validates_uniqueness_of :user_name, :scope => :account_id
July 14, 2010
1 thank
July 10, 2010
2 thanks



That has nothing to do with IE. When you specify :cache => true you are saying that the files referenced should be saved to a file called all.js. When the script encounters the next line, it will overwrite the same file with the new contents.

Caching is not compressing, it doesn’t make sense to do with individual files, but it can make sense some times. I someone wants to do it, just specify a name for the cached file:

javascript_include_tag 'layout', 'typography', :cache => 'base'
javascript_include_tag 'admin/layout', 'admin/extras', :cache => 'admin'