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 :prefix argument
The 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
delegating methods.
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
Transaction Scope
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
Association Methods
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.
Haml []
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
div_for and 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>
RESTful actions
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), 
put(singular), and delete(singular), but what isn’t as obvious is
that.
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.
Rake Tasks
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
Database Index
Since most applications have far more reads than writes, you should add
indexes to every field that appears in a WHERE clause or an ORDER
clause. You should also add indexes for every combination of fields that
are used that are combined with AND.
As always, don’t follow this advice blindely, if a table only has three rows then perhaps the index is overkill…
Conclusion
Apart from these tips, there are tons of other useful information, making this book a must-read if you are doing Rails development.
Thanks for your review. It's really handy :)
ReplyDelete@Abel, I'm glad you liked it.
ReplyDelete