The Art of Mixing in

ruby mixins modules rails models

09|25|2009

The Giant Central Model

I've been working for over a year at recomed.com, which basically is a social network for doctors that aids people in potentially finding the right doctor for their needs.

Since the application's core is the Doctor, you naturally have so much objects interacting with it. I'll highlight the education part of the doctor to illustrate:

   class Doctor < ActiveRecord::Base
     has_one  :school
     has_many :residencies
     has_many :internships
     has_many :fellowships
   end

Looks nice and clean right? Well, we need to specify nested form capability too:

   class Doctor < ActiveRecord::Base
     has_one  :school
     has_many :residencies
     has_many :internships
     has_many :fellowships

     accepts_nested_attributes_for :school, :residencies, 
       :internships, :fellowships
   end

And now, you need to open up the attributes (since I'm using attr_accessible which finally results in the code below:

    class Doctor < ActiveRecord::Base
      has_one  :school
      has_many :residencies
      has_many :internships
      has_many :fellowships

      accepts_nested_attributes_for :school, :residencies, 
        :internships, :fellowships

      attr_accessible :school_attributes, :residencies_attributes,
        :internships_attributes, :fellowships_attributes
    end

What if your model has 20 or more associations?

In our case, this is a reality, so just by the macro declarations i gave above, the LOC blows up really fast.

Hello Mixins

    class Doctor < ActiveRecord::Base
      include Education
    end

    # in app/models/doctor/education.rb
    module Doctor::Education
      def self.included( doctor )
        doctor.class_eval do
          has_one  :school
          has_many :residencies
          has_many :internships
          has_many :fellowships

          accepts_nested_attributes_for :school, :residencies, 
            :internships, :fellowships

          attr_accessible :school_attributes, :residencies_attributes,
            :internships_attributes, :fellowships_attributes
        end
      end
    end

Before i go, a snapshot of how our Doctor model looks like right now:

class Doctor < User
  include Licensing
  include Specialties

  include Profile::Fields
  include Profile::Practice
  include Profile::Education
  include Profile::Profession
  include Profile::Research
  include Profile::Training
  include Profile::Recognitions

  include Authorization
  include Requirements
  include Security
  include Searchability
  include AsynchronousIndexing
  include Identification
  include FocusOfPractice
  include Inquiries
  include Publications
  include TrustSystem
  include Pic
  include AgeConcerns
  include Completeness
  include Networkability
  include Recommendations
  include Conversations
  include Notifications

  ...
end
blog comments powered by Disqus