Flowdock

Notes posted to Ruby on Rails

RSS feed
July 24, 2012
1 thank

rest of code is in Object#try

The logic for #try is shared between this method and Object#try – “Show source” here doesn’t show the whole story. Both methods are currently implemented in the file activesupport/lib/active_support/core_ext/object/try.rb .

July 24, 2012
2 thanks

rest of code is in NilClass#try

If you click “Show source” here, you may get confused. The logic for #try is shared between this method and NilClass#try . Both versions are currently implemented in the file activesupport/lib/active_support/core_ext/object/try.rb .

July 23, 2012
0 thanks

Replacement

Replacement

# Method using returning can replaced
def foo
  returning Hash.new do |h|
    h[:foo] = "bar"
  end
end
# By method using tap  
def foo
  Hash.new.tap do |h|
    h[:foo] = "bar"
  end
end
July 20, 2012
1 thank

Skipping validation - follow up

For Rails 2.x use #save(false) for Rails 3.x use #save(:validate => false)

July 20, 2012
0 thanks

Set ids when using a collection of values (cont.)

Regarding schmidt’s post.

The following will not have the expected behavior:

<% Car.each do |c| %>
  <%= check_box_tag "car_ids[]", c.id, :id => "car_ids_#{c.id}" %>
<% end %>

But, if you put the “checked” option to false (or true), it will.

<% Car.each do |c| %>
  <%= check_box_tag "car_ids[]", c.id, false, :id => "car_ids_#{c.id}" %>
<% end %>
July 20, 2012 - (v3.0.0 - v3.2.3)
2 thanks

Changing the Message

For Change the default message:

Code example

validates :invoice_number, :presence => {:message => 'The invoice number must be informed.'}
July 12, 2012
1 thank

conditional rescue_from

Would it be possible to do something like:

rescue_from Exception, :with => my_handler, :unless => request.local?
July 10, 2012
0 thanks

Checking content_for

@tordans You asked your question 3 years ago, but in any case, should anyone have that same issue, you can manage that with:

- unless content_for(:footer).blank?
  yield(:footer)
- else
  == render "layouts/footer_big"

content_for(:x) defaults to an empty string, that’s why you need to check for blank? not nil?.

July 9, 2012
0 thanks

this has been deprecated; replace with Memoist

In Rails 3.2, memoize has been deprecated. In edge Rails, it has been removed.

The commit when it was deprecated: http://github.com/rails/rails/commit/36253916b0b788d6ded56669d37c96ed05c92c5c

A Stack Overflow question about this change: http://stackoverflow.com/q/9132197/578288

I personally disagree with the removal of memoize, and don’t recommend using the `||=` pattern Rails now suggests. The exception is if your entire program only memoizes something once or twice, so it’s not worth including a gem for.

The easiest way to keep using memoize is to use the Memoist gem (http://github.com/matthewrudy/memoist , http://rubygems.org/gems/memoist), which is a simple extraction of ActiveSupport::Memoizable into its own gem.

June 25, 2012 - (<= v2.3.8)
0 thanks

Adding Additional Parameters to form_for

If you want to add additional parameters to the form_for helper, but still want to use one form for both your “create” and your “update” actions, you can add the additional parameters to the :url option, but you need to omit the :controller and :action keys.

form_for(@user, :url => {:param1 => "value1", :param2 => "value2"}) do |f|

or

form_for([@post, @comment], :url => {:param1 => "value1", :param2 => "value2"}) do |f| 

where param1 and param2 are not :controller or :action

June 20, 2012 - (v2.2.1 - v3.2.3)
1 thank

Another usage example

given: order active record class with “state” string field

class Order < ActiveRecord::Base
  def state
    @state ||= ActiveSupport::StringInquirer.new(read_attribute(:status))
  end
end

order = Order.new(state: "initial")
order.state.initial? #=> true
order.state.paid? #=> false
June 20, 2012 - (>= v3.0.0)
1 thank

add_to_base in Rails 3

In addition to stevo’s note, in Rails 3 you can also do:

model_instance.errors.add(:base, "Msg") 
June 15, 2012 - (<= v3.2.3)
0 thanks

Month-first date string no longer parses correctly

The following date format won’t be parsed correctly:

'06/15/2008'.to_date 

Use this instead:

Date.strptime("6/15/2012", '%m/%d/%Y')
June 13, 2012
0 thanks

Example of usage

e.g.

str = ActiveSupport::StringInquirer.new('test')

str.test? # => true
str.foobar? # => false
June 7, 2012 - (>= v3.2.3)
1 thank

:disable_with is deprecated

Or you can use this way:

<%= submit_tag "Login", data: { disable_with: "Please wait.." } %>
June 5, 2012
1 thank

:disable_with is deprecated

Since version 3.2.5 you should not use :disable_with.

Use this:

<%= submit_tag "Login", 'data-disable-with' => "Please wait.." %>
June 4, 2012
0 thanks

You can remove leading Zeros this way as well

By just adding a - symbol.

%-I %-d

June 4, 2012 - (v2.3.2 - v3.2.3)
0 thanks

This method does not work.

It’s an old problem, reported back in 2010, just reopened issue:

http://github.com/rails/rails/issues/6620

May 28, 2012
0 thanks

Accepted parameters for validate

Validate method also accepts :on and :if parameters. The default value for :on is :save, the other accepted values are :create and :update

class Comment
  include ActiveModel::Validations

  validate :must_be_friends, :on => :create, :if => Proc.new {|comment| some_condition}

  def must_be_friends
    errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee)
  end
