Flowdock

Recent good notes

RSS feed
April 25, 2012 - (>= v3.1.0)
5 thanks

HTML5 data- attributes using RESTful approach

HTML5 specifies extensible attributes like data-foo=“bar” (or as in Twitter Bootstrap data-toggle=“modal”), which poses two problems for Rails.

First, if you’re using symbol notation in link_to to specify attributes, this fails (dash is not a valid symbol character), so

Invalid!

link_to "Edit", @user, :class => "btn", :data-toggle => "modal"

There are two solutions:

  1. put the symbols in quotes,

  2. use the special :data hash

Solution 1: Quote Symbols

link_to "Edit", @user, :class => "btn", "data-toggle" => "modal"

Solution 2: Use the :data hash

link_to "Edit", @user, :class => "btn", :data => {:toggle => "modal"}

Resulting HTML

<a href="/users/1" class="btn", data-toggle="modal">Edit</a>

The second is minimally documented, but as a hash, can accept multiple values and is perhaps a little cleaner

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 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
June 4, 2011 - (>= v3.0.0)
4 thanks

finding without default scopes in rails 3

if you want to find without default scopes in rails 3 and with_exclusive_scope is giving you protected method errors in controllers, use unscoped for a similar purpose

May 23, 2011 - (>= v3.0.5)
5 thanks

Change to the way the block is handled

At least in 3.0.5, some of the previous examples no longer work: ActionView seems to quietly ignore Array content.

If you were using code of the form

content_tag(:li, nil, :class => 'someClass') {
  arr.collect { |x|
    content_tag(:ul, x)
  }
}

it now needs to look like

content_tag(:li, nil, :class => 'someClass') {
  arr.reduce('') { |c, x|
    c << content_tag(:ul, x)
  }.html_safe
}
March 3, 2011
5 thanks

Using namespaces

If you are using a namespace in your routes.rb, for example:

namespace :admin do
  resources :products
end

then you can:

url_for([:admin, @product])

and:

url_for([:edit, :admin, @product])
February 22, 2011
5 thanks

Passing arguments to block

To pass arguments to block being captured, just list them as capture method params. I.e.

def export(exportable, export_klass, options={}, &block)
  result = ""
  #...
  if block_given?
    result += capture(my_custom_var_i_want_to_pass_to_block, &block)
  end
  result
end

Then simply…

 <%= export(@a, @b) do |my_custom_var| %>
  <% if my_custom_var.nil? %>
    My custom var is nil!!!
  <% end %>
<% end %>
February 21, 2011 - (>= v3.0.0)
6 thanks

case-insensitive uniqueness

For case-insensitive uniqueness:

validate :username, :uniqueness => {:case_sensitive => false}
December 10, 2010 - (>= v3.0.0)
3 thanks

complex conditions

If you need add complex conditions you can use this:

Model.where(:foo => 'bar').where(:attr => 1).update_all("author = 'David'")
December 8, 2010 - (>= v3.0.0)
3 thanks

helpers using options for select

You can now add html options to select options by creating a container with items like the following:

Code Example

['display','value',:class => 'option_class']

This will produce:

Code Example

<option value="value" class="option_class">display</option>
November 9, 2010
8 thanks

NOT Equivalent to Array#reject!

@tadman is wrong. There is a difference and, trust me, it can bite:

1.9.2 > [1,2,3,4].delete_if {|x| x > 10}
 => [1, 2, 3, 4] 
1.9.2 > [1,2,3,4].reject! {|x| x > 10}
 => nil 

That is, if reject! hasn’t rejected anything, it returns nil.

October 26, 2010
3 thanks

Polymorphic has_many within inherited class gotcha

Given I have following classes

class User < ActiveRecord::Base
end

class ::User::Agent < ::User
 has_many :leads,  :as => :creator
end

I would expect, that running

User::Agent.first.leads

will result in following query

SELECT "leads".* FROM "leads" WHERE ("leads".creator_id = 6 AND "leads".creator_type = 'User::Agent')

however it results in

SELECT "leads".* FROM "leads" WHERE ("leads".creator_id = 6 AND "leads".creator_type = 'User')

Possible solutions:

  • Make User class use STI - polymorphic relations will then retrieve correct class from :type field (however in my situation it was not an option)

  • If You do never instantiate User class itself, mark it as abstract

class User < ActiveRecord::Base
 self.abstract_class = true
end
  • If You do instantiate User class, as last resort You can overwrite base_class for User::Agent

class ::User::Agent < ::User
 has_many :leads,  :as => :creator

 def self.base_class
  self
 end
end
  • If none of above is an option and You do not care that You will lose some of relation’s features, You can always

