Friday, September 14, 2007

ActiveRecord find_or_create methods


def create
company = params[:person].delete(:company)
@company = Company.find_or_create_by_name(company[:name])
@person = @company.people.create(params[:person])

respond_to do |format|
format.html { redirect_to(person_list_url) }
format.js
format.xml { render :xml => @person.to_xml(:include => @company) }
end
end

Added find_or_initialize_by_X which works like find_or_create_by_X but doesn’t save the newly instantiated record. [Sam Stephenson]
Added constrain scoping for creates using a hash of attributes bound to the :creation key [DHH]. Example:

Comment.constrain(:creation => { :post_id => 5 }) do
# Associated with :post_id
Comment.create :body => "Hello world"
end

This is rarely used directly, but allows for find_or_create on associations. So you can do:

# If the tag doesn't exist, a new one is created that's associated with the person
person.tags.find_or_create_by_name("Summer")

Added extension capabilities to has_many and has_and_belongs_to_many proxies [DHH]. Example:

class Account < ActiveRecord::Base
has_many :people do
def find_or_create_by_name(name)
first_name, *last_name = name.split
last_name = last_name.join " "

find_or_create_by_first_name_and_last_name(first_name, last_name)
end
end
end

person = Account.find(:first).people.find_or_create_by_name("David Heinemeier Hansson")
person.first_name # => "David"
person.last_name # => "Heinemeier Hansson"

Note that the anoymous module must be declared using brackets, not do/end (due to order of evaluation).

No comments :