recess 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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