unobservable 0.1.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/README.rdoc +23 -1
  2. data/VERSION +1 -1
  3. data/lib/unobservable.rb +49 -40
  4. metadata +3 -3
data/README.rdoc CHANGED
@@ -7,9 +7,31 @@ then the Observable mixin is the wrong tool for the job.
7
7
  Unobservable overcomes the limitations of the Observable mixin by allowing objects to own one or more Event
8
8
  objects.
9
9
 
10
+ == 2-Second Tour
11
+
12
+ require 'unobservable'
13
+
14
+
15
+ class Button
16
+ include Unobservable::Support
17
+
18
+ attr_event :clicked
19
+
20
+ def click(x, y)
21
+ raise_event(:clicked, x, y)
22
+ end
23
+ end
24
+
25
+
26
+ button = Button.new
27
+ button.clicked.register {|x, y| puts "You just clicked: #{x} #{y}"}
28
+
29
+ button.click(2, 3)
30
+
31
+
10
32
  == 2-Minute Tour
11
33
 
12
- Instead of a lengthy introduction, here's a short program that demonstrates the main concepts:
34
+ Now here's a slightly-longer demonstration of Unobservable. This time, I even included comments!
13
35
 
14
36
 
15
37
  require 'unobservable'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.4.0
data/lib/unobservable.rb CHANGED
@@ -15,6 +15,11 @@ module Unobservable
15
15
  contributors += mod.ancestors[1...-1] if mod.is_a? Class
16
16
  end
17
17
 
18
+ self.collect_instance_events_defined_by(contributors)
19
+ end
20
+
21
+
22
+ def self.collect_instance_events_defined_by(contributors)
18
23
  retval = Set.new
19
24
 
20
25
  contributors.each do |c|
@@ -29,88 +34,92 @@ module Unobservable
29
34
  end
30
35
 
31
36
 
32
-
33
37
  # This module is a mixin that provides support for "instance events".
34
38
  module ModuleSupport
35
39
 
36
- # This is just a shortcut for Unobservable#instance_events_for . It passes
37
- # in self as the first argument.
38
- def instance_events(include_supers = true)
39
- Unobservable.instance_events_for(self, include_supers)
40
+ def instance_events(all = true)
41
+ Unobservable.instance_events_for(self, all)
40
42
  end
41
43
 
42
44
 
43
45
  private
44
46
 
47
+
45
48
  # This helper method is similar to attr_reader and attr_accessor. It allows
46
49
  # for instance events to be declared inside the body of the class.
47
50
  def attr_event(*names)
48
51
  @unobservable_instance_events ||= Set.new
49
52
 
50
53
  names.each do |n|
51
- @unobservable_instance_events.add(n.to_sym)
52
54
  define_method n do
53
55
  return event(n)
54
56
  end
57
+ @unobservable_instance_events.add(n.to_sym)
55
58
  end
56
59
 
57
60
  return @unobservable_instance_events.to_a
58
61
  end
62
+
63
+ alias :define_event :attr_event
59
64
 
60
65
  end
61
66
 
62
67
 
63
68
 
64
- module ObjectSupport
69
+ module Support
65
70
 
66
- def events
67
- unobservable_events_map.keys
71
+ def self.extended(obj)
72
+ obj.singleton_class.extend ModuleSupport
68
73
  end
69
74
 
70
- def event(name)
71
- unobservable_events_map[name]
75
+ def self.included(other_mod)
76
+ other_mod.extend ModuleSupport
72
77
  end
78
+
73
79
 
74
- private
75
- def raise_event(name, *args, &block)
76
- event(name).call(*args, &block)
80
+ def singleton_events(all = true)
81
+ if all
82
+ contributors = self.singleton_class.included_modules
83
+ contributors -= self.class.included_modules
84
+ contributors.push self.singleton_class
85
+ Unobservable.collect_instance_events_defined_by(contributors)
86
+ else
87
+ Unobservable.collect_instance_events_defined_by([self.singleton_class])
88
+ end
77
89
  end
90
+
78
91
 
79
-
80
- def unobservable_events_map
81
- @unobservable_events_map ||= initialize_unobservable_events_map(self.class)
92
+ def define_singleton_event(*name)
93
+ self.singleton_class.send(:attr_event, *name)
82
94
  end
83
95
 
84
-
85
- def initialize_unobservable_events_map(clazz)
86
- retval = {}
87
- if clazz.respond_to? :instance_events
88
- clazz.instance_events.each do |e|
89
- retval[e] = Event.new
96
+ def events(all = true)
97
+ self.singleton_class.instance_events(all)
98
+ end
99
+
100
+ def event(name)
101
+ @unobservable_events_map ||= {}
102
+ e = @unobservable_events_map[name]
103
+ if not e
104
+ if self.events.include? name
105
+ e = Event.new
106
+ @unobservable_events_map[name] = e
107
+ else
108
+ raise NameError, "Undefined event: #{name}"
90
109
  end
91
110
  end
111
+ return e
112
+ end
92
113
 
93
- return retval
114
+ private
115
+ def raise_event(name, *args, &block)
116
+ event(name).call(*args, &block)
94
117
  end
95
-
118
+
96
119
  end
97
120
 
98
121
 
99
- # Typically, when you add support for Events to a class, you also want
100
- # support for the handy attr_event keyword. So, including this module
101
- # is equivalent to the following:
102
- #
103
- # class MyClass
104
- # extend Unobservable::ModuleSupport # Get support for the attr_event keyword
105
- # include Unobservable::ObjectSupport # Get support for the instance methods
106
- # end
107
- module Support
108
- include ObjectSupport
109
-
110
- def self.included(other_mod)
111
- other_mod.extend ModuleSupport
112
- end
113
- end
122
+
114
123
 
115
124
 
116
125
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unobservable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-04 00:00:00.000000000 Z
12
+ date: 2012-11-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: shoulda
@@ -108,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
108
  version: '0'
109
109
  segments:
110
110
  - 0
111
- hash: 1737406497350544853
111
+ hash: -2089249244928206460
112
112
  required_rubygems_version: !ruby/object:Gem::Requirement
113
113
  none: false
114
114
  requirements: