Flowdock

Notes posted to Ruby on Rails

RSS feed
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:

helpers.label.<object_name>.<method_name>

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

activerecord.attributes.<object>.<attribute>

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:

en:
  activerecord:
    attributes:
      "content/rich_text":
        name: Page name
  helpers:
    label:
      content_rich_text:
        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.

Example:

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
3 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:

http://guides.rubyonrails.org/routing.html#using-maproot

July 16, 2010
3 thanks

to set NULL => NO

use :null => false

change_column :my_table, :my_column, :integer, :default => 0, :null => false
July 16, 2010
0 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 }
end
July 14, 2010
5 thanks

uniqueness

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

Re: IE GOTCHA

@insane-dreamer

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'
July 9, 2010 - (>= v2.2.1)
0 thanks

Separator default is not always "." but depends on locale

Locale en:

number_with_precision(111.2345)  # => 111.235

Locale fr-FR:

number_with_precision(111.2345)  # => 111,235

Same with delimiter.

July 8, 2010
0 thanks

Destroying Data

As far as I can tell, at least on a migration of a column from an integer to a decimal, this does not get rid of existing data.

July 8, 2010 - (>= v2.1.0)
0 thanks

Rails v2.1.0 has built-in time-zone support

Rails versions as of 2.1.0 have basic timezone support built-in to the Time object. However, to get a list of all the timezones you need to install the tzinfo gem.

http://tzinfo.rubyforge.org/

All contries, all timezones:

TZInfo::Country.all.sort_by { |c| c.name }.each do |c|
  puts c.name # E.g. Norway
  c.zones.each do |z|
    puts "\t#{z.friendly_identifier(true)} (#{z.identifier})" # E.g. Oslo (Europe/Oslo)
  end
end

TZInfo::TimeZone.get(identifier) returns a TimeZone -object by the identifier.

July 4, 2010
1 thank

Common use

I typically use require_dependency when developing a class or module that resides in my rails app, perhaps in the lib/ dir. A normal require statement does not reload my changes, so I use require_dependency in files that reference my newly developed class or module.

July 2, 2010
0 thanks

Takes array

Like assert_difference this method can take an array of expressions to evaluate all of them. For example:

assert_no_difference ['Publisher.count', 'User.count', 'Membership.count'] do
  post :create
end

It creates an assertion for each item in the array. So this will add three assertions to your test.

June 24, 2010
0 thanks

authenticity_token

<div style=“margin:0;padding:0”>

<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" /> 

</div>

Helper generates a div element with a hidden input inside. This is a security feature of Rails called cross-site request forgery protection and form helpers generate it for every form whose action is not “get”.

June 23, 2010
0 thanks

Getting the client ip

From CgiRequest you can get the client ip in controller:

request.remote_ip
June 23, 2010
2 thanks

Accessing controller data

You can access controller attributes from views via the @controller variable.

It has some important attributes:

  • @controller.controller_name -> the name of the controller

  • @controller.request -> returns the ActionController::Request

    • @controller.request.method -> the request method ( get, post, put, delete )

    • @controller.request.host -> the request host ( ip address or hostname ) where your server runs

    • @controller.request.ip -> the ip where your browser runs

June 23, 2010
1 thank

how I use it

def rescue_action_in_public(exception)

case exception

when ActiveRecord::RecordNotFound, ActionController::UnknownAction, ActionController::RoutingError
  redirect_to errors_path(404), :status=>301
else
  redirect_to errors_path(500)
end

end

June 18, 2010
7 thanks

multiple attributes with the same validations

You can list multiple attributes if they share the same validations

validates :title, :body, :presence => true

sending the attributes as an array will return an error

validates [:title, :body], :presence => true
#=> ArgumentError: Attribute names must be symbols
June 18, 2010
0 thanks

Careful when updating foreign key directly

Seems when you change key directly it doesn’t update association automatically.

>> chicken = Chicken.first
>> chicken.head
=> old_head
>> chicken.head_id = new_head.id
>> chicken.head
=> old_head

Easy (stupid?) way to fix it:

class Chicken
  def head_id=(value)
    self.head = Head.find_by_id(value)
  end
end
June 13, 2010 - (>= v2.3.8)
0 thanks

Positioning the column. MySQL only

Add support for MySQL column positioning via #add_column and #change_column

add_column and change_column in the MySQL adapter now accept some additional options:

:first => true # Put the column in front of all the columns

:after => column_name # Put the column after ‘column_name’

class AddLastNameToUsers < ActiveRecord::Migration
  def self.up
    add_column :users, :last_name, :after => :first_name
  end

  def self.down
    remove_column :users, :last_name
  end
end

or

class AddIdToUsers < ActiveRecord::Migration
  def self.up
    add_column :urers, :id, :first => true
  end

  def self.down
    remove_column :users, :id
  end
end