Flowdock

Recent notes

RSS feed
November 7, 2008
2 thanks

Parsing YAML from a POST request

When building a REST server which should accept YAML there are several things to take into consideration.

First of the client should tell the server what type of data it is going to send. This is done via the Content-Type header (which is NOT only a response header as opposed to what the RESTful Web Services book from O’Reilly made us believe).

Second the server application should know how handle the body of the POST request. Placing the following line in your environment.rb:

ActionController::Base.param_parsers[Mime::YAML] = :yaml

This registers the YAML parser. Smooth sailing from here on!

November 7, 2008
3 thanks

Add spacer template

<%= render :partial => “product”, :collection => @products, :spacer_template => “product_ruler” %>

November 6, 2008 - (v1_8_6_287)
1 thank

Missing Documentation

Returns false if obj <=> min is less than zero or if anObject <=> max is greater than zero, true otherwise.

3.between?(1, 5)               #=> true
6.between?(1, 5)               #=> false
'cat'.between?('ant', 'dog')   #=> true
'gnu'.between?('ant', 'dog')   #=> false
November 6, 2008
4 thanks

current_url

exact url from browser window:

def current_url
  url_for :only_path=>false,:overwrite_params=>{}
end
November 6, 2008
1 thank

Compiling mysql gem in Leopard with MacPorts MySQL

Needs architecture and reference to mysql_config:

sudo env ARCHFLAGS="-arch i386" gem install mysql -- \
--with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config
November 5, 2008
2 thanks

Rendering YAML

When you want to render XML or YAML you can use

render :xml, some_object.to_xml 

or

render :json, some_object.to_json

However there is no equivalent for YAML. What you can do is render just plain text with a correct content-type:

render :text => some_object.to_yaml, :content_type => 'text/yaml'

The content_type is debatable but this seems to be the most standard.

November 5, 2008
0 thanks

re: james' note incorrect

kieran is correct, my note is incorrect, it was not meant for ActionMailer::Base

November 5, 2008 - (v1.0.0 - v2.1.0)
1 thank

james' note incorrect

The render method in ActionMailer is infact a private method, in all versions (including the new Rails 2.2).

However, spectators note about @template works well. Thanks.

November 5, 2008
0 thanks

RERE: 1 render definition for many actions (cleaner)

@arronwashington. Ah, so that’s the motivation for using default_render, thanks for clearing that up, thanks :)

November 4, 2008
2 thanks

RE: 1 render definition for many actions (cleaner)

Hi James,

Unfortunately that doesn’t work if you use the

@zombies 

variable in the rendered template, which is why default_render was added as a patch AFAIK. :)

before_filter is called too soon, after_filter is called after an attempt at rendering is made, so default_render is the only option for this as far as I know.

November 4, 2008
0 thanks

re: Specifying :include no longer necessarily joins the association

I have seen how :include does not nessisarily perform a join during that SQL query, if you need the join to occur then, rather then tricking AR (“forcing”), use :joins instead of :include to ensure the joins occur.

November 4, 2008 - (v1.0.0 - v2.1.0)
1 thank

1 render definition for many actions (cleaner)

@arronwashington, you can just call render rather then using instance_eval to overwrite default_render, for example:

before_filter :render_filter, :only => [:zombies, :cool_zombies]

def zombies
  @zombies = Zombie.find(:all)
end

def cool_zombies
  @zombies = Zombie.find(:all, :conditions => { :eats_humans => false, :is_hippie => true })
end

protected

def render_filter
  # without instance_eval or overwriting default_render
  render :template => 'zombies/all'
end
November 4, 2008
0 thanks

1 render definition for many actions.

Overriding default_render in especially useful when you have many actions that all render the same thing.

before_filter :render_filter, :only => [:zombies, :cool_zombies]

def zombies
  @zombies = Zombie.find(:all)
end

def cool_zombies
  @zombies = Zombie.find(:all, :conditions => { :eats_humans => false, :is_hippie => true })
end

protected

def render_filter
  instance_eval do
    def default_render
      render :template => 'zombies/all'
    end
  end
end
November 2, 2008
2 thanks

params hash gets the model id automatically

The params hash gets automatically populated with the id of every model that gets passed to form_for. If we were creating a song inside an existing album:

URL:/albums/209/songs/new
form_for [@album, @song] do |f| 
  ...
  f.submit "Add"
end

The params hash would be:

params = {"commit"=>"Add", 
          "authenticity_token"=>"...",
          "album_id"=>"209",
          "song"=>{"song_attributes"=>{...}}
          }

So, in the songs_controller you could use this album_id in a before_filter:

before_filter :find_album
protected
def find_album
  @album = Album.find(params[:album_id])
end

If you only did this:

form_for @song do |f| 

You would get this params hash:

params = {"commit"=>"Add", 
          "authenticity_token"=>"...",
          "song"=>{"song_attributes"=>{...}}
          }  
November 2, 2008 - (v1_8_6_287)
1 thank

The reverse operation of split is join.

Given that String#split returns an array, its reverse operation is Array#join. Example:

"life is awesome".split
=>["life","is","awesome"]

