Ok, so I've been refactoring my code in my little Rails app in an effort to remove duplication, and in general make my life easier (as I like an easy life). Part of this refactoring, has been to move code that's common to two of my models to a module that I can include where I need it.
So far, so good. Looks like it's going to work out, but I've just hit a problem that I'm not sure how to get around. The module (which I've called sendable), is just going to be the code that handles faxing, e-mailing, or printing a PDF of the document. So, for example, I have a purchase order, and I have Internal Sales Orders (imaginatively abbreviated to ISO).
The problem I've struck, is that I want some variables initialised (initialized for people who don't spell correctly :P ) after the object is loaded, so I've been using the after_initialize hook. No problem... until I start adding some more mixins.
The problem I have, is that I can have an after_initialize
in any one of my mixins, so I need to include a super call at the start to make sure the other mixin after_initialize
calls get called. Which is great, until I end up calling super and I get an error because there is no super to call.
Here's a little example, in case I haven't been confusing enough:
class Iso < ActiveRecord::Base
include Shared::TracksSerialNumberExtension
include Shared::OrderLines
extend Shared::Filtered
include Sendable::Model
validates_presence_of :customer
validates_associated :lines
owned_by :customer
order_lines :despatched # Mixin
tracks_serial_numbers :items # Mixin
sendable :customer # Mixin
attr_accessor :address
def initialize( params = nil )
super
self.created_at ||= Time.now.to_date
end
end
So, if each one of the mixins have an after_initialize call, with a super call, how can I stop that last super call from raising the error? How can I test that the super method exists before I call it?
You can use this:
super if defined?(super)
Here is an example:
class A
end
class B < A
def t
super if defined?(super)
puts "Hi from B"
end
end
B.new.t
Have you tried alias_method_chain
? You can basically chained up all your after_initialize
calls. It acts like a decorator: each new method adds a new layer of functionality and passes the control onto the "overridden" method to do the rest.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With