Amit Patel
Amit Patel

Reputation: 15985

Define custom callbacks on ruby method

I have many service classes with call method having variation in arguments.

I want to call a function notify at the end of each call method. I don't want to modify those service classes but I am open to modify base class.

I am playing with ActiveSupport::Callbacks but it doesn't serve the purpose of not modifying service class.

require 'active_support'
class Base
  include ActiveSupport::Callbacks
  define_callbacks :notifier

  set_callback :notifier, :after do |object|
    notify()
  end

  def notify
    puts "notified successfully"
  end
end

class NewPost < Base
  def call
    puts "Creating new post on WordPress"
    # run_callbacks :notifier do
    #   puts "notifying....."
    # end
  end
end

class EditPost < Base
  def call
    puts "Editing the post on WordPress"
    # run_callbacks :notifier do
    #   puts "notified successfully"
    # end
  end
end

person = NewPost.new
person.call

Problem In order to run callbacks, I need to uncomment the commented code. But here you can see that I need to modify existing classes to add run_callbacks block. But that is not what I want. I can easily call notify method instead without adding such complexity.

Can anybody suggest how can I get to the solution ruby way?

Upvotes: 3

Views: 4859

Answers (2)

mkon
mkon

Reputation: 1113

Generally the callbacks are set in the inheriting classes. Not sure what you want to achieve from your example, but from your initial description it should be this:

require 'active_support'

class Base
  include ActiveSupport::Callbacks
  define_callbacks :call

  def call
    run_callbacks(:call) { puts "something is happening..." }
  end
end

class Post < Base
  set_callback :notify, :after, :call

  private

  def notify
    puts "new post!"
  end
end

post = Post.new
post.call

Upvotes: 0

Thomas
Thomas

Reputation: 1633

I would do something like this:

require 'active_support'
class Base
  include ActiveSupport::Callbacks
  define_callbacks :notifier

  set_callback :notifier, :after do |object|
    notify()
  end

  def notify
    puts "notified successfully"
  end

  def call
    run_callbacks :notifier do
      do_call
    end
  end

  def do_call
    raise 'this should be implemented in children classes'
  end
end

class NewPost < Base
  def do_call
    puts "Creating new post on WordPress"
  end
end

person = NewPost.new
person.call

Another solution without ActiveSupport:

module Notifier
  def call
    super
    puts "notified successfully"
  end
end


class NewPost
  prepend Notifier

  def call
    puts "Creating new post on WordPress"
  end
end

NewPost.new.call

You should check your ruby version prepend is a "new" method (2.0)

Upvotes: 5

Related Questions