ccp 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,111 @@
1
+ = ccp
2
+
3
+ CCP is a Ruby library for Composite Command Programming
4
+ that helps you to split spaghetti codes into pieces.
5
+
6
+ === Websites
7
+ * http://github.com/maiha/ccp
8
+
9
+ == What is a Composite Command Programming?
10
+
11
+ There are three principles.
12
+
13
+ 1. SRP (Single responsibility principle)
14
+ 2. Typed Variables (especially needed in Ruby)
15
+ 3. Explicit Data Dependencies
16
+
17
+ As you know, Ruby is a handy and powerful programming language.
18
+ We can use variables without definitions and re-assign them even if type mismatch.
19
+ Although it is very comfortable while you are writing, it would be painful for others.
20
+
21
+ CCP is a framework composed with above principles and a few debugging utils
22
+ that gives you(as writer) a little restrictions and gives you(as reader) a readability.
23
+
24
+
25
+ == Example
26
+ === usual ruby code
27
+
28
+ class SomeOperation
29
+ def execute
30
+ # fetching data
31
+ # calculating it
32
+ # print results
33
+ end
34
+ end
35
+
36
+ Later, it would be a more complex and longer code like this.
37
+
38
+ class SomeOperation
39
+ def execute
40
+ @data = fetch_data
41
+ ...
42
+ @result = calculate(@data)
43
+ ...
44
+ print_results(@result)
45
+ end
46
+
47
+ def fetching_data
48
+ # accessing instance variables, and long code here
49
+ ...
50
+
51
+ Let's imagine a situation that you need to replace above "fetch" code after several years.
52
+ It is too hard to see data dependencies especially about instance variables.
53
+
54
+ === with CCP
55
+
56
+ class SomeOperation
57
+ include Ccp::Commands::Composite
58
+
59
+ command FetchData
60
+ command Calculate
61
+ command PrintResult
62
+ end
63
+
64
+ class FetchData # 1. SRP
65
+ include Ccp::Commands::Core
66
+
67
+ # {pre,post} methods can be used like Design By Contract
68
+ def post
69
+ data.check(:fetched, {Symbol => [Float]}) # 2. Typed Variables
70
+ end
71
+
72
+ def execute
73
+ # fetching data...
74
+ data[:fetched] = ... # 3. Data Dependencies
75
+ end
76
+ end
77
+
78
+ class Calculate
79
+ ...
80
+
81
+
82
+ All sub commands like FetchData,Calculate,PrintResult are executed
83
+ in each scopes, and can share variables only via data object.
84
+
85
+ So you can easily refactor or replace FetchData unit
86
+ because there are no implicit instance variable dependencies
87
+ and futhermore all depencenies would be explicitly declared in "pre","post" method.
88
+
89
+ === execute
90
+
91
+ Just call a "execute" instance method.
92
+
93
+ cmd = SomeOperation.new
94
+ cmd.execute
95
+
96
+ === invokers
97
+
98
+ Invokers::Base can be used as a top level composite command.
99
+
100
+ class SomeOperation < Ccp::Invokers::Base
101
+ command FetchData
102
+ ...
103
+
104
+
105
+ Its "benchmark" method generates profile information.
106
+
107
+ ruby -r some_operation -e 'SomeOperation.new.benchmark'
108
+ [43.3%] 2.5834830 FetchData#execute
109
+ [35.9%] 2.0710440 Calculate#execute
110
+ ...
111
+
data/ccp.gemspec CHANGED
@@ -18,7 +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_dependency "typed", ">= 0.1.0"
21
+ s.add_dependency "typed", ">= 0.1.2"
22
22
  s.add_dependency "dsl_accessor", ">= 0.4.0"
23
23
 
24
24
  s.add_development_dependency "rspec"
data/lib/ccp.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "typed"
2
+ require "dsl_accessor"
2
3
  require "active_support/core_ext"
3
4
  require "ccp/version"
4
5
  require "ccp/data"
@@ -56,12 +56,6 @@ module Ccp
56
56
  ######################################################################
57
57
  ### Enumerable
58
58
 
