-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy path07-plugin-system-v5.rb
122 lines (102 loc) · 2.09 KB
/
07-plugin-system-v5.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
class Libry
class Book; end
class User; end
module Plugins
module Core
module BookMethods
attr_accessor :checked_out_to
def initialize(name)
@name = name
end
def checkin
checked_out_to.books.delete(self)
@checked_out_to = nil
end
end
module UserMethods
attr_accessor :books
def initialize(id)
@id = id
@books = []
end
def checkout(book)
book.checked_out_to = self
@books << book
end
end
end
end
def self.plugin(mod)
if defined?(mod::BookMethods)
Book.include(mod::BookMethods)
end
if defined?(mod::UserMethods)
User.include(mod::UserMethods)
end
if defined?(mod::BookClassMethods)
Book.extend(mod::BookClassMethods)
end
if defined?(mod::UserClassMethods)
User.extend(mod::UserClassMethods)
end
mod.after_load if mod.respond_to?(:after_load)
end
plugin(Plugins::Core)
end
class Libry
module Plugins
module Cursing
module BookMethods
def curse!
@cursed = true
end
def checked_out_to=(user)
user.curse! if @cursed
super
end
end
module UserMethods
def curse!
@cursed = true
end
def checkout(book)
super unless @cursed
end
end
end
end
end
module Libry::Plugins::Tracking
def self.after_load
[Libry::Book, Libry::User].each do |klass|
klass.instance_exec{@tracked ||= []}
end
end
module TrackingMethods
attr_reader :tracked
def new(*)
obj = super
@tracked << obj
obj
end
end
BookClassMethods = TrackingMethods
UserClassMethods = TrackingMethods
end
module Libry::Plugins::AutoCurse
module BookMethods
def initialize(*)
super
curse!
end
end
module UserMethods
def curse!
super
books.each(&:curse!)
end
end
end
Libry.plugin(Libry::Plugins::AutoCurse)
Libry::Book.new('a')
# NoMethodError: undefined method `curse!'