1

Suppose I have a class with a save method, and three mixins which modify it using aliasing, e.g.

module Callbacks
  def save_with_callbacks
    callback :before_save
    save_without_callbacks
    end
  end

  alias_method_chain :save, :callbacks
end

and similarly for save_with_transaction and save_with_timestamps, mixed in in that order, so MyModel#save calls save_with_timestamps, which calls save_with_transaction, which calls save_with_callbacks, which finally calls the original save.

Now suppose I want to save without a transaction. I can call save_without_transaction, but that doesn't call the code to set the timestamps.

How can I save my model with timestamps and callbacks, but no transaction?

I could reorder the mixins, but my question is about omitting the middle, rather than specifically transactions. How can I omit the middle of a chain of methods?

NOTE - I've used RoR's alias_method_chain for brevity, but my question applies to ruby in general

Simon
  • 25,468
  • 44
  • 152
  • 266

1 Answers1

2

Your only option seems to be -- to me, anyway -- to provide a second calling chain that handles this functionality further up. I don't think you can do this with aliasing; you're going to have to define a new method that calls the old method, instead - so something like:

  1. MyModel#save <-save_with_timestamps <- save_with_transaction <- save_with_callbacks <-save.
  2. MyModel#save_other <-save_with_timestamps_other <- save_with_callbacks_other <-save_other.

(As an aside, aren't long chains of aliases going to make your code very difficult to read? Personally I think I would work hard to avoid them.)

Andy
  • 1,480
  • 14
  • 17
  • Yes, they do sometimes make it difficult to read, but the Rails codebase makes heavy use of them. – Simon Jun 30 '11 at 12:35
  • 1
    Well, as my mother would say, "if the rails codebase jumped off a cliff, would you do it too?" ...okay, she wouldn't have actually said that... :) – Andy Jun 30 '11 at 16:20