Module: Lolita::Hooks::ClassMethods

Defined in:
lib/lolita/hooks.rb

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(*args, &block) ⇒ Object

Try to recognize named run methods like

MyClass.run_after_save # will call MyClass.run(:after_save)


330
331
332
333
334
# File 'lib/lolita/hooks.rb', line 330

def method_missing(*args, &block)
  unless self.recognize_hook_methods(*args,&block)
    super
  end
end

Instance Method Details

#add_hook(*names) ⇒ Object

This method is used to add hooks for class. It accept one or more hook names.

Example

add_hook :before_save
MyClass.add_hooks :after_save, :around_save


282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/lolita/hooks.rb', line 282

def add_hook(*names)
  (names||[]).each{|hook_name|
    self.class_eval <<-HOOK,__FILE__,__LINE__+1
      def self.#{hook_name}(*methods,&block)
        options=methods.extract_options!
        in_hooks_scope(options[:scope]) do
          register_callback(:"#{hook_name}",*methods,&block)
        end
      end

      def #{hook_name}(*method,&block)
        self.class.#{hook_name}(*method,:scope=>self,&block)
      end
    HOOK
    register_hook(hook_name)
  }
end

#add_hooks(*names) ⇒ Object



274
275
276
# File 'lib/lolita/hooks.rb', line 274

def add_hooks *names
  add_hook *names
end

#all_hooksObject



257
258
259
260
261
262
263
264
265
266
# File 'lib/lolita/hooks.rb', line 257

def all_hooks
  @all_hooks||=self.ancestors.inject([]) do |result,const_name|
    if const_name.respond_to?(:hooks)
      result+=const_name.send(:hooks)
    else
      result
    end
  end
  @all_hooks
end

#clear_hooksObject

Reset all hooks and callbacks to defaults.



269
270
271
272
# File 'lib/lolita/hooks.rb', line 269

def clear_hooks
  @hooks=[]
  @callbacks={}
end

#collect_callbacks_from(name, const_name, scope_callbacks) ⇒ Object



344
345
346
347
348
349
350
# File 'lib/lolita/hooks.rb', line 344

def collect_callbacks_from(name,const_name,scope_callbacks)
    class_callbacks=const_name.callbacks[name.to_sym] || {}
    [:methods,:blocks].each do |attr|
      scope_callbacks[attr]=((class_callbacks[attr] || [])+(scope_callbacks[attr] || [])).uniq
    end
  scope_callbacks
end

#has_hook?(name) ⇒ Boolean

Is hook with name is defined for class.

Returns:

  • (Boolean)


324
325
326
# File 'lib/lolita/hooks.rb', line 324

def has_hook?(name)
  self.all_hooks.include?(name.to_sym)
end

#hooksObject

All hooks for class. This is Array of hook names.



252
253
254
255
# File 'lib/lolita/hooks.rb', line 252

def hooks
  @hooks||=[]
  @hooks
end

#hooks_scopeObject



248
249
250
# File 'lib/lolita/hooks.rb', line 248

def hooks_scope
  @hooks_scope || self
end

#hooks_scope=(value) ⇒ Object



244
245
246
# File 'lib/lolita/hooks.rb', line 244

def hooks_scope=(value)
  @hooks_scope = value
end

#in_hooks_scope(scope) ⇒ Object



300
301
302
303
304
305
306
307
# File 'lib/lolita/hooks.rb', line 300

def in_hooks_scope(scope)
  begin
    self.hooks_scope = scope
    yield
  ensure
    self.hooks_scope = self
  end
end

#recognize_hook_methods(method_name, *args, &block) ⇒ Object

Set #method_missing



337
338
339
340
341
342
# File 'lib/lolita/hooks.rb', line 337

def recognize_hook_methods method_name, *args, &block
  if method_name.to_s.match(/^run_(\w+)/)
    self.run($1,*args,&block)
    true
  end
end

#register_callback(name, *methods, &block) ⇒ Object

Register callback with given scope.



353
354
355
356
357
358
359
360
# File 'lib/lolita/hooks.rb', line 353

def register_callback(name,*methods,&block)
  temp_callback=hooks_scope.callbacks[name]||{}
  temp_callback[:methods]||=[]
  temp_callback[:methods]+=(methods||[]).compact
  temp_callback[:blocks]||=[]
  temp_callback[:blocks]<< block if block_given?
  hooks_scope.callbacks[name]=temp_callback
end

#register_hook(name) ⇒ Object

Register hook for scope.



363
364
365
# File 'lib/lolita/hooks.rb', line 363

def register_hook(name)
  self.hooks<<name
end

#run(hook_name, *args, &block) ⇒ Object

run is used to execute callback. Method accept one or more hook_names and optional block. It will raise error if hook don’t exist for this class. Also it accept :scope options, that is used to #get_callbacks and #run_callbacks.

Example

MyClass.run(:before_save,:after_save,:scope=>MyClass.new)
# this will call callbacks in MyClass instance scope, that means that self will be MyClass instance.


315
316
317
318
319
320
321
# File 'lib/lolita/hooks.rb', line 315

def run(hook_name,*args,&block)

  options=args ? args.extract_options! : {}
  raise Lolita::HookNotFound, "Hook #{hook_name} is not defined for #{self}." unless self.has_hook?(hook_name)
  runner = Lolita::Hooks::Runner.new(self,hook_name,options)
  runner.run(&block)
end

#superclassesObject



367
368
369
370
371
372
373
374
375
376
377
# File 'lib/lolita/hooks.rb', line 367

def superclasses
  unless @klasses
    @klasses=[]
    self.ancestors.each do |const_name|
      if const_name.respond_to?(:hooks)
        @klasses<<const_name
      end
    end
  end
  @klasses
end