lib/kindergarten/sandbox.rb in kindergarten-0.1.0 vs lib/kindergarten/sandbox.rb in kindergarten-0.1.1
- old
+ new
@@ -1,32 +1,34 @@
module Kindergarten
class Sandbox
- attr_reader :child, :governess, :perimeter, :purpose
+ attr_reader :child, :governess, :perimeters, :purpose
def initialize(child)
@child = child
@governess = Kindergarten::HeadGoverness.new(child)
- @purpose = {}
- @perimeter = []
- def @perimeter.include?(other)
- (self.collect(&:class) & [ other.class ]).any?
- end
+ @purpose = {}
+ @perimeters = []
@unguarded = false
end
def extend_perimeter(*perimeter_classes)
perimeter_classes.each do |perimeter_class|
+ if @perimeters.collect(&:class).include?(perimeter_class)
+ # already have this one
+ return
+ end
+
# if the perimeter specifies a governess, use that - otherwise appoint
# the head governess
child = self.child
governess = perimeter_class.governess ?
perimeter_class.governess.new(child) :
self.governess
- perimeter = perimeter_class.new(child, governess)
+ perimeter = perimeter_class.new(self, governess)
raise ArgumentError.new(
"Module must inherit from Kindergarten::Perimeter"
) unless perimeter.kind_of?(Kindergarten::Perimeter)
@@ -35,11 +37,24 @@
# the head governess must know all the rules
unless governess == self.governess || perimeter_class.govern_proc.nil?
self.governess.instance_eval(&perimeter_class.govern_proc)
end
- @perimeter << perimeter unless @perimeter.include?(perimeter)
+ perimeter_class.subscriptions.each do |purpose, events|
+ if self.purpose[purpose].nil?
+ Kindergarten.warning "#{perimeter_class} has subscriptions on un-loaded purpose :#{purpose}"
+ next
+ end
+
+ events.each do |event, blocks|
+ blocks.each do |block|
+ self.purpose[purpose]._subscribe(event, &block)
+ end
+ end
+ end
+
+ @perimeters << perimeter
end
end
alias_method :load_perimeter, :extend_perimeter
alias_method :load_module, :extend_perimeter
@@ -70,9 +85,47 @@
def disallows?(action, target)
governess.cannot?(action, target)
end
alias_method :disallowed?, :disallows?
+
+ def guard(action, target, opts={})
+ unless allows?(action, target)
+ raise Kindergarten::AccessDenied.new(action, target, opts)
+ end
+ end
+
+ def subscribe(purpose_name, *events, &block)
+ unless (purpose = @purpose[purpose_name.to_sym])
+ Kindergarten.warning "No such purpose has been loaded: #{purpose_name}"
+ return
+ end
+
+ events.each do |event|
+ purpose._subscribe(event, &block)
+ end
+ end
+
+ def unsubscribe(purpose_name, *events)
+ unless (purpose = @purpose[purpose_name.to_sym])
+ Kindergarten.warning "No such purpose has been loaded: #{purpose_name}"
+ return
+ end
+
+ events.each do |event|
+ purpose._unsubscribe(event)
+ end
+ end
+
+ def broadcast(&block)
+ @broadcast = block
+ end
+
+ def broadcast!(event)
+ return if @broadcast.nil?
+
+ @broadcast.call(event)
+ end
# TODO: Find a purpose and call that - move this block to Purpose
def method_missing(name, *args, &block)
super