class User::Agent < ::User
 has_many :leads,
          :as => :creator,
          :finder_sql => %q(SELECT "leads".* FROM "leads" WHERE ("leads".creator_id = #{id} AND "leads".creator_type = 'User::Agent'))
end
October 20, 2010
4 thanks

use raw() instead

Don’t use this method unless you’re sure your string isn’t nil. Instead use the raw() method, which wont raise an exception on nil.

October 16, 2010 - (>= v3.0.0)
8 thanks

needs to be paired with respond_to

Needs to be paired with respond_to at the top of your class.

class MyController < ApplicationController
  respond_to :js, :html
October 13, 2010
7 thanks

Sending array parameters

Another technique to use when you need to send an array parameter is pass in the :multiple option.

check_box("puppy", "commands", {:multiple => true}, "sit", nil)
check_box("puppy", "commands", {:multiple => true}, "fetch", nil)
check_box("puppy", "commands", {:multiple => true}, "roll_over", nil)

If all checkboxes are checked, the paramters will be:

"puppy" => {"commands" => ["sit", "fetch", "roll_over"]}

NOTE: because of the gotcha, the hidden fields will be inserted and any unchecked boxes will be sent as “” (empty string). You will need to filter those values out in your model:

class Dog < ActiveRecord::Base
  def commands=(commands)
    commands.reject(&:blank?)
  end
end
October 9, 2010
4 thanks

Be Advised

Also may convert original string into Jamaican.

e.g.

"green moon".squeeze  #=> "gren mon"
August 25, 2010 - (>= v2.3.8)
8 thanks

Undocumented :inverse_of option

Support for the :inverse_of option was backported to 2.3.6+.

Here’s the description from the original commit: http://github.com/rails/rails/commit/ccea98389abbf150b886c9f964b1def47f00f237


You can now add an :inverse_of option to has_one, has_many and belongs_to associations. This is best described with an example:

class Man < ActiveRecord::Base
  has_one :face, :inverse_of => :man
end

class Face < ActiveRecord::Base
  belongs_to :man, :inverse_of => :face
end

m = Man.first
f = m.face

Without :inverse_of m and f.man would be different instances of the same object (f.man being pulled from the database again). With these new :inverse_of options m and f.man are the same in memory instance.

Currently :inverse_of supports has_one and has_many (but not the :through variants) associations. It also supplies inverse support for belongs_to associations where the inverse is a has_one and it’s not a polymorphic.

August 25, 2010 - (>= v2.3.8)
7 thanks

Undocumented :inverse_of option

Support for the :inverse_of option was backported to 2.3.6+.

Here’s the description from the original commit: http://github.com/rails/rails/commit/ccea98389abbf150b886c9f964b1def47f00f237


You can now add an :inverse_of option to has_one, has_many and belongs_to associations. This is best described with an example:

class Man < ActiveRecord::Base
  has_one :face, :inverse_of => :man
end

class Face < ActiveRecord::Base
  belongs_to :man, :inverse_of => :face
end

m = Man.first
f = m.face

Without :inverse_of m and f.man would be different instances of the same object (f.man being pulled from the database again). With these new :inverse_of options m and f.man are the same in memory instance.

Currently :inverse_of supports has_one and has_many (but not the :through variants) associations. It also supplies inverse support for belongs_to associations where the inverse is a has_one and it’s not a polymorphic.

August 25, 2010 - (>= v2.3.8)
3 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
end

class Child < ActiveRecord::Base
  belongs_to :parent
  validates_presence_of :parent
end
August 13, 2010
9 thanks

add_to_base in Rails 3

use

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

instead of depracated

model_instance.errors.add_to_base("Msg")

for Rails 3

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:

Article.unscoped

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

July 29, 2010
4 thanks

Getting (n..end) reloaded

You can do

array[n..-1]
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 16, 2010
3 thanks

to set NULL => NO

use :null => false

change_column :my_table, :my_column, :integer, :default => 0, :null => false
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
June 18, 2010
6 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
May 31, 2010
4 thanks

Naming fragment cache

One of the common ways of using fragment caching is to cache content that’s shared across the site (eg. left navigation, menus, widgets etc.) that looks and works the same regardless of the name of the action or controller calling it. In such cases it’s very easy to just use named fragment caching eg.:

<% cache('left_nav') do -%>
  <%= display_left_nav -%>
<% end -%>
April 16, 2010
5 thanks

Require file from the same folder

If you want to require file from the same folder, the simplest way is

require File.expand_path('../file-to-require', __FILE__)

If your file is /lib/book.rb

File.expand_path('../page', '/lib/book.rb') => '/lib/page.rb'