Notes posted to Ruby on Rails

RSS feed
November 11, 2011
3 thanks

Catching and throwing -- don't!

@wiseleyb and @glosakti, neither of your suggestions are necessary, and both are bad practices.

This test:

test "transactions" do
  assert_raises ZeroDivisionError do
    User.transaction do
      1/0
    end
  end
end

passes just fine on its own, with the transaction rolled back as you’d expect. No need to hack something ugly together.

November 10, 2011
0 thanks

logic in class/id

If you need to place some simple logic in class or like that, I think that best to make it with simple brackets:

Code example

<%= link_to ‘All actions’, switch_action_tab_path, :remote => true, :class => (‘selected’ if @tab == ‘all’) %>

November 7, 2011 - (<= v3.0.9)
1 thank

unscoped.all / unscoped.count

At least in console, doing unscoped.all or unscoped.count initially returns expected results but, after you’ve added new records outside of the default_scope those two calls seem to use some cached values.

Therefore it should always be used with the block (as they sort of imply in the doc). unscoped { all } and unscoped {count }

November 6, 2011 - (>= v3.1.0)
3 thanks

Removed in 3.1.x

This method (and #auto_link_urls) has been removed in Rails 3.1 - other options are out there, such as Rinku, however there is a gem you can use for migration purposes etc, which is rails_autolink: http://rubygems.org/gems/rails_autolink

October 26, 2011
2 thanks

Adding to the URL

If you want to use polymorphic routing for your object but you also need to specify other stuff like an anchor, you can explicitly generate the polymorphic url with extra options:

form_for @candidate,
  :url => polymorphic_path(@candidate, :anchor => 'signup')
October 19, 2011 - (>= v3.0.0)
3 thanks

Replaced by :on => :create

From rails 3,

before_validation_on_create 

has been removed and replaced with:

before_validation :foo, :on => :create
October 18, 2011
0 thanks

Upgrading to 3.x

http://railscasts.com/episodes/202-active-record-queries-in-rails-3

Since this is deprecated, one can watch the Railcast for upgrading to 3.x

The equivalent is the ActiveRecord finder methods. http://apidock.com/rails/ActiveRecord/Fixture/find

October 10, 2011 - (>= v3.1.0)
1 thank

Use Ruby instead!

E.g.

class TestClass < SomeSuperClass
  attr_accessor :sample_acc

  def initialize      
    @sample_acc = []
    super
  end
end

If nil is not a valid value for this accessor, then you can just define reader for it.

class TestClass
  attr_accessor :sample_acc

  def sample_acc
    @sample_acc ||= 98
  end
end
October 8, 2011
6 thanks

Undocumented :location option

You can use undocumented :location option to override where respond_to sends if resource is valid, e.g. to redirect to products index page instead of a specific product’s page, use:

respond_with(@product, :location => products_url)  
October 7, 2011
3 thanks

How to submit current url

For example to change some kind of param on select change…

<%= form_tag({}, {:method => :get}) do %>
  <%= select_tag :new_locale, options_for_select(I18n.available_locales, I18n.locale), :onchange => "this.form.submit();" %>
<% end %>
October 4, 2011
2 thanks

How to change format automatically depending on locale...

… without passing locale option.

In your application_helper.rb (or in other helper) place following code:

def number_to_currency(number, options = {})
  options[:locale] ||= I18n.locale
  super(number, options)
end

Then, in your locale files:

en-GB:
  number:
    currency:
      format:
        format: "%n %u"
        unit: "USD"

And that is it :)

October 3, 2011
0 thanks

@Mange

If you’re actually looking to cut down on code why not use .map instead of the longer .collect?

September 30, 2011 - (>= v3.0.0)
1 thank

Using a block with image_tag

HTML5 officially supports block-level elements in the anchor tag and Rails 3 allows you to pass a block to image_tag:

<%= image_tag(some_path) do %>

<%= content_tag(:p, "Your link text here")

<% end %>

September 30, 2011 - (v3.0.0 - v3.1.0)
0 thanks

Without module

If you want to have only the path prefix without namespacing your controller, pass :module => false.

Normal:

namespace :account do
  resources :transactions, :only => [:index]
end

account_transactions GET /account/transactions(.:format)
{:controller=>"account/transactions", :action=>"index"}