59
- def <<(command)
60
- command = command.new if command.is_a?(Class) and command.ancestors.include?(Core)
61
- command.must(Core)
62
- commands << command
63
- end
64
-
65
59
  def commands
66
60
  @commands ||= build_commands.must(Array)
67
61
  end
@@ -70,19 +64,18 @@ module Ccp
70
64
  ### Commands
71
65
 
72
66
  def execute
73
- benchmark
67
+ commands.each(&:benchmark)
74
68
  end
75
69
 
76
- def benchmark
77
- pre if respond_to?(:pre)
78
- commands.each(&:benchmark)
79
- post if respond_to?(:post)
70
+ def receiver=(value)
71
+ super
72
+ commands.each{|c| c.receiver = value}
80
73
  end
81
74
 
82
75
  private
83
76
  def build_commands
84
77
  array = self.class.commands.select{|c| c.cond.nil? or instance_eval(&c.cond)}
85
- array.map{|c|
78
+ cmds = array.map{|c|
86
79
  c = c.klass.new(*c.args)
87
80
  c.receiver = receiver
88
81
  c
@@ -9,8 +9,8 @@ module Ccp
9
9
 
10
10
  ### Profiling
11
11
 
12
- def benchmark(method = :execute)
13
- receiver.profile(self, method)
12
+ def benchmark
13
+ receiver.profile(self, :execute)
14
14
  end
15
15
  end
16
16
  end
@@ -5,7 +5,7 @@ module Ccp
5
5
  ### Receiver Methods
6
6
 
7
7
  def receiver
8
- @receiver ||= Ccp::Receivers::None.new
8
+ @receiver ||= Ccp::Receivers::Base.new
9
9
  end
10
10
 
11
11
  def receiver=(value)
@@ -12,26 +12,49 @@ module Ccp
12
12
  DEFAULT_OPTIONS = {
13
13
  :profile => false,
14
14
  :comment => true,
15
+ :logger => Logger.new($stderr),
15
16
  }
16
17
 
18
+ ######################################################################
19
+ ### Class Methods
20
+
21
+ def self.execute(options = {}, &block)
22
+ cmd = new(options)
23
+ if block_given?
24
+ cmd.instance_eval(&block)
25
+ end
26
+ cmd.benchmark
27
+ return cmd
28
+ end
29
+
30
+ def self.benchmark(options = {}, &block)
31
+ execute({:profile => true}.merge(options), &block)
32
+ end
33
+
17
34
  ######################################################################
18
35
  ### Instance Methods
19
36
 
20
37
  def initialize(options = nil)
21
- self.receiver = self.class.receiver.new
22
- self.class.prepend_command Commands::RuntimeArgs, options
38
+ options ||= {}
39
+ set_default_receiver(options[:receiver])
23
40
  set_default_options
41
+ set_runtime_options(options)
42
+ end
43
+
44
+ def set_default_receiver(receiver)
45
+ self.receiver = receiver || self.class.receiver.new
24
46
  end
25
47
 
26
48
  def set_default_options
27
49
  self.class::DEFAULT_OPTIONS.each_pair do |key,val|
28
50
  data.default[key] = val
29
51
  end
30
- data.default(:logger) { Logger.new($stderr) }
31
52
  end
32
53
 
33
- def execute
34
- benchmark
54
+ def set_runtime_options(options)
55
+ options.each_pair do |key,val|
56
+ data[key] = val
57
+ end
35
58
  end
36
59
 
37
60
  def benchmark
data/lib/ccp/receivers.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Ccp
2
2
  module Receivers
3
3
  autoload :Base , 'ccp/receivers/base'
4
- autoload :None , 'ccp/receivers/none'
4
+ autoload :Global , 'ccp/receivers/global'
5
5
  autoload :Commentable , 'ccp/receivers/commentable'
6
6
  autoload :Profileable , 'ccp/receivers/profileable'
7
7
  end
@@ -0,0 +1,9 @@
1
+ module Ccp
2
+ module Receivers
3
+ class Global < Base
4
+ def self.new
5
+ @instance ||= super
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,6 +1,6 @@
1
1
  module Ccp
2
2
  module Receivers
3
- class None < Base
3
+ class Global < Base
4
4
  def self.new
5
5
  @instance ||= super
6
6
  end
@@ -16,12 +16,16 @@ module Ccp
16
16
 
17
17
  def profile(target, method)
18
18
  start = Time.new
19
- target.pre if target.must.duck?(:pre)
19
+ target.__send__(:pre) if target.respond_to?(:pre)
20
20
  target.__send__(method)
21
- target.post if target.must.duck?(:post)
22
- target.must.duck(:no_bench) {
21
+ target.__send__(:post) if target.respond_to?(:post)
22
+
23
+ case target
24
+ when Ccp::Commands::Composite
25
+ # no profiles
26
+ else
23
27
  profiles << Profile.new(target, method, (Time.new - start).to_f)
24
- }
28
+ end
25
29
  end
26
30
 
27
31
  def profiles
data/lib/ccp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ccp
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -0,0 +1,83 @@
1
+ require "spec_helper"
2
+
3
+ describe Ccp::Commands::Composite do
4
+ describe "#execute" do
5
+ it "should call its execute and sub commands's {pre,execute,post} in declared order" do
6
+ c = Program.new
7
+ c.data[:breadcrumbs] = []
8
+ c.execute
9
+ c.data[:breadcrumbs].should ==
10
+ ["Cmd1#pre", "Cmd1#execute", "Cmd1#post",
11
+ "Cmd2#pre", "Cmd2#execute", "Cmd2#post",
12
+ "Cmd3#pre", "Cmd3#execute", "Cmd3#post"]
13
+ end
14
+ end
15
+
16
+ describe "#benchmark" do
17
+ it "should call its and sub commands's {pre,execute,post} in declared order" do
18
+ c = Program.new
19
+ c.data[:breadcrumbs] = []
20
+ c.benchmark
21
+ c.data[:breadcrumbs].should ==
22
+ ["Program#pre",
23
+ "Cmd1#pre", "Cmd1#execute", "Cmd1#post",
24
+ "Cmd2#pre", "Cmd2#execute", "Cmd2#post",
25
+ "Cmd3#pre", "Cmd3#execute", "Cmd3#post",
26
+ "Program#post"]
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "Ccp::Commands::Composite(nested)" do
32
+ describe "#execute" do
33
+ it "should call its execute and sub commands's {pre,execute,post} in declared order" do
34
+ c = CompositeProgram.new
35
+ c.data[:breadcrumbs] = []
36
+ c.execute
37
+ c.data[:breadcrumbs].should ==
38
+ ["Cmd1#pre", "Cmd1#execute", "Cmd1#post",
39
+ "Cmd23#pre",
40
+ "Cmd23#execute:start",
41
+ "Cmd2#pre", "Cmd2#execute", "Cmd2#post",
42
+ "Cmd3#pre", "Cmd3#execute", "Cmd3#post",
43
+ "Cmd23#execute:end",
44
+ "Cmd23#post",
45
+ "Cmd4#pre", "Cmd4#execute", "Cmd4#post"]
46
+ end
47
+ end
48
+
49
+ describe "#benchmark" do
50
+ it "should call its and sub commands's {pre,execute,post} in declared order" do
51
+ c = CompositeProgram.new
52
+ c.data[:breadcrumbs] = []
53
+ c.benchmark
54
+ c.data[:breadcrumbs].should ==
55
+ ["CompositeProgram#pre",
56
+ "Cmd1#pre", "Cmd1#execute", "Cmd1#post",
57
+ "Cmd23#pre",
58
+ "Cmd23#execute:start",
59
+ "Cmd2#pre", "Cmd2#execute", "Cmd2#post",
60
+ "Cmd3#pre", "Cmd3#execute", "Cmd3#post",
61
+ "Cmd23#execute:end",
62
+ "Cmd23#post",
63
+ "Cmd4#pre", "Cmd4#execute", "Cmd4#post",
64
+ "CompositeProgram#post"]
65
+ end
66
+ end
67
+
68
+ it "should update receiver recursively" do
69
+ cmd = CompositeProgram.new
70
+ cmd.commands.each do |c|
71
+ c.receiver.should == cmd.receiver
72
+ end
73
+
74
+ new_receiver = Ccp::Receivers::Base.new
75
+ new_receiver.should_not == cmd.receiver
76
+
77
+ # update receiver
78
+ cmd.receiver = new_receiver
79
+ cmd.commands.each do |c|
80
+ c.receiver.should == cmd.receiver
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ describe Ccp::Commands::Core do
4
+ describe "(accessor)" do
5
+ subject { Object.new.extend Ccp::Commands::Core }
6
+
7
+ # data container
8
+ it { should respond_to(:data?) }
9
+ it { should respond_to(:data) }
10
+ its(:data) { should be_kind_of(Typed::Hash) }
11
+
12
+ # executable
13
+ it { should respond_to(:execute) }
14
+ it { should respond_to(:benchmark) }
15
+
16
+ # receivable
17
+ it { should respond_to(:receiver) }
18
+ its(:receiver) { should be_kind_of(Ccp::Receivers::Base) }
19
+ end
20
+
21
+ describe "#execute" do
22
+ it "should call only execute" do
23
+ cmd1 = Cmd1.new
24
+ cmd1.data[:breadcrumbs] = []
25
+ cmd1.execute
26
+ cmd1.data[:breadcrumbs].should == ["Cmd1#execute"]
27
+ end
28
+ end
29
+
30
+ describe "#benchmark" do
31
+ it "should call {pre,execute,post}" do
32
+ cmd1 = Cmd1.new
33
+ cmd1.data[:breadcrumbs] = []
34
+ cmd1.benchmark
35
+ cmd1.data[:breadcrumbs].should == ["Cmd1#pre", "Cmd1#execute", "Cmd1#post"]
36
+ end
37
+
38
+ it "should call receiver.profile" do
39
+ (receiver = Ccp::Receivers::Base.new).should_receive(:profile)
40
+
41
+ cmd1 = Cmd1.new
42
+ cmd1.receiver = receiver
43
+ cmd1.data[:breadcrumbs] = []
44
+ cmd1.benchmark
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,121 @@
1
+ require "spec_helper"
2
+
3
+ describe Ccp::Invokers::Base do
4
+ def no_logger; Logger.new('/dev/null'); end
5
+
6
+ describe "#execute" do
7
+ it "should call its execute and sub commands's {pre,execute,post} in declared order" do
8
+ c = CompositeInvoker.new
9
+ c.data[:breadcrumbs] = []
10
+ c.execute
11
+ c.data[:breadcrumbs].should ==
12
+ ["Cmd1#pre", "Cmd1#execute", "Cmd1#post",
13
+ "Cmd23#pre",
14
+ "Cmd23#execute:start",
15
+ "Cmd2#pre", "Cmd2#execute", "Cmd2#post",
16
+ "Cmd3#pre", "Cmd3#execute", "Cmd3#post",
17
+ "Cmd23#execute:end",
18
+ "Cmd23#post",
19
+ "Cmd4#pre", "Cmd4#execute", "Cmd4#post"]
20
+ end
21
+ end
22
+
23
+ describe "#benchmark" do
24
+ it "should call its and sub commands's {pre,execute,post} in declared order" do
25
+ c = CompositeInvoker.new
26
+ c.data[:breadcrumbs] = []
27
+ c.benchmark
28
+ c.data[:breadcrumbs].should ==
29
+ ["CompositeInvoker#pre",
30
+ "Cmd1#pre", "Cmd1#execute", "Cmd1#post",
31
+ "Cmd23#pre",
32
+ "Cmd23#execute:start",
33
+ "Cmd2#pre", "Cmd2#execute", "Cmd2#post",
34
+ "Cmd3#pre", "Cmd3#execute", "Cmd3#post",
35
+ "Cmd23#execute:end",
36
+ "Cmd23#post",
37
+ "Cmd4#pre", "Cmd4#execute", "Cmd4#post",
38
+ "CompositeInvoker#post"]
39
+ end
40
+ end
41
+
42
+ describe ".execute" do
43
+ it "should call its and sub commands's {pre,execute,post} in declared order" do
44
+ c = CompositeInvoker.execute(:breadcrumbs => [])
45
+ c.data[:breadcrumbs].should ==
46
+ ["CompositeInvoker#pre",
47
+ "Cmd1#pre", "Cmd1#execute", "Cmd1#post",
48
+ "Cmd23#pre",
49
+ "Cmd23#execute:start",
50
+ "Cmd2#pre", "Cmd2#execute", "Cmd2#post",
51
+ "Cmd3#pre", "Cmd3#execute", "Cmd3#post",
52
+ "Cmd23#execute:end",
53
+ "Cmd23#post",
54
+ "Cmd4#pre", "Cmd4#execute", "Cmd4#post",
55
+ "CompositeInvoker#post"]
56
+ end
57
+
58
+ it "should call only show_comments in default" do
59
+ r = Ccp::Receivers::Base.new
60
+ r.should_receive(:show_comments).once
61
+ r.should_receive(:show_profiles).never
62
+ CompositeInvoker.execute(:receiver => r, :breadcrumbs => [])
63
+ end
64
+
65
+ it "should call show_profiles if :profile option is given" do
66
+ r = Ccp::Receivers::Base.new
67
+ r.should_receive(:show_profiles).once
68
+ CompositeInvoker.execute(:receiver => r, :breadcrumbs => [], :profile => true)
69
+ end
70
+
71
+ it "should disable show_comments if :comment option is false" do
72
+ r = Ccp::Receivers::Base.new
73
+ r.should_receive(:show_comments).never
74
+ CompositeInvoker.execute(:receiver => r, :breadcrumbs => [], :comment => false)
75
+ end
76
+ end
77
+
78
+ describe ".benchmark" do
79
+ it "should call its and sub commands's {pre,execute,post} in declared order" do
80
+ r = Ccp::Receivers::Base.new
81
+ r.stub!(:show_comments) # disable output
82
+ r.stub!(:show_profiles) # disable output
83
+
84
+ c = CompositeInvoker.benchmark(:receiver => r, :breadcrumbs => [])
85
+ c.data[:breadcrumbs].should ==
86
+ ["CompositeInvoker#pre",
87
+ "Cmd1#pre", "Cmd1#execute", "Cmd1#post",
88
+ "Cmd23#pre",
89
+ "Cmd23#execute:start",
90
+ "Cmd2#pre", "Cmd2#execute", "Cmd2#post",
91
+ "Cmd3#pre", "Cmd3#execute", "Cmd3#post",
92
+ "Cmd23#execute:end",
93
+ "Cmd23#post",
94
+ "Cmd4#pre", "Cmd4#execute", "Cmd4#post",
95
+ "CompositeInvoker#post"]
96
+ end
97
+
98
+ it "should call only show_comments in default" do
99
+ r = Ccp::Receivers::Base.new
100
+ r.should_receive(:show_comments).once
101
+ r.should_receive(:show_profiles).once
102
+ CompositeInvoker.benchmark(:receiver => r, :breadcrumbs => [])
103
+ end
104
+
105
+ it "should disable show_profiles if :profile option is false" do
106
+ r = Ccp::Receivers::Base.new
107
+ r.should_receive(:show_comments).once
108
+ r.should_receive(:show_profiles).never
109
+ CompositeInvoker.benchmark(:receiver => r, :breadcrumbs => [], :profile => false)
110
+ end
111
+
112
+ it "should disable show_comments if :comment option is false" do
113
+ r = Ccp::Receivers::Base.new
114
+ r.should_receive(:show_comments).never
115
+ r.should_receive(:show_profiles).once
116
+ CompositeInvoker.benchmark(:receiver => r, :breadcrumbs => [], :comment => false)
117
+ end
118
+ end
119
+ end
120
+
121
+
data/spec/models.rb ADDED
@@ -0,0 +1,98 @@
1
+ module Breadcrumbing
2
+ def this
3
+ "%s#%s" % [self.class.name, caller[0].to_s.scan(/`(.*?)'/).first]
4
+ end
5
+ end
6
+
7
+ class Cmd1
8
+ include Ccp::Commands::Core
9
+ include Breadcrumbing
10
+
11
+ def pre
12
+ data[:breadcrumbs] << this
13
+ end
14
+
15
+ def execute
16
+ data[:breadcrumbs] << this
17
+ end
18
+
19
+ def post
20
+ data[:breadcrumbs] << this
21
+ end
22
+ end
23
+
24
+ class Cmd2 < Cmd1; end
25
+ class Cmd3 < Cmd1; end
26
+ class Cmd4 < Cmd1; end
27
+
28
+ class Program
29
+ include Ccp::Commands::Composite
30
+ include Breadcrumbing
31
+
32
+ command Cmd1
33
+ command Cmd2
34
+ command Cmd3
35
+
36
+ def pre
37
+ data[:breadcrumbs] << this
38
+ end
39
+
40
+ def post
41
+ data[:breadcrumbs] << this
42
+ end
43
+ end
44
+
45
+ class Cmd23
46
+ include Ccp::Commands::Composite
47
+ include Breadcrumbing
48
+
49
+ command Cmd2
50
+ command Cmd3
51
+
52
+ def pre
53
+ data[:breadcrumbs] << this
54
+ end
55
+
56
+ def execute
57
+ data[:breadcrumbs] << this + ":start"
58
+ super
59
+ data[:breadcrumbs] << this + ":end"
60
+ end
61
+
62
+ def post
63
+ data[:breadcrumbs] << this
64
+ end
65
+ end
66
+
67
+ class CompositeProgram
68
+ include Ccp::Commands::Composite
69
+ include Breadcrumbing
70
+
71
+ command Cmd1
72
+ command Cmd23
73
+ command Cmd4
74
+
75
+ def pre
76
+ data[:breadcrumbs] << this
77
+ end
78
+
79
+ def post
80
+ data[:breadcrumbs] << this
81
+ end
82
+ end
83
+
84
+ class CompositeInvoker < Ccp::Invokers::Base
85
+ include Breadcrumbing
86
+
87
+ command Cmd1
88
+ command Cmd23
89
+ command Cmd4
90
+
91
+ def pre
92
+ data[:breadcrumbs] << this
93
+ end
94
+
95
+ def post
96
+ data[:breadcrumbs] << this
97
+ end
98
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,3 +3,5 @@ $:.unshift File.expand_path('../../lib', __FILE__)
3
3
 
4
4
  require 'rspec'
5
5
  require 'ccp'
6
+
7
+ require File.join(File.dirname(__FILE__), "models")
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ccp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 29
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 2
10
- version: 0.1.2
9
+ - 3
10
+ version: 0.1.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - maiha
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-02-10 00:00:00 +09:00
18
+ date: 2012-02-14 00:00:00 +09:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -26,12 +26,12 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- hash: 27
29
+ hash: 31
30
30
  segments:
31
31
  - 0
32
32
  - 1
33
- - 0
34
- version: 0.1.0
33
+ - 2
34
+ version: 0.1.2
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
@@ -76,7 +76,7 @@ extra_rdoc_files: []
76
76
  files:
77
77
  - .gitignore
78
78
  - Gemfile
79
- - README
79
+ - README.rdoc
80
80
  - Rakefile
81
81
  - ccp.gemspec
82
82
  - lib/ccp.rb
@@ -89,19 +89,21 @@ files:
89
89
  - lib/ccp/commands/executable.rb
90
90
  - lib/ccp/commands/receivable.rb
91
91
  - lib/ccp/commands/resolvable.rb
92
- - lib/ccp/commands/runtime_args.rb
93
92
  - lib/ccp/data.rb
94
93
  - lib/ccp/invokers.rb
95
94
  - lib/ccp/invokers/base.rb
96
95
  - lib/ccp/receivers.rb
97
96
  - lib/ccp/receivers/base.rb
98
97
  - lib/ccp/receivers/commentable.rb
98
+ - lib/ccp/receivers/global.rb
99
99
  - lib/ccp/receivers/none.rb
100
100
  - lib/ccp/receivers/profileable.rb
101
101
  - lib/ccp/version.rb
102
- - spec/commands_spec.rb
103
- - spec/composite_spec.rb
102
+ - spec/commands_composite_spec.rb
103
+ - spec/commands_core_spec.rb
104
104
  - spec/data_spec.rb
105
+ - spec/invokers_spec.rb
106
+ - spec/models.rb
105
107
  - spec/spec_helper.rb
106
108
  has_rdoc: true
107
109
  homepage: http://github.com/maiha/ccp
data/README DELETED
File without changes
@@ -1,24 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # map options to data
3
-
4
- module Ccp
5
- module Commands
6
- class RuntimeArgs
7
- include Core
8
-
9
- def initialize(options = {})
10
- @options = (options || {}).must(Hash)
11
- end
12
-
13
- def execute
14
- @options.each_pair do |key, val|
15
- data[key] = val
16
- end
17
- end
18
-
19
- def inspect
20
- super.sub(/>$/, " #{@options.inspect}>")
21
- end
22
- end
23
- end
24
- end
@@ -1,18 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Ccp::Commands::Core do
4
- subject { Object.new.extend Ccp::Commands::Core }
5
-
6
- # data container
7
- it { should respond_to(:data?) }
8
- it { should respond_to(:data) }
9
- its(:data) { should be_kind_of(Typed::Hash) }
10
-
11
- # executable
12
- it { should respond_to(:execute) }
13
- it { should respond_to(:benchmark) }
14
-
15
- # receivable
16
- it { should respond_to(:receiver) }
17
- its(:receiver) { should be_kind_of(Ccp::Receivers::Base) }
18
- end
@@ -1,85 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Ccp::Commands::Composite do
4
- module Breadcrumbing
5
- BREADCRUMBS = []
6
-
7
- def this
8
- "%s#%s" % [self.class.name, caller[0].to_s.scan(/`(.*?)'/).first]
9
- end
10
-
11
- def breadcrumbs
12
- BREADCRUMBS
13
- end
14
- end
15
-
16
- class Cmd1
17
- include Ccp::Commands::Core
18
- include Breadcrumbing
19
-
20
- def execute
21
- breadcrumbs << this
22
- data[:foo] = []
23
- end
24
-
25
- def post
26
- breadcrumbs << this
27
- end
28
- end
29
-
30
- class Cmd2
31
- include Ccp::Commands::Core
32
- include Breadcrumbing
33
-
34
- def pre
35
- breadcrumbs << this
36
- end
37
-
38
- def execute
39
- breadcrumbs << this
40
- data[:foo] << "cmd2"
41
- end
42
-
43
- def post
44
- breadcrumbs << this
45
- end
46
- end
47
-
48
- class Cmd3
49
- include Ccp::Commands::Core
50
- include Breadcrumbing
51
-
52
- def pre
53
- breadcrumbs << this
54
- end
55
-
56
- def execute
57
- breadcrumbs << this
58
- data[:foo] << "cmd3"
59
- end
60
- end
61
-
62
- class Program
63
- include Ccp::Commands::Composite
64
-
65
- command Cmd1
66
- command Cmd2
67
- command Cmd3
68
- end
69
-
70
- subject { Program.new }
71
-
72
- it { should be_kind_of(Ccp::Commands::Core) }
73
-
74
- it "should call sub commands's {pre,execute,post} in declared order" do
75
- Breadcrumbing::BREADCRUMBS.clear
76
- subject.execute
77
- Breadcrumbing::BREADCRUMBS.should ==
78
- ["Cmd1#execute", "Cmd1#post", "Cmd2#pre", "Cmd2#execute", "Cmd2#post", "Cmd3#pre", "Cmd3#execute"]
79
- end
80
-
81
- it "should share same data storage in each sub commands" do
82
- subject.execute
83
- subject.data[:foo].should == ["cmd2", "cmd3"]
84
- end
85
- end