DateTimes are Dates, beware

Given:

datetime = DateTime.now
date = datetime.to_date #or Date.today

will assert:

datetime.is_a? Date == true
datetime.is_a? DateTime == true
datetime.instance_of? Date == false
datetime.instance_of? DateTime == true

In case you have a table and a model like:

create_table :event do |t|
  t.date    :day
  t.string  :description
end
class Event < ActiveRecord::Base; end

And you say:

event = Event.new(:day => '2013-03-22')

Rails will convert the supplied value for day to the type of the database field,...

When you set date attributes, you should not pass times

As you know, time zones make stuff a bit more difficult but are necessary.

A time-zoned record is converted to UTC using to_s(:db) to be stored, and put back into the correct time zone when loaded. So when you are not on UTC, the following will happen:

>> Time.current
=> Fri, 15 Mar 2013 11:56:03 CET +01:00
>> Time.current.to_s(:db)
=> "2013-03-15 10:56:03" # This is now UTC

That will blow up in your face when you sen...

Profiling Ruby with ruby-prof

require 'ruby-prof' # you don't need this if you have ruby-prof in your Gemfile

You can set one of the things you want to measure by using (default is PROCESS_TIME most useful ones are PROCESS_TIME, MEMORY, CPU_TIME):
RubyProf.measure_mode = RubyProf::PROCESS_TIME
RubyProf.measure_mode = RubyProf::WALL_TIME
RubyProf.measure_mode = RubyProf::CPU_TIME
RubyProf.measure_mode = RubyProf::ALLOCATIONS
RubyProf.measure_mode = RubyProf::MEMORY
RubyProf.measure_mode = RubyProf::GC_RUNS
RubyProf.measure_mode = ...

has_defaults issues

What
The object returned by has_defaults apparently is the same between multiple object creations.
Consider this scenario:

class Order
  has_defaults :items => []
end

o1 = Order.new
o1.items #=>> []
o1.items << item
o1.items #=>> [item]

o2 = Order.new
o2.items #=>> [item]

So, now o2.items is not empty by default because we modified the same object in has_defaults

How
When using has_defaults on a model, consider using it in the following way:

has_defaults :items => proc {[] }

When
Consider do...

Database: Scopes, migrations, and indices

Wether you modify an existing named scope or add a new one, or when you write a new query, make sure you have the proper indices.

This particularly applies if you're going to run non-trivial queries of course (admin backends, analytics, etc).

Compound indices

A chain of scopes results in (usually) one query. You should take into account all attributes (columns) that are used in :conditions, :join, :group, :having, and :order, as all those result in filtering and sorting–slow operations without indices.

Take the list of all ...

Cleaner Rspec

When simply checking equality or truthiness then
Instead of:
it "should have role set to admin" do
@user.role.should eql('admin')
end

it "should be valid" do
  @user.valid?.should be_true
end

Do:
it { @user.role.should eql('admin') }
it { @user.valid?.should be_true}

Try to stick to one expectation per test block, diverge in exceptional circumstrances, so instead of:
describe "#some_method" do
before(:each) do
@object = Class.new
end

   it "should have attributes set" do

...

Method return value should always be of same type

One of the main source of bugs and complexity in the code is when a functional method (that we expect to return a value) return different values under different circumstances.

For example, we ruby programmers have a bad habit of returning nil from a method when certain condition is not fulfilled else return an Array or Hash. That just makes the calling code unnecessary complex and error prone because then it has to do different checks.

Bad Practice:

def bad_method(param)
  return unless param == 'something'
  [1,2,3]
end

...

Rebase your feature branches

Regularly, but at least before merging your feature branches, rebase them to get rid of "fix typo" and "wip" commits.

Getting rid of unnecessary commits

Let's say you do a git rebase -i HEAD~~~~ and have this commit history:

pick 1d1e1f My Feature
pick 2d2e2f My Feature - wip
pick 3d3e3f My Feature - fix typo
pick 4d4e4f My Other feature

Change it to use fixup for those commits that should be merged into the one before ...

ActiveRecord::NamedScopes (2.3.x) obtaining the SQL conditions

It's a good pratice to chain several named scopes like:

Property.listable.for_2_or_more_guests.best_10_properties

Now, to make the lesson more valuable let's assume the following code:

Property.scoped(:conditions => "foo = 2").scoped(:conditions => "foo2 IS NOT NULL")

Next, if you want to be able to fetch the underlying conditions scope generated by ActiveRecord. You must do this:

Property.scoped(:conditions => "foo = 2").scoped(:conditions => "foo2 IS NOT NULL").scope(:find)
# => {:conditions => "(foo = 2) AND (foo2...