Module: Rtml::Widgets

Defined in:
lib/rtml/widgets.rb

Overview

This module makes sure that all Widgets that can be found in Rtml.configuration.widget_paths have been loaded, and then registers Widget functionality with whatever class included Rtml::Widgets. Note that while merely including this module does allow your class to support Widgets, the Widget itself must declare that it is meant to affect your object.

You can interface with existing Widgets (assuming they support your class at a more fundamental level) by defining a self.name method which returns the name of one of the elements the Widget in question affects. This definition must appear before the inclusion of Rtml::Widgets.

Class Method Summary collapse

Class Method Details

.add_proxies_to_base(base) ⇒ Object

Mixes the various proxy methods into the specified base.



50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/rtml/widgets.rb', line 50

def add_proxies_to_base(base)
  target_name = base.respond_to?(:name) ? base.name.underscore.sub(/^.*\//, '') : nil
  (@widget_mapping ||= {}).each do |key, mixin|
    klass = base
    if base.kind_of? ActiveRecord::Base
      klass = class << base; self; end
    end

    if klass.respond_to?(:name) && key == target_name
      klass.send(:include, mixin)
    end
  end
end

.affecting(target) ⇒ Object

Returns all Widgets which affect the specified target.



33
34
35
# File 'lib/rtml/widgets.rb', line 33

def affecting(target)
  mapping(target).proxied_widgets
end

.create_widgets_array(base) ⇒ Object



105
106
107
108
109
110
# File 'lib/rtml/widgets.rb', line 105

def create_widgets_array(base)
  base.instance_eval do
    class_inheritable_array :class_widgets
    read_inheritable_attribute(:class_widgets) || write_inheritable_attribute(:class_widgets, [])
  end
end

.included(base) ⇒ Object



38
39
40
41
42
43
44
45
46
47
# File 'lib/rtml/widgets.rb', line 38

def included(base)
  @bases ||= []
  @bases << base

  create_widgets_array(base)
  base.send(:include, Rtml::WidgetCore::WidgetAccessorInstanceMethods)
  base.send(:extend,  Rtml::WidgetCore::WidgetAccessorClassMethods)
  load_widgets
  add_proxies_to_base(base)
end

.load_widget!(file) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/rtml/widgets.rb', line 91

def load_widget!(file)
  if Rtml.configuration.widget_logging_enabled
    begin
      result = require_dependency(file)
      Rails.logger.debug "Loading Widget: #{file} (#{result})"
    rescue
      Rails.logger.debug "Loading Widget: #{file} (#{$!.message})"
      raise $!
    end
  else
    require_dependency file
  end
end

.load_widgets(load_path = nil) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/rtml/widgets.rb', line 64

def load_widgets(load_path = nil)
  if load_path.nil?
    load_widgets(File.join(Rtml.root, 'builtin/widgets'))

    Rtml.configuration.widget_paths.each do |lp|
      if defined?(Rails) && defined?(Rails.root)
        lp = File.join(Rails.root, lp) unless lp =~ /^#{Regexp::escape Rails.root}/ || lp =~ /^C\:/ || lp =~ /\//
        load_widgets(lp)
      else
        load_widgets(lp)
      end
    end
  else
    if File.file?(load_path)
      load_widget!(load_path)
    else
      if Rtml.configuration.widget_logging_enabled
        Rails.logger.debug "Searching for Widgets in '#{load_path}/**/*.rb'..."
      end
      Dir.glob(File.join(load_path, "**/*.rb")).each do |fi|
        next if fi =~ /\.svn/ or File.directory?(fi)
        load_widget!(fi)
      end
    end
  end
end

.mapping(key) ⇒ Object

The Widget mapping is a hash whose keys are symbols and whose values are instances of Module. The symbols represent either RTML models or TML tag names, while the Modules represent the proxy from the representation’s class into the Widget itself. This way, the Module can be mixed-in with the target, and Widgets added after the fact can simply add methods to the mixed-in Module. These methods are automatically added to the target class by Ruby. It’s a really fancy version of doing something like this:

mixin = Module.new
mixin.send(:define_method, :say_hi) { puts 'hello' }
class Target; end
Target.send(:include, mixin)
mixin.send(:define_method, :say_bye) { puts 'goodbye' } # notice this happens AFTER it's mixed in!

target_instance = Target.new
target_instance.say_hi        # => hello
target_instance.say_bye       # => goodbye


27
28
29
30
# File 'lib/rtml/widgets.rb', line 27

def mapping(key)
  @widget_mapping ||= {}
  @widget_mapping[key.to_s] ||= Rtml::WidgetCore::WidgetProxy.new
end