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