recess 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,10 @@
1
1
  require "recess/version"
2
2
 
3
3
  module Recess
4
- module Inside
5
-
6
- end
4
+
7
5
  end
8
6
 
7
+ require "recess/util"
9
8
  require "recess/outside"
10
9
  require "recess/inside"
11
-
10
+ require "recess/game"
@@ -0,0 +1,109 @@
1
+ module Recess::Game
2
+ module ClassMethods
3
+ def recess_list_of_games
4
+ @game_with ||= []
5
+ end
6
+
7
+ def game_with(what, options = {})
8
+ clazz_name = what.to_s
9
+ rules_clazz = Recess::Util.constantize(clazz_name)
10
+ args = rules_clazz.list.clone
11
+ args << options
12
+ send(:inside, clazz_name, *args)
13
+ recess_list_of_games << clazz_name
14
+
15
+ unless method_defined? :recess_rules_game_object_mapping
16
+ define_method(:recess_rules_game_object_mapping) do |rule|
17
+ key = rule.to_s
18
+ @cached_recess_games ||= self.recess_games
19
+ @recess_rules_game_object_mapping ||= {}
20
+
21
+ game_clazz_name = @cached_recess_games[key]
22
+ # TODO: try again if it's not there? always try?
23
+ raise "No game implementation of #{key} given." unless game_clazz_name
24
+
25
+ game_clazz_name = game_clazz_name.to_s
26
+ game_clazz = Recess::Util.constantize(game_clazz_name)
27
+ @recess_rules_game_object_mapping[key] = nil unless @recess_rules_game_object_mapping[key].is_a? game_clazz
28
+ return @recess_rules_game_object_mapping[key] if @recess_rules_game_object_mapping[key]
29
+
30
+ # see if we already have this object
31
+ obj = nil
32
+ @cached_recess_games.each do |rule_key, name|
33
+ if name.to_s == game_clazz_name
34
+ obj = @recess_rules_game_object_mapping[rule_key]
35
+ break if obj
36
+ end
37
+ end
38
+
39
+ unless obj
40
+ data_method = self.class.recess_inside_objects_options[clazz_name][:data]
41
+ obj = game_clazz.new(self, data_method)
42
+ end
43
+
44
+ @recess_rules_game_object_mapping[key] = obj
45
+ end
46
+ end
47
+
48
+ unless method_defined? :recess_reset_games
49
+ define_method(:recess_reset_games) do
50
+ @cached_recess_games = nil
51
+ @recess_rules_game_object_mapping = nil
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ class Rules < Recess::Inside::Base
58
+ def self.rule(method_name)
59
+ list << method_name.to_sym
60
+
61
+ define_method method_name do |*args|
62
+ raise "there is no parent object" unless parent_root
63
+ game_object = parent_root.recess_rules_game_object_mapping(self.class.name.to_s)
64
+ game_object.send(method_name, *args)
65
+ end
66
+ end
67
+
68
+ def self.list
69
+ @list ||= []
70
+ end
71
+ end
72
+
73
+ class Base < Recess::Inside::Base
74
+ def self.rules(clazz)
75
+ list_of_rules << clazz.to_s
76
+ end
77
+ def self.list_of_rules
78
+ @rules ||= []
79
+ end
80
+
81
+ def self.broken_rules
82
+ out = []
83
+ rule_methods_needed.each do |meth|
84
+ out << meth unless self.method_defined? meth
85
+ end
86
+ out
87
+ end
88
+
89
+ def self.follow_rules!
90
+ missing = self.broken_rules
91
+ raise "#{self.name} is missing rule method(s): [#{missing.join(", ")}]" unless missing.size == 0
92
+ end
93
+
94
+ protected
95
+
96
+ def self.rule_methods_needed
97
+ out = []
98
+ list_of_rules.each do |clazz_name|
99
+ rules_clazz = Recess::Util.constantize(clazz_name.to_s)
100
+ out.concat rules_clazz.list
101
+ end
102
+ out.uniq
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+
109
+ Object.send :include, Recess::Game::ClassMethods
@@ -3,7 +3,7 @@ module Recess::Inside
3
3
  def recess_inside_instance_methods(from_base=nil)
4
4
  return [] unless @recess_inside_instance_methods
5
5
  return @recess_inside_instance_methods.keys unless from_base
6
- (@recess_inside_base_classes[from_base] || []).uniq
6
+ (@recess_inside_base_classes[from_base.to_s] || []).uniq
7
7
  end
8
8
 
9
9
  def recess_inside_objects_options
@@ -12,13 +12,15 @@ module Recess::Inside
12
12
 
13
13
  def inside(what, *args)
14
14
  options = args.last.is_a?(::Hash) ? args.pop : {}
15
- object_clazz = what
16
- recess_inside_objects_options[object_clazz.to_s] = options
15
+ clazz_name = what.to_s
16
+ object_clazz = Recess::Util.constantize(clazz_name)
17
+
18
+ recess_inside_objects_options[clazz_name] = options
17
19
 
18
20
  @recess_inside_instance_methods ||= {}
19
21
  @recess_inside_base_classes ||= {}
20
22
 
21
- unless @recess_inside_base_classes[object_clazz]
23
+ unless @recess_inside_base_classes[clazz_name]
22
24
  if object_clazz.respond_to?(:insided)
23
25
  if object_clazz.method(:insided).arity == 1
24
26
  object_clazz.insided(self)
@@ -29,18 +31,20 @@ module Recess::Inside
29
31
  end
30
32
 
31
33
  object_clazz.all_parent_instance_methods.each do |used|
32
- @recess_inside_base_classes[object_clazz] ||= []
33
- @recess_inside_base_classes[object_clazz] << used
34
+ @recess_inside_base_classes[clazz_name] ||= []
35
+ @recess_inside_base_classes[clazz_name] << used
34
36
 
35
37
  @recess_inside_instance_methods[used] ||= []
36
- @recess_inside_instance_methods[used] << object_clazz
38
+ @recess_inside_instance_methods[used] << clazz_name
37
39
  end
38
40
 
39
41
  unless method_defined? :recess_inside_instance_objects
40
- define_method(:recess_inside_instance_objects) do |clazz|
41
- data_method = self.class.recess_inside_objects_options[clazz.to_s][:data]
42
+ define_method(:recess_inside_instance_objects) do |the_name|
43
+ the_name = the_name.to_s
44
+ clazz = Recess::Util.constantize(the_name)
45
+ data_method = self.class.recess_inside_objects_options[the_name][:data]
42
46
  @recess_inside_instance_objects ||= {}
43
- @recess_inside_instance_objects[clazz.to_s] ||= clazz.new(self, data_method)
47
+ @recess_inside_instance_objects[the_name] ||= clazz.new(self, data_method)
44
48
  end
45
49
  end
46
50
 
@@ -57,7 +61,7 @@ module Recess::Inside
57
61
  end
58
62
 
59
63
  define_method delegated do |*args|
60
- recess_inside_instance_objects(object_clazz).send(delegated, *args)
64
+ recess_inside_instance_objects(clazz_name).send(delegated, *args)
61
65
  end
62
66
  end
63
67
  end
@@ -0,0 +1,14 @@
1
+ module Recess::Util
2
+ extend self
3
+
4
+ def constantize(camel_cased_word)
5
+ names = camel_cased_word.split('::')
6
+ names.shift if names.empty? || names.first.empty?
7
+
8
+ constant = Object
9
+ names.each do |name|
10
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
11
+ end
12
+ constant
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Recess
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -18,8 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_development_dependency 'rspec', '1.3.0'
22
- s.add_development_dependency 'mocha', '0.9.8'
21
+ s.add_development_dependency 'rspec'
23
22
 
24
23
  # specify any dependencies here; for example:
25
24
  # s.add_development_dependency "rspec"
