unobservable 0.1.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: