Flowdock

Recent notes

RSS feed
July 22, 2008
18 thanks

Nested resources in form_for

If you like doing things RESTfully and have a model relationship like:

Post_ has many Comments_

Then you can construct a form_for within your view to mirror this relationship when creating comments:

form_for [@post, @comment] do |f|
  ...
end

You also need to make sure your routes reflect this relationship:

map.resources :post, :has_many => [:comments]
July 22, 2008
6 thanks

selected

select :languages, :language, [‘en’, ‘de’, ‘fr’], {:selected=> ‘en’}

July 22, 2008
15 thanks

Demo: select onchange invoke an ajax

select(“order”, “customer_id”, o.customer.collect {|c| [ c.label, c.id ] },

{:include_blank => true, :selected => o.customer_id }, 
:onchange => remote_function(:update => "message_id",
:method => "put",
:with => "'item=' + value",  
:url => { :controller => :orders, :action => :set_customer_id, :id => order.id}))
July 22, 2008
6 thanks

Documentation

Allows for reverse merging where its the keys in the calling hash that wins over those in the other_hash. This is particularly useful for initializing an incoming option hash with default values:

def setup(options = {})
  options.reverse_merge! :size => 25, :velocity => 10
end

The default :size and :velocity is only set if the options passed in doesn‘t already have those keys set.

July 22, 2008
2 thanks

reverse_merge(other_hash)

Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.

July 22, 2008 - (v2.1.0)
4 thanks

Rails 2.1 migrations

Things to take note of are the lack of ‘column spam’, which didn’t convey much semantic meaning. Also the combination of multiple fields per line with the same type.

references is also a nice helper to convey relationship information (t.references :role is equivilant to t.integer :role_id). references also takes another parameters, see the method for more details.

code

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string :first_name, :last_name, :email
      t.text :address
      t.date :date_of_birth
      t.references :role

      t.timestamps
    end

    add_index :users, :email
  end

  def self.down
    drop_table :users
  end
end
July 22, 2008 - (v1.0.0 - v2.1.0)
4 thanks

Better slug generation (essentially a to_param replacement)

Monkey Patching String

