memo Accountability

# http://martinfowler.com/apsupp/accby.pdf
class AccountabilityType
  attr_accessor :name
  def initialize name
    @name = name
  end
end

class Accountability
  attr_accessor :parent, :child, :type
    
  def initialize &block
    yield self
    parent.friend_add_child_accountability(self)
    child.friend_add_parent_accountability(self)
  end
end

class Party
  attr_accessor :name
  def initialize name
    @name = name
    @parent_accountabilities = []
    @child_accountabilities = []
  end
  

  def parents(type = nil)
    @parent_accountabilities.inject [] do |result, acc|
      if type.nil? || (acc.type == type)
        result << acc.parent
      end
      result
    end
  end
  
  def children(type = nil)
    @child_accountabilities.inject [] do |result, acc|
      if type.nil? || (acc.type == type)
        result << acc.child
      end
      result
    end
  end
  
  def friend_add_child_accountability child
    @child_accountabilities << child unless @child_accountabilities.include? child
  end
  
  def friend_add_parent_accountability parent
    @parent_accountabilities << parent unless @parent_accountabilities.include? parent
  end
end

describe "acountablity" do
  before(:each) do
    @supervision = AccountabilityType.new("Supervies")
    @mark = Party.new "mark"
    @tom = Party.new "tom"
    @stMarys = Party.new "St Mary's"
  end
  
  describe "accountability exmaple " do
    before(:each) do
      Accountability.new do |c|
        c.parent = @stMarys
        c.child = @mark
        c.type = @supervision
      end
      Accountability.new do |c|
        c.parent = @stMarys
        c.child = @tom
        c.type = @supervision
      end
    end
    
    it "should include related child" do
      @stMarys.children.should include @tom
      @stMarys.children(@supervision).should include @mark
      @stMarys.children(AccountabilityType.new("notfound")).should_not include @mark
    end
    
    it "should include related parent" do
      @tom.parents().should include @stMarys
      @tom.parents(@supervision).should include @stMarys
      @tom.parents(AccountabilityType.new("notfound")).should_not include @stMarys
    end
  end
end