["life","is","awesome"].join(" ")
=>"life is awesome"
October 31, 2008
0 thanks

By images's sub dirctionary to img tag

image_tag(“icons/edit.png”) # =>

<img src="/images/icons/edit.png" alt="edit" />
October 30, 2008
2 thanks

re: Customizing attribute names in error messages

You can use Module.alias_attribute to achieve the same result as overriding human_attribute_name. After aliasing use the new name in the validates_xxxx_of methods or ActiveRecord::Errors.add.

October 30, 2008
0 thanks

Anyone know the order the scopes assemble conditions?

It seems like last scope = first condition in sql. Can anyone confirm?

October 30, 2008
1 thank

can be useful to achieve attr_reader effect

e.g.

class Account < ActiveRecord::Base 

  def credit(amount)
    self.write_attribute(:balance, self.balance + amount)
    self.save!
  end

  def balance=(value)
    raise "You can't set this attribute. It is private."
  end

end

this allows fred.account.credit(5) whilst raising an error on fred.account.balance = 1000

October 30, 2008
7 thanks

Can be extended but only with a module

Although not documented, belongs_to does support Association Extensions however it doesn’t accept a block like has_many does. So you can’t do this:

class Account < ActiveRecord::Base
  belongs_to :person do
    def do_something_funky
      # Some exciting code
    end
  end
end

but you can do this:

module FunkyExtension
  def do_something_funky
    # Some exciting code
  end
end

class Account < ActiveRecord::Base
  belongs_to :person, :extend => FunkyExtension
end

And then call it like this:

@account = Account.first
@account.person.do_something_funky
October 30, 2008
2 thanks

Does very litle

This method simply returns the hash itself since HashWithIndifferentAccess by definition support symbolized key access. For a (regular rails) Hash there is ActiveSupport::CoreExtensions::Hash::Keys#symbolize_keys! that “Destructively convert all keys to symbols”.

October 29, 2008
3 thanks

A work-around for adding confirmation to image_submit_tag

Sometimes you may want to add a confirmation to image submit tags but this function does not allow it. To get over this limitation use a normal submit tag and set the src and type properties (set type to “image”)

Code example

submit_tag “Delete”, :confirm => “Are you sure?”, :src => “/images/trash.png”, :type => “image” %>

October 25, 2008
3 thanks
October 25, 2008
2 thanks

Alternative: use 1000.humanize

1.humanize == “1″ 1000000.humanize == “1.000.000″ 1000.12345.humanize == “1.000,12″

http://pragmatig.wordpress.com/2008/10/25/numbers-for-humans-humanize-for-numeric/

October 24, 2008
1 thank

module includes with callbacks

If you write a plugin or module that includes callbacks make sure to define the method and call super after you’re done with your business.

module CoolStuff

def self.included(base)
  super
  base.extend(ClassMethods)
  # the next line seems to clobber. instead opt for defining an inheritable method
  # base.after_save :chill
end

module ClassMethods
  # cool class methods
end

def chill
  self.cool = true
end

def after_save
  self.chill
  super # if you don't call super, bloggy won't run
end

end # yes I know this next line is a divisive issue but it’s common enough ActiveRecord::Base.send :include, CoolStuff

class Blog < ActiveRecord::Base

after_save :bloggy

def bloggy
  slugify_title
end

end

October 24, 2008
11 thanks

Prompt vs. Select

According to the docs in form_options_helper.rb

:include_blank - set to true or a prompt string if the first option element of the select element is a blank. Useful if there is not a default value required for the select element.

:prompt - set to true or a prompt string. When the select element doesn’t have a value yet, this prepends an option with a generic prompt – “Please select” – or the given prompt string.

The main difference is that if the select already has a value, then :prompt will not show whereas the :include_blank always will.

October 24, 2008
0 thanks

Styling question

How do we style the select boxes and “:” somehow within this method?

Follwup: it seems in Rails 2.1, FormBuilder#time_select didn’t pass html_options to this method. and it’s fixed i

October 24, 2008
9 thanks

Back it up with a unique index

As mentioned briefly above, as well as using this validation in your model you should ensure the underlying database table also has a unique index to avoid a race condition.

For example:

class User < ActiveRecord::Base
  validates_uniqueness_of :login_name
end

The index can be specified in the migration for the User model using add_index like this:

add_index :users, :login_name, :unique => true

You do a similar thing when using the :scope option:

class Person < ActiveRecord::Base
  validates_uniqueness_of :user_name, :scope => :account_id
end

Should have a migration like this:

add_index :people, [ :account_id, :user_name ], :unique => true

Note that both the attribute being validated (:user_name) and the attribute(s) used in the :scope (:account_id) must be part of the index.

For a clear and concise explanation of the potential for a race condition see Hongli Lai’s blog.

October 24, 2008
2 thanks

The human side of inflections

Rails 2.2 moves this functionality to the Inflector::Inflections class:

See the ticket and the code that allow the humanisation rules to be centralised in an app.

October 23, 2008
2 thanks

Customizing attribute names in error messages

This can be used to customize attribute names in error messages. See my note in ActionView::Helpers::ActiveRecordHelper#error_messages_for.