class String
  def slugify
    returning self.downcase.gsub(/'/, '').gsub(/[^a-z0-9]+/, '-') do |slug|
      slug.chop! if slug.last == '-'
    end
  end
end

In a model, or wherever

def to_param
  # Don't need the id here if we're looking up the model by the stored slug.
  "#{id} #{title}".slugify
end
July 21, 2008 - (v2.0.3 - v2.1.0)
10 thanks

Is it really deprecated?

I think the deprecation notice is in the wrong place, it is actually the instance method ActiveRecord::Validations#validate that has been deprecated.

The same applies to ActiveRecord::Validations#validate_on_create and ActiveRecord::Validations#validate_on_update: they have both been deprecated in favour of the class methods validate_on_create and validate_on_update.

July 21, 2008
14 thanks

helper method to partial

concat can be useful for rendering a block to a partial from a helper:

def block_to_partial(partial_name, options = {}, &block)
  options.merge!(:body => capture(&block))
  concat(render(:partial => partial_name, :locals => options), block.binding)
end

This would be particularly useful if you had some partial to help you out with rounded corners, for example. So, in your helper:

def rounded_corners &block
  block_to_partial("shared/rounded_corners", {}, &block)
end

In your view you could have something like:

<% rounded_corners do -%>
     This text is surrounded by rounded corners
<% end -%>

You would have to create some partial in

app/views/shared/rounded_corners.html.erb

And it would look something like:

<div class='c1'>
  <div class=c2>
    .
    .
    .
    <%= body -%>
  </div>
</div>
July 20, 2008
10 thanks

Generate an observer

Generating an observer from the command line follows the usual pattern:

script/generate observer audit

This will create a model called:

app/models/audit_observer.rb
July 17, 2008
7 thanks

Where you declare before_destroy matters

Beware that where you declare a before_destroy callback matters if you have any “acts_as” type declarations, that also declare before_destroy callbacks. A good example is the acts_as_nested_set. If you specify acts_as_nested_set prior to your before_destroy, then acts_as_nested_set will go through and destroy all children first, then your callback will run (at which point children will be empty). Thus, if your before_destroy callback needs to examine the children, it will not work properly. Putting your before_destroy callback ahead of acts_as_nested_set or anything else that declares a before_destroy is key in such cases.

July 15, 2008
1 thank

Mapping Order

Something I always forget is the order in which each mapping should be specified.

The first item is the attribute name in the ActiveRecord model, and the second is the name of the attribute in the ValueObject (the writer uses it to read from the VO).

Furthermore, the order in which mapping pairs are specified should be the same as the order the attributes are specified in the ValueObject’s initialize method (for the reader to be able to instantiate a VO with the record’s values).

nachokb

July 15, 2008
9 thanks

Required Reading

The details for using layout (such as possible values for the conditions hash) can be found in ActionController::Layout::ClassMethods.

July 13, 2008
5 thanks

Convert strings to Dates

Uses the undocumented Date._parse method. Some usage examples:

'06/15/2008'.to_date         # => Sun, 15 Jun 2008
'20080615'.to_date           # => Sun, 15 Jun 2008
'2008-06-15'.to_date         # => Sun, 15 Jun 2008
'Sun, 15 Jun 2008'.to_date   # => Sun, 15 Jun 2008
July 10, 2008
1 thank

migration example

def self.up create_table :regs do |t|

t.column :login, :string, :limit=>'10'
t.column :pass, :string, :limit=>'10'
t.column :email, :string, :limit=>'20'
t.column :fio, :string, :limit=>'30'
t.column :born, :date
t.column :phone_code, :integer, :limit=>'3'
t.column :phone_post, :integer, :limit=>'7'
t.column :password, :string, :limit=>'20'
t.column :pass_when, :date
t.column :pass_who, :string,:limit=>'30'
t.column :wmid, :integer, :limit=>12
t.column :wmr, :integer, :limit=>12
t.column :wmz, :integer, :limit=>12
end

add_index :regs, [:login, :wmr, :wmz], :unique => true end

July 10, 2008
This note might be spam Show
July 10, 2008
0 thanks

watch out for urls with &

image_tag(‘x.com/aaa?a=1&b=2’) = x.com/aaa?a=1&amp;b=2

July 8, 2008
4 thanks
July 8, 2008
3 thanks

For more information

See ActiveMailer::Base.

July 7, 2008
4 thanks

List of statuses

You can view a full list of statuses at http://dev.rubyonrails.org/browser/trunk/actionpack/lib/action_controller/status_codes.rb.

head can be called with a symbol or a status code:

Using head with a symbol

head :length_required # 411 Length Required
head :ok              # 200 OK

Using head with a status code

head 404              # 404 Not Found
July 5, 2008
23 thanks

Using counters with collections

When you’re rendering a collection partial, the partial_name_counter variable contains the position of the current element in the collection. For example:

<%= render(:partial => 'example', :collection => %w(rails-doc is cool)) %>

Now in _example.html.erb:

<p>Element: <%= example %> (index: <%= example_counter %>)</p>

It would produce:

<p>Element: rails-doc (index: 1)</p>
<p>Element: is (index: 2)</p>
<p>Element: cool (index: 3)</p>

As you can see, indexing starts from 1.

July 4, 2008
3 thanks

Using a specific layout

To choose the layout (or no layout) for a method call the render method with a :layout option.

July 4, 2008
2 thanks

around_filter code example

This is how it’s used:

around_filter do |controller, action|
  do_your(:stuff) do
    action.call
  end
end
July 4, 2008
6 thanks

Window open a dialog of no menu, no status, have scroll

Example

link_to name, url, :popup => ['dialog name','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes']
July 4, 2008
0 thanks

Add if before Ajax.request

Use link_to_remote’s before

link_to_remote(“watcher”, {:url => “/watchers/add”, :before => “if($F(‘user_id’)==”){return false;}” })

<a onclick=“if($F(‘user_id’)==”){return false;}; new Ajax.Request(‘/watchers/add’, {asynchronous:true, evalScripts:true, parameters:”}); return false;”>添加订阅人

July 4, 2008
12 thanks

Add empty option and text is -select-

select :object, :method, options, :prompt => ‘-select-’

July 4, 2008
5 thanks

Used to get current Rails environment

Rails#env returns a string representing the current Rails environment.

Code example

>> Rails.env # in development mode
Rails.env
=> "development"
July 3, 2008
5 thanks

Connections to multiple databases

establish_connection can be used to connect to multiple databases. The immediate downside is that your rake migrations may not work properly without hacking.

In each model that resides in a different database we call:

establish_connection :different_database

You can check they are working by hitting script/console with:

>> App.connection.instance_eval {@config[:database]}
=> "app_development"
>> AnotherDatabase.connection.instance_eval {@config[:database]}
=> "another_database"

Now doing a call to AnotherDatabase.find() will connect to the AnotherDatabase database and start returning results.