Created
October 15, 2010 17:29
-
-
Save kakra/628584 to your computer and use it in GitHub Desktop.
Associates models to a parent by other methods, similar to delegates
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# AssociateBy | |
# | |
# Associates models to a parent by other methods, similar to delegates but | |
# changing the association itself instead of the associated object when | |
# writing to the delegated attribute. | |
# | |
# Usage: | |
# ActiveRecord::Base.class_eval { include AssociateBy } | |
# | |
# Example: | |
# | |
# class Street < ActiveRecord::Base | |
# has_many :locations | |
# end | |
# | |
# class Location < ActiveRecord::Base | |
# belongs_to :street | |
# associate :street, :by => :name | |
# end | |
# | |
# @street = Street.create :name => "First Street" | |
# puts @street.id #==> 1 | |
# Street.create :name => "Second Ave" | |
# | |
# puts @location.street_name #==> nil | |
# @location.street_name = "First Street" | |
# puts @location.street.id #==> 1 | |
# | |
# @location.street_name = "Second Ave" | |
# puts @location.street.id #==> 2 | |
# | |
# @location.street = Street.first | |
# puts @location.street_name #==> "First Street" | |
# | |
# written by Kai Krakow, http://github.com/kakra | |
# Provided as-is | |
module AssociateBy | |
def self.included(base) | |
base.extend ClassMethods | |
end | |
module ClassMethods | |
# TODO check sanity of parameters | |
# TODO check "by_method" is an attribute of the association | |
# TODO check "by_method" is a unique key of the association | |
# TODO watch changes to the association to invalidate memoization | |
def associate(association, options = {}) | |
by_method = options[:by].to_s | |
associated_method = "#{association.to_s}_#{by_method}" | |
src = <<-SRC | |
def #{associated_method} | |
@#{associated_method} ||= #{association.to_s}.#{by_method} | |
rescue NoMethodError | |
@#{associated_method} = nil | |
end | |
def #{associated_method}=(#{by_method}) | |
if self.#{association.to_s} = #{association.to_s.classify}.find_by_#{by_method}(#{by_method}) | |
@#{associated_method} = #{association}.#{by_method} | |
else | |
@#{associated_method} = nil | |
end | |
end | |
SRC | |
self.class_eval src, __FILE__, __LINE__ | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment