I don't think there is anything wrong with your implementation,
strictly. Its just more code, which means more to test and to
maintain. Using a Rails feature like alias_method_chain will be a
more obvious idiom to other experienced Rails developers, and will
also have the advantage of using a tested, supported api from Rails.
OTOH, doing it yourself did help you learn more about what is going on
underneath, which is a good thing. 
- rob
Hmmm, I see one disadvantage with the aliases: the consumer class can't override attribute=, unless they make sure the def stays physically before the inclusion of the modules.
Using the callchain method, the consumer class can override attribute= as long as they call super instead of write_attribute.
Unless I did something wrong. Here is my test:
class Superthing #this stands in for ActiveRecord::Base
def dohook
puts "whatever happens, this must happen"
end
end
module Doer #this is in one file in a plugin
module Mary
def self.included(base)
base.class_eval do
alias_method :doit_without_mary, :doit unless method_defined?(:doit_without_mary)
alias_method :doit, :doit_with_mary
end
end
def doit_with_mary
puts "Mary says doit"
doit_without_mary
end
end
end
module Doer # this is in another file in a plugin, and is somewhat orthogonal to "Mary"
module Bob
def self.included(base)
base.class_eval do
alias_method :doit_without_bob, :doit unless method_defined?(:doit_without_bob)
alias_method :doit, :doit_with_bob
end
end
def doit_with_bob
puts "Bob says doit"
doit_without_bob
end
end
end
module Doer # this initializes the plugin
def self.included(base)
puts "I just got included"
base.extend SetupMethods
end
module MakeSureTheresASuper # this is necessary in my example
def doit
puts "I'm just standing in"
dohook
end
end
module SetupMethods
def setmeup
include MakeSureTheresASuper
if rand(2) == 1
puts "Bob first"
include Bob
include Mary
else
puts "Mary first"
include Mary
include Bob
end
end
end
end
Superthing.send(:include, Doer::SetupMethods)
class Thing < Superthing
include Doer
setmeup
end
class CustomThing < Superthing
include Doer
setmeup
def doit()
puts "CustomThing says doit"
super
end
# if we do setmeup here instead, it will work. but that is yucky
end
#will always do Bob & will always do Mary, but order is random
puts "Thing:"
Thing.new.doit
puts
puts "OOPS!!! CustomThing loses all the good love"
puts "CustomThing:"
CustomThing.new.doit