has_one :through
      Rails is missing the capability to have a has_one association via a link table.  I created this implementation that adds methods to add basic "has_one" support through a habtm association.
The following method defines a new type of association that is currently
missing in rails. There is currently no way to have a
has_one association when a join table is used.
This association requires that a has_and_belongs_to_many
association exists and adds methods to access the first
element of the resulting array.
Example: Enrollments have one registration, but is
modeled through the enrollments_registrations join table.
There is already a "has_and_belongs_to_many :registrations"
and the following operations are added
(and perform as expected):
  
    The following method defines a new type of association that is currently
missing in rails. There is currently no way to have a
has_one association when a join table is used.
This association requires that a has_and_belongs_to_many
association exists and adds methods to access the first
element of the resulting array.
Example: Enrollments have one registration, but is
modeled through the enrollments_registrations join table.
There is already a "has_and_belongs_to_many :registrations"
and the following operations are added
(and perform as expected):
- enrollment.registration => enrollments.registrations.first
- enrollment.registration_id => enrollments.registrations.first.id
-  enrollment.registration=   will set the assocation, erasing any existing registration.
 This method will take an id or a registration object
- enrollment.registration_id= like registration=, but takes an id
- enrollment.has_registration? => true or false as the case may be
def self.has_one_through_join_table(class_name)
  class_name = class_name.to_s
  has_many_association_name = class_name.pluralize
      
  # def registration
  define_method(class_name) do
   send(has_many_association_name).first
  end
  
  #def registration_id
  define_method(class_name+"_id") do
    send(class_name) ? send(class_name).id : nil 
  end
  # def registration=(id_or_object)
  define_method(class_name+"=") do |id_or_object|
    clazz = eval(class_name.classify)
    # the has_and_belong_to_many association (i.e. registrations)
    habtm = send(class_name.pluralize)
    
    if id_or_object.nil?
       habtm.clear
       return
    end
    
    id_or_object = clazz.find(id_or_object) unless 
                              id_or_object.is_a?(clazz)
    if id_or_object
      habtm.clear  # can only have one object
      habtm << id_or_object
    end
  end
  
  #def registration_id=(id)
  define_method(class_name+"_id=") do |id| 
     send(class_name+"=", id)
  end
  # def has_registration?
  define_method("has_#{class_name}?") do
    ! send(class_name).nil?
  end
  
end # has_many_through_join_table



0 Comments:
Post a Comment
<< Home