class Eaco::Cucumber::World

The world in which scenarios are run. This is a story and an example, real-world data model that can be effectively protected by Eaco.

But +before { some :art }+

AYANAMI REI

                                   __.-"..--,__
                              __..---"  | _|    "-_\
                       __.---"          | V|::.-"-._D
                  _--"".-.._   ,,::::::'"\/""'-:-:/
             _.-""::_:_:::::'-8b---"            "'
          .-/  ::::<  |\::::::"\
          \/:::/::::'\\ |:::b::\
          /|::/:::/::::-::b:%b:\|
           \/::::d:|8:::b:"%%%%%\
           |\:b:dP:d.:::%%%%%"""-,
            \:\.V-/ _\b%P_   /  .-._
            '|T\   "%j d:::--\.(    "-.
            ::d<   -" d%|:::do%P"-:.   "-,
            |:I _    /%%%o::o8P    "\.    "\
             \8b     d%%%%%%P""-._ _ \::.    \
             \%%8  _./Y%%P/      .::'-oMMo    )
               H"'|V  |  A:::...:odMMMMMM(  ./
               H /_.--"JMMMMbo:d##########b/
            .-'o      dMMMMMMMMMMMMMMP""
          /" /       YMMMMMMMMM|
        /   .   .    "MMMMMMMM/
        :..::..:::..  MMMMMMM:|
         \:/ \::::::::JMMMP":/
          :Ao ':__.-'MMMP:::Y
          dMM"./:::::::::-.Y
         _|b::od8::/:YM::/
         I HMMMP::/:/"Y/"
          \'""'  '':|
           |    -::::\
           |  :-._ '::\
           |,.|    \ _:"o
           | d" /   " \_:\.
           ".Y. \       \::\
            \ \  \      MM\:Y
             Y \  |     MM \:b
             >\ Y      .MM  MM
             .IY L_    MP'  MP
             |  \:|   JM   JP
             |  :\|   MP   MM
             |  :::  JM'  JP|
             |  ':' JP   JM |
             L   : JP    MP |
             0   | Y    JM  |
             0   |     JP"  |
             0   |    JP    |
             m   |   JP     #
             I   |  JM"     Y
             l   |  MP     :"
             |\  :-       :|
             | | '.\      :|
             | | "| \     :|
              \    \ \    :|
              |  |  | \   :|
              |  |  |   \ :|
              |   \ \    | '.
              |    |:\   | :|
              \    |::\..|  :\
               ". /::::::'  :||
                 :|::/:::|  /:\
                 | \/::|: \' ::|
                 |  :::||    ::|
                 |   ::||    ::|
                 |   ::||    ::|
                 |   ::||    ::|
                 |   ': |    .:|
                 |    : |    :|
                 |    : |    :|
                 |    :||   .:|
                 |   ::\   .:|
                |    :::  .::|
               /     ::|  :::|
            __/     .::|   ':|
   ...----""        ::/     ::
  /m_  AMm          '/     .:::
  ""MmmMMM#mmMMMMMMM"     .:::m
     """YMMM""""""P        ':mMI
              _'           _MMMM
          _.-"  mm   mMMMMMMMM"
         /      MMMMMMM""
         mmmmmmMMMM"
                          ch1x0r

http://ascii.co.uk/art/anime

Scenario

In this imaginary world we are N E R V, a Top Secret organization that handles very confidential documents. Some users can read them, some can edit them, and very few bosses can destroy them.

The organization employs internal staff and employs consultants. Staff members have official positions in the organization hierarchy, and they belong to units within departments. They have the big picture.

Consultants, on the other hand, come and go, and work on small parts of the documents, for specific purposes. They do not have the big picture.

Departments own the documents, not people. Documents are of interest of departments, sometimes they should be accessed by the whole house, some other time only few selected users, some times two specific departments or some units.

Either way, most of the time, access is granted to who owns a peculiar authority within the organization and not to a specific person. People may change, authorities and rules change less often.

Mapping Eaco concepts

The Document is a {Eaco::Resource}

Each instance of a Document has an {Eaco::ACL} .acl attribute.

The :reader, :editor and :owner are Roles on the Document resource, and each role is granted a Permission.

The User is a {Eaco::Actor}.

Having an user account is the {Eaco::Designator} of type :user. Occupying an official position is the Designator of type :position. Belonging to a department is the Designator of type :department

Public Class Methods

new() click to toggle source

Sets up the World:

# File lib/eaco/cucumber/world.rb, line 139
def initialize
  Eaco::Cucumber::ActiveRecord.connect!
end

Public Instance Methods

actors() click to toggle source

All registered {Actor} instances.

@return [Hash] actors keyed by name

# File lib/eaco/cucumber/world.rb, line 232
def actors
  @actors ||= {}
end
authorize_model(name, definition) click to toggle source

Authorizes model with the given {DSL}

@param name [String] the model name @param definition [String] the {DSL} code @see {#find_model}

@return [void]

# File lib/eaco/cucumber/world.rb, line 152
def authorize_model(name, definition)
  model = find_model(name)

  eval_dsl definition, model
end
check_documents(names, &block) click to toggle source

Checks the given block on the given set of Document

@param names [String] the document names, separated by +,+ @param block [Proc] the code to run on each Document

@return [void]

@see Eaco::Cucumber::ActiveRecord::Document

# File lib/eaco/cucumber/world.rb, line 256
def check_documents(names, &block)
  model = find_model('Document')
  names = names.split(/,\s*/)
  model.where(name: names).each(&block)
end
eval_dsl(code, model = nil) click to toggle source

Evaluates the given {Eaco::DSL} code, substituting the +$MODEL+ string with the given model name.

@param code [String] the DSL code to eval @param model [Class] the model name to substitute (optional)

@return [void]

# File lib/eaco/cucumber/world.rb, line 285
def eval_dsl(code, model = nil)
  # Sub in place to print final code when running cucumber
  code.sub! '$MODEL', model.name if model
  Eaco.eval! code, '(feature)'
end
fetch_actor(name) click to toggle source

Fetches an {Actor} instance by name.

@param name [String] the actor name @return [Actor] the registered actor name @raise [RuntimeError] if the actor is not found in the registry

# File lib/eaco/cucumber/world.rb, line 185
def fetch_actor(name)
  actors.fetch(name)
rescue KeyError
  # :nocov:
  raise "Actor '#{name}' not found in registry"
  # :nocov:
end
fetch_resource(model, name) click to toggle source

Fetches a {Resource} instance by name.

@param model [String] the {Resource} model name @param name [String] the {Resource} name

# File lib/eaco/cucumber/world.rb, line 219
def fetch_resource(model, name)
  resources.fetch(model).fetch(name)
rescue KeyError
  # :nocov:
  raise "Resource #{model} '#{name}' not found in registry"
  # :nocov:
end
find_model(model_name) click to toggle source

Returns a model in the {ActiveRecord} namespace.

Example:

World.find_model('Document')

@param model_name [String] the model name @return [Class]

# File lib/eaco/cucumber/world.rb, line 272
def find_model(model_name)
  Eaco::Cucumber::ActiveRecord.const_get(model_name)
end
register_actor(model, name, options = {}) click to toggle source

Registers and persists an {Actor} instance with the given name.

@param model [String] the {Actor} model name @param name [String] the {Actor} instance name @param options [Boolean] the only supported one is admin, and

specifies whether this {Actor} an admin

@return [Actor] the newly created {Actor} instance.

# File lib/eaco/cucumber/world.rb, line 168
def register_actor(model, name, options = {})
  actor_model = find_model(model)

  actors[name] = actor_model.new.tap do |actor|
    actor.name  = name
    actor.admin = options.fetch(:admin, false)
    actor.save!
  end
end
register_resource(model, name) click to toggle source

Registers and persists {Resource} instance with the given name.

@param model [String] the {Resource} model name @param name [String] the {Resource} name

@return [Resource] the newly instantiated {Resource}

# File lib/eaco/cucumber/world.rb, line 201
def register_resource(model, name)
  resource_model = find_model(model)

  resource = resource_model.new.tap do |resource|
    resource.name = name
    resource.save!
  end

  resources[model] ||= {}
  resources[model][name] = resource
end
resources() click to toggle source

All registered {Resource} instances.

@return [Hash] resources keyed by model name with +Hash+es

as values keyed by resource name.
# File lib/eaco/cucumber/world.rb, line 242
def resources
  @resources ||= {}
end