With :module => false:

namespace :account, :module => false do
  resources :transactions, :only => [:index]
end

account_transactions GET /account/transactions(.:format)
{:controller=>"transactions", :action=>"index"}
September 29, 2011 - (<= v3.1.0)
2 thanks

Additional Format meaning

%e - Day of the month, without leading zero (1..31)

September 27, 2011 - (>= v3.1.0)
0 thanks

1.9 behavior

In Ruby 1.9 and newer mb_chars returns self’”

This would seem to be a lie. At least in rails 3.1.0 and ruby 1.9.2, mb_chars still returns a proxy object with additional useful methods defined on it that aren’t on a 1.9.2 String.

ruby-1.9.2-p180 :007 >  "àáâãäå".normalize(:kd)
NoMethodError: undefined method `normalize' for "àáâãäå":String

ruby-1.9.2-p180 :008 > "àáâãäå".mb_chars.normalize(:kd)
 => àáâãäå
September 25, 2011
1 thank

Parsing the Date Params into a New Date Object.

Useful for when you need to create a Date object from these manually, such as for reporting.


If the date select input is start_date and it belongs to the report form object:

@start_date = Date.civil(params[:report]["start_date(1i)"].to_i,
                         params[:report]["start_date(2i)"].to_i,
                         params[:report]["start_date(3i)"].to_i)

@start_date.class
# => Date

@start_date
# => Sun, 25 Sep 2011  # For example.

Use a similar method for DateTime situations.

September 17, 2011
0 thanks

this works, but doesn't make sense

does it?

replace(klass.find(ids).index_by { |r| r.id }.values_at(*ids))

equals

replace(klass.find(ids))

I see no point in making it that complicated

September 15, 2011
2 thanks

beware of trying to dup in subclass inside class context

The example of adding to an array without effecting superclass:

# Use setters to not propagate changes:
Base.setting = []
Subclass.setting += [:foo]

That’s right as far as it goes. But beware when you are in context of class definition:

class Subclass < Base
   # possibly wrong, ruby seems to get 
   # confused and think you mean a local 
   # var, not the class ivar
   setting += [:foo]

   # But this will work:
   self.setting += [:foo]

   # Or:
   self.setting = self.setting.dup
   self.setting << :foo

   [...]
end
September 14, 2011
0 thanks

Find a Selected Option in a Drop Down.

You can find the selected option (or options for multiple select inputs) with the following:

assert_select('select#membership_year option[selected]').first['value']
September 14, 2011
2 thanks

More on add_to_base

Actually, use

model_instance.errors.add :base, :invalid

to have I18n working.

September 13, 2011
0 thanks

more options

useful options are:

:root => ‘object’, :skip_instruct => true, :indent => 2

:builder can also be used to pass your own Builder::XmlMarkup instance.

September 13, 2011
1 thank

Some unexpected behaviour

When using Array as default value, it behaves more like cattr_accessor

class A
 attr_accessor_with_default :b, []
end

x = A.new
x.b << 1

#puts x.b.inspect => [1]

y = A.new
y.b << 2

#puts y.b.inspect => [1, 2]
September 9, 2011 - (v3.0.9)
0 thanks

Example usage...

`

Time.now.advance(:days => +2, :hours => +8)

`

September 8, 2011 - (>= v3.0.9)
0 thanks

First example simplified

The first code example may be simplified, since the call to method to_xml is made implicitly anyway:

def index
  @people = Person.find :all

  respond_to do |format|
    format.html
    format.xml { render :xml => @people }
  end
end
September 7, 2011 - (v3.0.0 - v3.0.9)
0 thanks

Tested w/ Rails 3 and returning true/false ignored

Per http://ar.rubyonrails.org/classes/ActiveRecord/Callbacks.html “If a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled.” [and presumably associated action is not canceled]

So, the callback chain will be broken, but the save will still happen.

Also ran into this: http://innergytech.wordpress.com/2010/03/08/dont-put-validations-in-after_save/

September 7, 2011 - (>= v3.0.9)
0 thanks

Passing an object as argument

It is possible to pass an instance of a record to the method. See the documentation of polymorphic_url (http://apidock.com/rails/ActionDispatch/Routing/PolymorphicRoutes).