@@ -0,0 +1,144 @@
1
+ require 'spec_helper'
2
+
3
+ class TestRules1 < Recess::Game::Rules
4
+ rule :must_have_one
5
+ rule :other_one
6
+ rule "third"
7
+ end
8
+
9
+ class TestRules2 < Recess::Game::Rules
10
+ rule :extra2
11
+ end
12
+
13
+ class TestGame1 < Recess::Game::Base
14
+ rules "TestRules2"
15
+
16
+ def extra2
17
+ "yes"
18
+ end
19
+ end
20
+
21
+ class TestGame2 < Recess::Game::Base
22
+ rules TestRules2
23
+
24
+ def extra2_not_here
25
+ "no"
26
+ end
27
+ end
28
+
29
+ class TestGame3 < Recess::Game::Base
30
+ rules TestRules1
31
+ rules "TestRules2"
32
+
33
+ def must_have_one
34
+
35
+ end
36
+
37
+ def other_one
38
+
39
+ end
40
+
41
+ def third
42
+ "333"
43
+ end
44
+
45
+ def extra2
46
+ "other"
47
+ end
48
+ end
49
+
50
+ class TestGame4 < Recess::Game::Base
51
+ rules TestRules1
52
+ rules TestRules2
53
+
54
+ def must_have_one
55
+
56
+ end
57
+
58
+ def missing_several
59
+
60
+ end
61
+ end
62
+
63
+ class TestGameObject1
64
+ game_with TestRules1
65
+ game_with TestRules2
66
+
67
+ def recess_games
68
+ {"TestRules2" => "TestGame1", "TestRules1" => TestGame3}
69
+ end
70
+ end
71
+
72
+ describe "Rules" do
73
+ it "should list out the methods" do
74
+ TestRules1.list.should =~ [:must_have_one, :other_one, :third]
75
+ end
76
+ end
77
+
78
+ describe "Games" do
79
+ describe "following rules" do
80
+ it "should raise if it doesn't implement all methods" do
81
+ lambda {
82
+ TestGame1.follow_rules!
83
+ }.should_not raise_error
84
+
85
+ lambda {
86
+ TestGame2.follow_rules!
87
+ }.should raise_error
88
+
89
+ lambda {
90
+ TestGame3.follow_rules!
91
+ }.should_not raise_error
92
+
93
+ lambda {
94
+ TestGame4.follow_rules!
95
+ }.should raise_error
96
+ end
97
+
98
+ it "should get a list of rules it doesn't follow" do
99
+ TestGame1.broken_rules.should == []
100
+ TestGame2.broken_rules.should =~ [:extra2]
101
+ TestGame3.broken_rules.should == []
102
+ TestGame4.broken_rules.should =~ [:other_one, :third, :extra2]
103
+ end
104
+ end
105
+ end
106
+
107
+ describe "Containers" do
108
+ it "should delegate to the implementation" do
109
+ obj = TestGameObject1.new
110
+ obj.respond_to?(:extra2).should == true
111
+ obj.extra2.should == "yes"
112
+ obj.third.should == "333"
113
+
114
+ obj.recess_reset_games
115
+ obj.stub(:recess_games).and_return({"TestRules2" => TestGame3})
116
+ obj.extra2.should == "other"
117
+ end
118
+
119
+ it "should raise if it's not there" do
120
+ obj = TestGameObject1.new
121
+ obj.stub(:recess_games).and_return({})
122
+ lambda {
123
+ obj.extra2
124
+ }.should raise_error
125
+ end
126
+
127
+ it "should use the same instances if possible" do
128
+ obj = TestGameObject1.new
129
+ obj.stub(:recess_games).and_return({"TestRules2" => "TestGame3", "TestRules1" => TestGame3})
130
+ obj.extra2.should == "other"
131
+ obj.third.should == "333"
132
+
133
+ instance1 = obj.recess_rules_game_object_mapping("TestRules1")
134
+ instance2 = obj.recess_rules_game_object_mapping("TestRules2")
135
+
136
+ instance1.extra2.should == "other"
137
+ instance1.third.should == "333"
138
+ instance2.extra2.should == "other"
139
+ instance2.third.should == "333"
140
+
141
+ instance1.object_id.should == instance2.object_id
142
+ end
143
+
144
+ end
@@ -81,7 +81,7 @@ class TestContainer4
81
81
  @called_value
