Another good Ruby book is out, Rails Anti-Patterns. The book is loaded with good tips on everything from following the Law of Demeter to cleaning up your views with the use of helper methods.
Here are some things I picked up from the book.
delegate can take a
delegate method from
active_support is used for delegating calls
to another object without having to write out the full delegating
methods. It can take a prefix option to customize the name of the
class Address @attr_accessors :street, :zip end class Person attr_reader :address # prefix => true, results in the model name being used as prefix delegate :street, :zip, :to => :address, :prefix => true #@person.address_street, @person.address_zip end class Person attr_reader :billing_address, :delivery_address # prefix => string, uses the string as prefix delegate :street, :zip, :to => :address, :prefix => delivery #@person.delivery_street, @person.delivery_zip delegate :street, :zip, :to => :address, :prefix => billing #@person.billing_street, @person.billing_zip end
The code executed in the ActiveRecord callbacks execute in the same transaction as the actual call to save, create, update, or delete. Knowing this helps to eliminate unneccessary explicit transactions.
# Using a before filter class Drink before_create :remove_ingredients_from_bar def remove_ingredients ingredients.each do |ingredient| Bar.remove(ingredient) end end end # Is better than using an explicit transaction class Drink def create_drink transaction do remove_ingredients create end end def remove_ingredients ingredients.each do |ingredient| Bar.remove(ingredient) end end end
It is possible to add methods directly on the activerecord associations. This is especially handy if the method uses information from both sides of the relation.
class Drink #has_field :minimum_drinking_age end class Customer #has_field :age has_many :drinks do def allowed # proxy_owner is the object defining the relation, Customer where(['minimum_drinking_age < ?', proxy_owner.age]) end end end
When to make a model active
If there is no user interface for adding, removing, or managing data, there is no need for an active model. A denormalized column populated by a hash or array of possible values is fine.
This is really just the application of the KISS principle, Keep It Simple Stupid, but I have never seen it as clearly described before reading this book.
A nice feature of Haml that I didn’t know about, is the  operator.
When given an object, such as [record],  acts as a combination of
content_for, outputting a tag with the id and class
attributes set appropriately.
-# This Haml %span[@team]
<!-- Results in this HTML --> <span class='team' id='team_1'></span>
When using resources in Rails there are seven methods that are used.
index, create, show, update, delete, edit, and
new. The first five
naturally map to
get(collection), post(collection), get(singular),
delete(singular), but what isn’t as obvious is
The new and edit actions are really just different ways of representing the show action.
This is of course obvious when you think about it, but once again Chad and Tammer has written it down in plain simple English.
How should you treat your application specific Rake tasks on order to test them easily. Once again the solution is very simple.
Write the domain specific code as a class method on the appropriate model associated with the task.
Then all you have to do is call the method from the task.
task :fill_bar_with_ingredients do Bar.fill_with_ingredients end
It is not always appropriate to add this functionality to the existing models. This is a clue that another model is needed in your domain.
task :fill_bar_with_ingredients do LiquorStore.order_ingredients end
Since most applications have far more reads than writes, you should add
indexes to every field that appears in a
WHERE clause or an
clause. You should also add indexes for every combination of fields that
are used that are combined with
As always, don’t follow this advice blindely, if a table only has three rows then perhaps the index is overkill…
Apart from these tips, there are tons of other useful information, making this book a must-read if you are doing Rails development.