neo-dci 0.0.1

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.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-19mode
5
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in neo-dci.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Neo::DCI [![Build Status](https://secure.travis-ci.org/neopoly/neo-dci.png?branch=master)](http://travis-ci.org/neopoly/neo-dci)
2
+
3
+ Simple DCI
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'neo-dci'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install neo-dci
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ task :default => :test
5
+
6
+ require 'rake/testtask'
7
+ Rake::TestTask.new do |t|
8
+ t.libs << "test"
9
+ t.test_files = FileList['test/**/*_test.rb']
10
+ t.verbose = true
11
+ end
@@ -0,0 +1 @@
1
+ require "neo/dci"
@@ -0,0 +1,6 @@
1
+ require 'neo/dci/version'
2
+
3
+ require 'neo/dci/data'
4
+ require 'neo/dci/role'
5
+ require 'neo/dci/context_result'
6
+ require 'neo/dci/context'
@@ -0,0 +1,27 @@
1
+ module Neo
2
+ module DCI
3
+ class Context
4
+
5
+ class << self
6
+ private :new
7
+ end
8
+
9
+ def self.call(*args, &block)
10
+ context = new(*args, &block)
11
+ result = ContextResult.new
12
+ context.call(result)
13
+ raise UnprocessedError unless result.processed?
14
+ result
15
+ rescue NotImplementedError
16
+ raise
17
+ end
18
+
19
+
20
+ def call(result)
21
+ raise NotImplementedError
22
+ end
23
+
24
+ class UnprocessedError < StandardError; end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,43 @@
1
+ require 'ostruct'
2
+
3
+ module Neo
4
+ module DCI
5
+ class ContextResult
6
+ attr_reader :error, :data
7
+
8
+ def success!(data = {})
9
+ self.data = data
10
+ end
11
+
12
+ def failure!(error, data = {})
13
+ @error = error
14
+ self.data = data
15
+ end
16
+
17
+ def data= (data)
18
+ raise ArgumentError, "Data is already set. Call success! or failure! only once." if @data
19
+ @data = Data.new(data)
20
+ @data.freeze
21
+ end
22
+ private :data=
23
+
24
+ def success?
25
+ processed? && !error
26
+ end
27
+
28
+ def failure?
29
+ processed? && !!error
30
+ end
31
+
32
+ def processed?
33
+ !!@data
34
+ end
35
+
36
+ class Data < OpenStruct
37
+ def to_hash
38
+ @table
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,16 @@
1
+ module Neo
2
+ module DCI
3
+ module Data
4
+ # Enhances an object with the Role +role+.
5
+ def role_as(role, *params)
6
+ if role.assignable_to?(self, *params)
7
+ extend role
8
+ role.role_assigned(self, *params)
9
+ self
10
+ else
11
+ raise Neo::DCI::Role::NotAssignable.new role, self, params
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,58 @@
1
+ # A Role gives an object (e.g. an User) specific behaviour (or methods).
2
+ #
3
+ # == Example
4
+ #
5
+ # module TeamMember
6
+ # extend Neo::DCI::Role
7
+ #
8
+ # def self.assignable_to?(user, team)
9
+ # team.member?(user)
10
+ # end
11
+ #
12
+ # def leave_team!(team)
13
+ # # ...
14
+ # end
15
+ # end
16
+ #
17
+ # class User
18
+ # include Neo::DCI::Data
19
+ # end
20
+ #
21
+ # team_member = team.members.first
22
+ # team_member.role_as TeamMember
23
+ # team_member.leave_team!(team)
24
+ #
25
+ # non_member = User.find(1)
26
+ # non_member.role_as TeamMember # => raises Role::NotAssignable
27
+ #
28
+ module Neo
29
+ module DCI
30
+ module Role
31
+ # Decides if the role is assignable to +object+.
32
+ #
33
+ # The decision can determined by +object+ and +params+.
34
+ #
35
+ # Returns +true+ by default so every +object+ can have that role.
36
+ def assignable_to?(object, *params)
37
+ true
38
+ end
39
+
40
+ # Hook after a role has been assigned.
41
+ #
42
+ # Useful for extend the role with other roles.
43
+ def role_assigned(object, *params)
44
+ end
45
+
46
+ class NotAssignable < StandardError
47
+ attr_reader :role, :object, :params
48
+
49
+ def initialize(role, object, params)
50
+ super "Role #{role} not assignable to #{object} with params #{params.inspect}"
51
+ @role = role
52
+ @object = object
53
+ @params = params
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,5 @@
1
+ module Neo
2
+ module DCI
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/neo/dci/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Peter Suschlik"]
6
+ gem.email = ["ps@neopoly.de"]
7
+ gem.description = %q{Simple DCI}
8
+ gem.summary = %q{Includes Data, Roles and Context.}
9
+ gem.homepage = "https://github.com/neopoly/neo-dci"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "neo-dci"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Neo::DCI::VERSION
17
+
18
+ gem.add_development_dependency "rake"
19
+ gem.add_development_dependency "minitest"
20
+ gem.add_development_dependency "simple_assertions"
21
+ end
@@ -0,0 +1,68 @@
1
+ require 'helper'
2
+
3
+ class ContextResultTest < NeoDCICase
4
+ let(:result) { Neo::DCI::ContextResult.new }
5
+ let(:error) { RuntimeError.new }
6
+ let(:data) { {:foo => :bar} }
7
+
8
+ test "returns success? when no error present" do
9
+ result.success!
10
+ assert result.success?
11
+ assert result.processed?
12
+ refute result.failure?
13
+ assert_nil result.error
14
+ end
15
+
16
+ test "returns failure? on error" do
17
+ result.failure!(error)
18
+ refute result.success?
19
+ assert result.failure?
20
+ assert result.processed?
21
+ assert_same error, result.error
22
+ end
23
+
24
+ test "returns not processed? on default" do
25
+ refute result.processed?
26
+ refute result.success?
27
+ refute result.failure?
28
+ end
29
+
30
+ test "returns data as payload on success" do
31
+ result.success!(data)
32
+ assert_equal data[:foo], result.data.foo
33
+ end
34
+
35
+ test "returns data as payload on failure" do
36
+ result.failure!(error, data)
37
+ assert_equal data[:foo], result.data.foo
38
+ end
39
+
40
+ context "frozen data" do
41
+ test "after success!" do
42
+ result.success!
43
+ assert result.data.frozen?
44
+ end
45
+ test "after failure!" do
46
+ result.failure!(error)
47
+ assert result.data.frozen?
48
+ end
49
+ end
50
+
51
+ context "can only be called once" do
52
+ before do
53
+ result.success!
54
+ end
55
+
56
+ test "with success!" do
57
+ assert_raises ArgumentError, :message => /once/ do
58
+ result.success!
59
+ end
60
+ end
61
+
62
+ test "with failure!" do
63
+ assert_raises ArgumentError, :message => /once/ do
64
+ result.failure!(error)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,56 @@
1
+ require 'helper'
2
+
3
+ class ContextTest < NeoDCICase
4
+ class DummyContext < Neo::DCI::Context
5
+ def initialize(&block)
6
+ @block = block
7
+ end
8
+
9
+ def call(result)
10
+ @block.call(result)
11
+ end
12
+ end
13
+
14
+ let(:data) { {:foo => :bar } }
15
+ let(:error) { RuntimeError.new }
16
+
17
+ test "initialize is private" do
18
+ assert_raises NoMethodError do
19
+ DummyContext.new
20
+ end
21
+ end
22
+
23
+ test "raises not implement error" do
24
+ assert_raises NotImplementedError do
25
+ Class.new(Neo::DCI::Context).call
26
+ end
27
+ end
28
+
29
+ test "raises unprocessed error if result is not processed" do
30
+ assert_raises Neo::DCI::Context::UnprocessedError do
31
+ Class.new(Neo::DCI::Context) do
32
+ def call(result); end
33
+ end.call
34
+ end
35
+ end
36
+
37
+ test "returns context result if success" do
38
+ result = DummyContext.call do |result|
39
+ result.success!(data)
40
+ end
41
+ assert result.success?
42
+ refute result.failure?
43
+ assert_equal :bar, result.data.foo
44
+ end
45
+
46
+ test "returns context result if failure" do
47
+ result = DummyContext.call do |result|
48
+ result.failure!(error, data)
49
+ end
50
+ assert result.failure?
51
+ refute result.success?
52
+ assert_same error, result.error
53
+ assert_equal :bar, result.data.foo
54
+ end
55
+
56
+ end
@@ -0,0 +1,13 @@
1
+ require 'minitest/autorun'
2
+ require 'simple_assertions'
3
+
4
+ require 'neo/dci'
5
+
6
+ class NeoDCICase < MiniTest::Spec
7
+ include SimpleAssertions::AssertRaises
8
+
9
+ class << self
10
+ alias :context :describe
11
+ alias :test :it
12
+ end
13
+ end
@@ -0,0 +1,82 @@
1
+ require 'helper'
2
+
3
+ class RoleTest < NeoDCICase
4
+ module Human
5
+ extend Neo::DCI::Role
6
+
7
+ def live!
8
+ :live
9
+ end
10
+ end
11
+
12
+ module CryBaby
13
+ extend Neo::DCI::Role
14
+ include Human
15
+
16
+ def self.assignable_to?(user, emo=false)
17
+ emo || user.gender == :female
18
+ end
19
+
20
+ def cry!
21
+ :me_a_river
22
+ end
23
+ end
24
+
25
+ module EmoCore
26
+ extend Neo::DCI::Role
27
+
28
+ def self.role_assigned(user, *args)
29
+ user.role_as(CryBaby, *args)
30
+ end
31
+
32
+ def growl!
33
+ :breee
34
+ end
35
+ end
36
+
37
+ User = Struct.new(:gender) do
38
+ include Neo::DCI::Data
39
+ end
40
+
41
+ let(:male) { User.new(:male) }
42
+ let(:emo) { User.new(:male) }
43
+ let(:female) { User.new(:female) }
44
+
45
+ context :usage do
46
+ test "all humans can live" do
47
+ male.role_as Human
48
+ female.role_as Human
49
+ assert_equal :live, male.live!
50
+ assert_equal :live, female.live!
51
+ end
52
+
53
+ test "female can cry!" do
54
+ female.role_as CryBaby
55
+ assert_equal :me_a_river, female.cry!
56
+ end
57
+
58
+ test "emo can cry!" do
59
+ emo.role_as CryBaby, true
60
+ assert_equal :me_a_river, emo.cry!
61
+ end
62
+
63
+ test "boys don't cry!" do
64
+ assert_raises Neo::DCI::Role::NotAssignable, :role => CryBaby, :object => male do
65
+ male.role_as CryBaby
66
+ end
67
+ end
68
+
69
+ test "emo cores can cry! and growl!" do
70
+ emo.role_as EmoCore, true
71
+ assert_equal :me_a_river, emo.cry!
72
+ assert_equal :breee, emo.growl!
73
+ end
74
+ end
75
+
76
+ context :role_as do
77
+ test "returns object itself" do
78
+ actual = female.role_as CryBaby
79
+ assert_same female, actual
80
+ end
81
+ end
82
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: neo-dci
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Peter Suschlik
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: minitest
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: simple_assertions
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Simple DCI
63
+ email:
64
+ - ps@neopoly.de
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .travis.yml
71
+ - Gemfile
72
+ - LICENSE
73
+ - README.md
74
+ - Rakefile
75
+ - lib/neo-dci.rb
76
+ - lib/neo/dci.rb
77
+ - lib/neo/dci/context.rb
78
+ - lib/neo/dci/context_result.rb
79
+ - lib/neo/dci/data.rb
80
+ - lib/neo/dci/role.rb
81
+ - lib/neo/dci/version.rb
82
+ - neo-dci.gemspec
83
+ - test/context_result_test.rb
84
+ - test/context_test.rb
85
+ - test/helper.rb
86
+ - test/role_test.rb
87
+ homepage: https://github.com/neopoly/neo-dci
88
+ licenses: []
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 1.8.24
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Includes Data, Roles and Context.
111
+ test_files:
112
+ - test/context_result_test.rb
113
+ - test/context_test.rb
114
+ - test/helper.rb
115
+ - test/role_test.rb