82
82
  end
83
83
 
84
- inside TestInside4, :foo
84
+ inside "TestInside4", :foo
85
85
  end
86
86
 
87
87
  class TestExample1Data
@@ -119,6 +119,8 @@ describe "Containers" do
119
119
  TestContainer1.recess_inside_instance_methods.should =~ ["foo", "foo="]
120
120
  TestContainer1.recess_inside_instance_methods(TestInside1).should =~ ["foo", "foo="]
121
121
  TestContainer3.recess_inside_instance_methods(TestInside2).should =~ ["foo"]
122
+ TestContainer1.recess_inside_instance_methods("TestInside1").should =~ ["foo", "foo="]
123
+ TestContainer3.recess_inside_instance_methods("TestInside2").should =~ ["foo"]
122
124
  end
123
125
 
124
126
  it "should allow call through to super" do
@@ -1,12 +1,12 @@
1
1
  require 'rubygems'
2
- require 'bundler'
3
-
4
- Bundler.setup
5
-
6
- require 'spec/autorun'
2
+ require 'bundler/setup'
3
+ require 'rspec'
7
4
 
8
5
  require 'recess'
9
6
 
10
- Spec::Runner.configure do |config|
11
-
7
+ RSpec.configure do |config|
8
+ config.mock_with :rspec
9
+ config.filter_run :focus => true
10
+ config.run_all_when_everything_filtered = true
11
+ config.order = 'random'
12
12
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: recess
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brian Leonard
@@ -15,7 +15,8 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-05-30 00:00:00 Z
18
+ date: 2012-10-24 00:00:00 -07:00
19
+ default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: rspec
@@ -23,32 +24,14 @@ dependencies:
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
24
25
  none: false
25
26
  requirements:
26
- - - "="
27
+ - - ">="
27
28
  - !ruby/object:Gem::Version
28
- hash: 27
29
+ hash: 3
29
30
  segments:
30
- - 1
31
- - 3
32
31
  - 0
33
- version: 1.3.0
32
+ version: "0"
34
33
  type: :development
35
34
  version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: mocha
38
- prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
42
- - - "="
43
- - !ruby/object:Gem::Version
44
- hash: 43
45
- segments:
46
- - 0
47
- - 9
48
- - 8
49
- version: 0.9.8
50
- type: :development
51
- version_requirements: *id002
52
35
  description: You know, to break up your classes.
53
36
  email:
54
37
  - brian@bleonard.com
@@ -65,14 +48,18 @@ files:
65
48
  - README.mdown
66
49
  - Rakefile
67
50
  - lib/recess.rb
51
+ - lib/recess/game.rb
68
52
  - lib/recess/inside.rb
69
53
  - lib/recess/outside.rb
54
+ - lib/recess/util.rb
70
55
  - lib/recess/version.rb
71
56
  - recess.gemspec
57
+ - spec/game_spec.rb
72
58
  - spec/inside_spec.rb
73
59
  - spec/outside_spec.rb
74
60
  - spec/spec_helper.rb
75
61
  - spec/test_spec.rb
62
+ has_rdoc: true
76
63
  homepage: ""
77
64
  licenses: []
78
65
 
@@ -102,11 +89,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
89
  requirements: []
103
90
 
104
91
  rubyforge_project: recess
105
- rubygems_version: 1.8.21
92
+ rubygems_version: 1.6.0
106
93
  signing_key:
107
94
  specification_version: 3
108
95
  summary: You know, to break up your classes.
109
96
  test_files:
97
+ - spec/game_spec.rb
110
98
  - spec/inside_spec.rb
111
99
  - spec/outside_spec.rb
112
100
  - spec/spec_helper.rb