end
May 22, 2012
0 thanks

similar to clone

See the clone documentation. I see that ActiveRecord is moving from “clone” (3.0.9) to “dup” (?).

May 18, 2012
0 thanks

Beware nested with_options clobbers!

Careful:

with_options :foo => :bar do |something|
  something.with_options :foo => :baz do |inner|
    what_is(:foo)
  end
end

:foo will be :baz. It will not be [:bar, :baz], for example.

This bit me when trying to do nested with_options for validation where both had :if => something.

May 17, 2012
0 thanks

If you try to use :id as a non-primary-key field

If you’re using this so that you can repurpose :id for another use, it gets hairy: your ActiveRecord::Base subclass will still use :id to refer to your primary key, whatever it be named.

So when you call [my obj].id = 33, 33 is set as the value of your primary key, not your :id attribute!

May 15, 2012
0 thanks

STI - Making callbacks trigger in inherited classes

Assuming we have

class ParentClass < ActiveRecord::Base
   attr_accessible :type
end

class ChildClass < ParentClass
   after_save :perform_something
end

Executing

ParentClass.create({:type => "ChildClass"})

will not trigger ChildClass callbacks. What is more, it will return instance of ParentClass instead of ChildClass.

To resolve this issue, you need to define following module

module ActiveRecord
  module CallbacksAwareSti
    extend ActiveSupport::Concern
    module ClassMethods
      def new(*args, &block)
        return super(*args, &block) unless args.first.respond_to?(:with_indifferent_access)
        type = args.first.with_indifferent_access[:type]
        if type.blank? or (type = type.constantize) == self
          super(*args, &block)
        else
          super(*args, &block).becomes(type)
        end
      end
    end
  end
end

and include it in parent class

class ParentClass < ActiveRecord::Base
   include ActiveRecord::CallbacksAwareSti
   attr_accessible :type
end

Inspired by http://stackoverflow.com/questions/4518935/activerecord-problems-using-callbacks-and-sti

May 10, 2012
0 thanks

block only and except

Code

class Journal < ActionController::Base
  # Require authentication for edit and delete.
  before_filter :authorize, :only => [:edit, :delete]

  # Passing options to a filter with a block.
  around_filter(:except => :index) do |controller, action_block|
    results = Profiler.run(&action_block)
    controller.response.sub! "</body>", "#{results}</body>"
  end

  private
    def authorize
      # Redirect to login unless authenticated.
    end
end
May 7, 2012
0 thanks

Hidden Field Example

Here’s a pseudo code example of a hidden field within an ERB template. A post has many comments and this comment form is in a post’s show view. This would set a comment’s post_id attribute.


<%= form_for(@comment) do |f| %>

<%= f.hidden_field :post_id, :value => @post.id %>

<% end %>


April 30, 2012 - (>= v3.1.0)
0 thanks

method to use instead

This may be obvious, but the replacement for this method is csrf_meta_tags.

April 27, 2012 - (>= v3.2.1)
1 thank

Example from Code School

module Tweets

 class ShowPresenter
   extend ActiveSupport::Memoizable

   def initialize(tweet)
     @tweet = tweet
   end

   def username
     @tweet.user.username
   end

   def status
     @tweet.status
   end

   def favorites_count
     @tweet.favorites.count
   end

   memoize :username, :status, :favorites_count

 end
end

From http://railsbest.com/

April 26, 2012
3 thanks
April 25, 2012 - (>= v3.1.0)
6 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