Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don’t worry, you can still create the pull request.
  • 3 commits
  • 7 files changed
  • 1 commit comment
  • 1 contributor
Commits on Jun 30, 2012
@jacius jacius Actors are responsible for building and adding their own behaviors.
Added Actor#build_behavior, which constructs a behavior according to
the behavior name and options, like BehaviorFactory#add_behavior used
to do. Actor#add_behavior adds behavior dependencies, then constructs
the new behavior via build_behavior and adds it.

Perhaps build_behavior should be a class method of Behavior, but
build_behavior is closely tied to the individual actor's object
context, so I think Actor must bear the responsibility for now.

The BehaviorFactory class is now obsolete, but retained for backward
compatibility. BehaviorFactory#add_behavior and Behavior#add_behavior
now simply call Actor#add_behavior, which is the proper API to use.

Add required behaviors during Actor#add_behavior, not build_behavior.
615e10d
Commits on Jul 01, 2012
@jacius jacius Moved most BehaviorFactory specs to Actor specs.
TODO: There are 3 pending Actor specs that I can't make work because I
don't understand what's going on with the conjected/mock objects.
46d689f
@jacius jacius Fixed ActorFactory and ActorViewFactory using BehaviorFactory#add_beh…
…avior
16ac234
View
74 lib/gamebox/core/actor.rb
@@ -19,12 +19,76 @@ def configure(opts={}) # :nodoc:
self.actor_type = opts[:actor_type]
end
- # Used by BehaviorFactory#add_behavior.
- # That's probably what you want to use from within another behavior
- def add_behavior(name, behavior)
- @behaviors[name] = behavior
+ # Add a behavior to the actor, perhaps with certain options.
+ #
+ # Examples:
+ # add_behavior(:shootable)
+ # add_behavior(:shootable, :range=>3)
+ def add_behavior(behavior_name, opts={})
+ raise "nil behavior definition" if behavior_name.nil?
+
+ # For backward compatibility. The second arg used to be an already
+ # built behavior, passed from BehaviorFactory#add_behavior.
+ unless opts.is_a?(Hash)
+ @behaviors[behavior_name] = opts
+ return
+ end
+
+ bdef = Behavior.definitions[behavior_name]
+ raise "unknown behavior #{behavior_name}" unless bdef
+ deps = bdef.required_behaviors
+ if deps
+ deps.each do |dep|
+ add_behavior(dep) unless has_behavior?(dep)
+ end
+ end
+
+ @behaviors[behavior_name] = build_behavior(behavior_name, opts)
+ end
+
+ # Build and return a new behavior using the given behavior_name and
+ # opts. The returned behavior should only be used with this actor.
+ def build_behavior(behavior_name, opts)
+ bdef = Behavior.definitions[behavior_name]
+ raise "unknown behavior #{behavior_name}" unless bdef
+
+ context = this_object_context
+ behavior = context.in_subcontext do |sub|
+ sub[:behavior]
+ end
+
+ reqs = bdef.required_injections
+ if reqs
+ reqs.each do |req|
+ object = context[req]
+ behavior.define_singleton_method(req) do
+ components[req]
+ end
+ components = behavior.send :components
+ components[req] = object
+ end
+ end
+
+ helpers = bdef.helpers_block
+ if helpers
+ helpers_module = Module.new &helpers
+ behavior.extend helpers_module
+ end
+
+ if bdef.react_to_block
+ behavior.define_singleton_method :react_to, bdef.react_to_block
+ end
+
+ behavior.configure(opts)
+
+ if bdef.setup_block
+ behavior.instance_eval &bdef.setup_block
+ end
+
+ behavior
end
-
+ private :build_behavior
+
def remove_behavior(name)
@behaviors.delete(name).tap do |behavior|
behavior.react_to :remove if behavior
View
2 lib/gamebox/core/actor_factory.rb
@@ -31,7 +31,7 @@ def build(actor, opts={})
beh_key = behavior.keys.first
end
- behavior_factory.add_behavior(model, beh_key, beh_opts)
+ model.add_behavior(beh_key, beh_opts)
end
actor_view_factory.build model, opts
View
2 lib/gamebox/core/actor_view_factory.rb
@@ -32,7 +32,7 @@ def build(actor, opts={})
view.configure
end
- behavior_factory.add_behavior(actor, :visible, view: view)
+ actor.add_behavior(:visible, view: view)
actor.react_to :show unless opts[:hide]
end
view
View
2 lib/gamebox/core/behavior.rb
@@ -24,7 +24,7 @@ def react_to(message_type, *opts)
end
def add_behavior(behavior_name, opts = {})
- behavior_factory.add_behavior actor, behavior_name, opts
+ actor.add_behavior behavior_name, opts
end
class << self
View
54 lib/gamebox/core/behavior_factory.rb
@@ -1,55 +1,11 @@
-# BehaviorFactory is in charge of creating all behaviors and placing them in an Actor.
-# Everything you want an Actor to _do_ is part of a Behavior. Actors are stupid buckets of data.
-# Behaviors can be created by:
-# has_behavior in an Actor's class definition
-# or by dynamically creating one at runtime via another behavior.
+
+# This class is obsolete, but retained for backward compatibility.
+# Use Actor#add_behavior instead.
class BehaviorFactory
- # Build a behavior.
- # add_behavior(actor, :shootable) or add_behavior(actor, :shootable, :range=>3)
- # this will create a new instance of Shootable and pass :range=>3 to it
+ # Obsolete. Use Actor#add_behavior instead.
def add_behavior(actor, behavior_name, opts = {})
- raise "nil actor" if actor.nil?
- raise "nil behavior definition" if behavior_name.nil?
-
- behavior_definition = Behavior.definitions[behavior_name]
-
- raise "unknown behavior #{behavior_name}" unless behavior_definition
- context = actor.this_object_context
- context.in_subcontext do |behavioral_context|
- behavioral_context[:behavior].tap do |behavior|
- reqs = behavior_definition.required_injections
- if reqs
- reqs.each do |req|
- object = context[req]
- behavior.define_singleton_method req do
- components[req]
- end
- components = behavior.send :components
- components[req] = object
- end
- end
-
- helpers = behavior_definition.helpers_block
- if helpers
- helpers_module = Module.new &helpers
- behavior.extend helpers_module
- end
-
- behavior.define_singleton_method :react_to, behavior_definition.react_to_block if behavior_definition.react_to_block
-
- deps = behavior_definition.required_behaviors
- if deps
- deps.each do |beh|
- add_behavior actor, beh unless actor.has_behavior?(beh)
- end
- end
- behavior.configure(opts)
- behavior.instance_eval &behavior_definition.setup_block if behavior_definition.setup_block
- actor.add_behavior behavior_name, behavior
- end
- end
+ actor.add_behavior behavior_name, opts
end
-
end
View
38 spec/core/actor_spec.rb
@@ -21,10 +21,42 @@
end
describe "#add_behavior" do
- it 'adds a behavior to the actors list of behaviors' do
- subject.add_behavior :foo, :bar
- subject.has_behavior?(:foo).should be_true
+ before do
+ define_behavior :test_behavior do
+ setup do
+ actor.has_attributes(test_attr: opts[:test_attr])
+ end
+ end
+ end
+
+ it 'adds a behavior to the actor\'s list of behaviors' do
+ pending "jacius doesn't understand conjected objects"
+ subject.add_behavior :test_behavior
+ subject.has_behavior?(:test_behavior).should be_true
end
+
+ it 'sets up the behavior on the actor' do
+ pending "jacius doesn't understand conjected objects"
+ subject.add_behavior :test_behavior
+ subject.has_attribute?(:test_attr).should be_true
+ end
+
+ it 'configures the behavior with the given opts' do
+ pending "jacius doesn't understand conjected objects"
+ subject.add_behavior :test_behavior, test_attr: 'test'
+ subject.test_attr.should == 'test'
+ end
+
+ it 'raises on nil behavior def' do
+ lambda { subject.add_behavior nil }.should raise_exception(/nil behavior definition/)
+ end
+
+ it 'raises for missing behavior' do
+ lambda { subject.add_behavior :undefined_behavior }.should raise_exception
+ end
+
+ it 'creates all required behaviors'
+ it 'mixes in helpers'
end
describe "#remove_behavior" do
View
47 spec/core/behavior_factory_spec.rb
@@ -1,50 +1,13 @@
require 'helper'
describe BehaviorFactory do
- let(:some_behavior) { stub('some behavior', required_behaviors: []) }
- let(:object_context) { mock('object context') }
- let(:some_actor) { stub('some actor', add_behavior: nil, this_object_context: object_context) }
-
- before do
- Behavior.define :shootable
-
- object_context.stubs(:[]).with(:behavior).returns(some_behavior)
- object_context.stubs(:in_subcontext).yields(object_context)
- some_behavior.stubs(:configure)
- end
-
describe "#add_behavior" do
- it 'creates the behavior based on the actor and symbol behavior_def' do
- some_behavior.expects(:configure).with({})
-
- subject.add_behavior some_actor, :shootable
- end
-
- it 'adds the behavior to the actor' do
- some_actor.expects(:add_behavior).with(:shootable, some_behavior)
- subject.add_behavior some_actor, :shootable
- end
+ it "should call #add_behavior on the actor" do
+ opts = {foo: 'bar'}
+ some_actor = stub("actor")
+ some_actor.expects(:add_behavior).with(:some_behavior, opts)
- it 'configures the behavior with the given opts' do
- opts = {some: 'opts'}
- some_behavior.expects(:configure).with(opts)
-
- subject.add_behavior some_actor, :shootable, opts
- end
-
- it 'raises on nil actor' do
- lambda { subject.add_behavior nil, {} }.should raise_exception(/nil actor/)
- end
-
- it 'raises on nil behavior def' do
- lambda { subject.add_behavior some_actor, nil }.should raise_exception(/nil behavior definition/)
- end
-
- it 'raises for missing behavior' do
- lambda { subject.add_behavior actor, :do_not_exist }.should raise_exception
+ subject.add_behavior( some_actor, :some_behavior, opts )
end
-
- it 'creates all required behaviors'
- it 'mixes in helpers'
end
end

Showing you all comments on commits in this comparison.

@jasonroelofs
Collaborator

Nor should you!

/troll

Also, actor\'s? Double quotes ho!

Something went wrong with that request. Please try again.