surrounded 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f382683688ed856434a815e352dcc47f4acba5bc
4
- data.tar.gz: c4701d73fe34507e5f4d57c06166c76a9f17d151
3
+ metadata.gz: 8a0524827a23eeb3aa9829988d8d5bc7773e81ca
4
+ data.tar.gz: ad49086b9e50454fbfb31c143d5428d52d46c0f9
5
5
  SHA512:
6
- metadata.gz: eff04f84a73c9f73b933e5e30491524d6641bc42e7e16a84a33245a4cc4ab5b2f916ae0e545ca3669134e0e97041701811380988c9fca34ec27a8e07a9a6c804
7
- data.tar.gz: 29dcf1aa2d0705efd2111b83f940ea6d67818966d0fc52c51392ab096783ee300ad0476e9ad19d3e1fe0f415d3a4fc2024b0d5e9e02287e50ccba89fd8ffd65d
6
+ metadata.gz: d84eaf1f7907b2b6c6a80e585721104916142f47fb79b4d5ccee6abdd6516868b7c08463234a38ea0d5f713914c11facef87abff0434ff3b9dc140e03da22100
7
+ data.tar.gz: eeb0bd64cf19f0d7e8ecd17df70d77f2ecc4e193ec95f952f95fda2f504e1fd8182beb92c953e6a4ab0e64475795b38f6c253bab820a705bb61901131d38db10
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ group :test do
5
5
  gem "simplecov"
6
6
  gem 'coveralls', :require => false
7
7
  gem 'casting'
8
+ gem 'rubinius-coverage', :platform => :rbx
8
9
  end
9
10
 
10
11
  platforms :rbx do
data/README.md CHANGED
@@ -14,7 +14,7 @@ The purpose of this library is to clear away the details of getting things setup
14
14
  There are two main parts to this library.
15
15
 
16
16
  1. `Surrounded` gives objects an implicit awareness of other objects in their environments.
17
- 2. `Surrounded::Context` helps you create objects which encapsulate other objects. These *are* the environments.
17
+ 2. `Surrounded::Context` helps you create objects which encapsulate other objects **and** their behavior. These *are* the environments.
18
18
 
19
19
  First, take a look at creating contexts. This is where you'll spend most of your time.
20
20
 
@@ -307,7 +307,24 @@ Alternatively, if you just want to define your own methods without the DSL using
307
307
 
308
308
  In fact, that's exactly what happens with the `disallow` keyword. After using it here, we'd have a `disallow_shove_it?` method defined.
309
309
 
310
- If you call the disallowed trigger directly, you'll raise a `Surrounded::Context::AccessError` exception and the code in your trigger will not be run.
310
+ If you call the disallowed trigger directly, you'll raise a `MyEnvironment::AccessError` exception and the code in your trigger will not be run. You may rescue from that or you may rescue from `Surrounded::Context::AccessError` although you should prefer to use the error name from your own class.
311
+
312
+ ## Restricting return values
313
+
314
+ _Tell, Don't Ask_ style programming can better be enforced by following East-oriented Code principles. This means that the returns values from methods on your objects should not provide information about their internal state. Instead of returning values, you can enforce that triggers return the context object. This forces you to place context responsiblities inside the context and prevents leaking the details and responsiblities outside of the system.
315
+
316
+ Here's how you enforce it:
317
+
318
+ ```ruby
319
+ class MyEnvironment
320
+ extend Surrounded::Context
321
+ east_oriented_triggers
322
+ end
323
+ ```
324
+
325
+ That's it.
326
+
327
+ With that change, any trigger you define will execute the block you provide and return `self`, being the instance of the context.
311
328
 
312
329
  ## Where roles exist
313
330
 
@@ -472,15 +489,9 @@ class ActiviatingAccount
472
489
  # pass an array of arrays with role name symbol and the object for that role
473
490
  map_roles([[:activator, activator],[:account, account]])
474
491
  end
475
-
476
- # if you want to stick with the `initialize` shortcut you can define these methods
477
- # for special initialization behavior.
478
- def preinitialize
479
- # to happen before any role mapping
480
- end
481
- def postinitialize
482
- # to happen after any role mapping
483
- end
492
+ # these also must be done if you create your own initialize method.
493
+ # this is a shortcut for using attr_reader and private
494
+ private_attr_reader :activator, :account
484
495
 
485
496
  role :activator do # module by default
486
497
  def some_behavior; end
@@ -549,6 +560,10 @@ class ActiviatingAccount
549
560
  instance.some_trigger_method
550
561
  end
551
562
 
563
+ # Set triggers to always return the context object
564
+ # so you can enforce East-oriented style or Tell, Don't Ask
565
+ east_oriented_triggers
566
+
552
567
  end
553
568
  ```
554
569
 
@@ -2,6 +2,9 @@ module Surrounded
2
2
  module AccessControl
3
3
  def self.extended(base)
4
4
  base.send(:include, AccessMethods)
5
+ unless defined?(base::AccessError)
6
+ base.const_set(:AccessError, Class.new(::Surrounded::Context::AccessError))
7
+ end
5
8
  end
6
9
 
7
10
  private
@@ -20,10 +23,10 @@ module Surrounded
20
23
 
21
24
  method_restrictor = "disallow_#{name}?"
22
25
  if self.respond_to?(method_restrictor, true) && self.send(method_restrictor)
23
- raise ::Surrounded::Context::AccessError.new("access to #{self.name}##{name} is not allowed")
26
+ raise ::#{self.to_s}::AccessError.new("access to #{self.name}##{name} is not allowed")
24
27
  end
25
28
 
26
- self.send("__trigger_#{name}")
29
+ #{trigger_return_content(name)}
27
30
 
28
31
  ensure
29
32
  remove_roles if __apply_role_policy == :trigger
@@ -2,6 +2,7 @@ require 'set'
2
2
  require 'surrounded/context/role_map'
3
3
  require 'surrounded/access_control'
4
4
  require 'surrounded/shortcuts'
5
+ require 'surrounded/east_oriented'
5
6
 
6
7
  # Some features are only available in versions of Ruby
7
8
  # where this method is true
@@ -62,7 +63,10 @@ module Surrounded
62
63
  def protect_triggers; self.extend(::Surrounded::AccessControl); end
63
64
 
64
65
  # Automatically create class methods for each trigger method.
65
- def shortcut_triggers; self.extend(::Surrounded::Shortcuts); end
66
+ def shortcut_triggers; self.extend(::Surrounded::Shortcuts); end
67
+
68
+ # Automatically return the context object from trigger methods.
69
+ def east_oriented_triggers; self.extend(::Surrounded::EastOriented); end
66
70
 
67
71
  def default_role_type
68
72
  @default_role_type ||= Surrounded::Context.default_role_type
@@ -192,7 +196,7 @@ module Surrounded
192
196
  begin
193
197
  apply_roles if __apply_role_policy == :trigger
194
198
 
195
- self.send("__trigger_#{name}")
199
+ #{trigger_return_content(name)}
196
200
 
197
201
  ensure
198
202
  remove_roles if __apply_role_policy == :trigger
@@ -201,6 +205,10 @@ module Surrounded
201
205
  }, __FILE__, __LINE__
202
206
  end
203
207
 
208
+ def trigger_return_content(name)
209
+ %{self.send("__trigger_#{name}")}
210
+ end
211
+
204
212
  # === Utility shortcuts
205
213
 
206
214
  # Set a named constant and make it private
@@ -0,0 +1,13 @@
1
+ module Surrounded
2
+ module EastOriented
3
+ # Always return the context object to ensure that a context may
4
+ # not be asked for information.
5
+ def trigger_return_content(name)
6
+ %{
7
+ self.send("__trigger_#{name}")
8
+
9
+ self
10
+ }
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module Surrounded
2
- VERSION = "0.8.1"
2
+ VERSION = "0.8.2"
3
3
  end
@@ -45,13 +45,22 @@ describe Surrounded::Context, 'access control' do
45
45
  refute context.triggers.include?(:if_ready)
46
46
  end
47
47
 
48
- it 'raises errors when trigger method not allowed' do
49
- error = assert_raises(::Surrounded::Context::AccessError){
48
+ it 'raises error specific to the context class when trigger method not allowed' do
49
+ error = assert_raises(::FilteredContext::AccessError){
50
50
  context.if_ready
51
51
  }
52
52
  assert_match(/access to FilteredContext#if_ready is not allowed/i, error.message)
53
53
  end
54
54
 
55
+ it 'supports rescuing from Surrounded defined error when trigger method not allowed' do
56
+ begin
57
+ context.if_ready
58
+ rescue ::Surrounded::Context::AccessError => error
59
+ assert "rescued!"
60
+ end
61
+ assert_match(/access to FilteredContext#if_ready is not allowed/i, error.message)
62
+ end
63
+
55
64
  it 'applies roles in disallow blocks' do
56
65
  assert_equal 'special user method', context.disallow_check_disallow_behavior?
57
66
  end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ class EastTestContext
4
+ extend Surrounded::Context
5
+ east_oriented_triggers
6
+
7
+ initialize :user, :other_user
8
+
9
+ trigger :ask? do
10
+ "asking a question..."
11
+ end
12
+ end
13
+
14
+ describe Surrounded::Context, '.east_oriented_triggers' do
15
+ let(:user){ User.new("Jim") }
16
+ let(:other_user){ User.new("Guille") }
17
+ let(:context){ EastTestContext.new(user, other_user) }
18
+
19
+ it 'returns the context object from trigger methods' do
20
+ assert_equal context, context.ask?
21
+ end
22
+ end
23
+
24
+ describe Surrounded::Context, '.east_oriented_triggers with protect_triggers' do
25
+ let(:user){ User.new("Jim") }
26
+ let(:other_user){ User.new("Guille") }
27
+ let(:context){
28
+ ctxt = EastTestContext.new(user, other_user)
29
+ ctxt.singleton_class.send(:protect_triggers)
30
+ ctxt
31
+ }
32
+
33
+ it 'returns the context object from trigger methods' do
34
+ assert_equal context, context.ask?
35
+ end
36
+ end
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surrounded
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
- - "'Jim Gay'"
8
- autorequire:
7
+ - '''Jim Gay'''
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-29 00:00:00.000000000 Z
11
+ date: 2014-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: triad
15
- requirement: !ruby/object:Gem::Requirement
15
+ version_requirements: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.1.2
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
20
+ requirement: !ruby/object:Gem::Requirement
23
21
  requirements:
24
- - - "~>"
22
+ - - ~>
25
23
  - !ruby/object:Gem::Version
26
24
  version: 0.1.2
25
+ prerelease: false
26
+ type: :runtime
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
- requirement: !ruby/object:Gem::Requirement
29
+ version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.3'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
34
+ requirement: !ruby/object:Gem::Requirement
37
35
  requirements:
38
- - - "~>"
36
+ - - ~>
39
37
  - !ruby/object:Gem::Version
40
38
  version: '1.3'
39
+ prerelease: false
40
+ type: :development
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
- requirement: !ruby/object:Gem::Requirement
43
+ version_requirements: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
51
49
  requirements:
52
- - - ">="
50
+ - - '>='
53
51
  - !ruby/object:Gem::Version
54
52
  version: '0'
53
+ prerelease: false
54
+ type: :development
55
55
  description: Gives an object implicit access to other objects in it's environment.
56
56
  email:
57
57
  - jim@saturnflyer.com
@@ -59,9 +59,9 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
- - ".gitignore"
63
- - ".simplecov"
64
- - ".travis.yml"
62
+ - .gitignore
63
+ - .simplecov
64
+ - .travis.yml
65
65
  - Gemfile
66
66
  - LICENSE.txt
67
67
  - README.md
@@ -73,11 +73,13 @@ files:
73
73
  - lib/surrounded/context/negotiator.rb
74
74
  - lib/surrounded/context/role_map.rb
75
75
  - lib/surrounded/context_errors.rb
76
+ - lib/surrounded/east_oriented.rb
76
77
  - lib/surrounded/shortcuts.rb
77
78
  - lib/surrounded/version.rb
78
79
  - surrounded.gemspec
79
80
  - test/context_access_test.rb
80
81
  - test/context_shortcuts_test.rb
82
+ - test/east_oriented_triggers_test.rb
81
83
  - test/example_proxy_test.rb
82
84
  - test/example_threaded_test.rb
83
85
  - test/example_wrapper_test.rb
@@ -89,29 +91,30 @@ homepage: http://github.com/saturnflyer/surrounded
89
91
  licenses:
90
92
  - MIT
91
93
  metadata: {}
92
- post_install_message:
94
+ post_install_message:
93
95
  rdoc_options: []
94
96
  require_paths:
95
97
  - lib
96
98
  required_ruby_version: !ruby/object:Gem::Requirement
97
99
  requirements:
98
- - - ">="
100
+ - - '>='
99
101
  - !ruby/object:Gem::Version
100
102
  version: '0'
101
103
  required_rubygems_version: !ruby/object:Gem::Requirement
102
104
  requirements:
103
- - - ">="
105
+ - - '>='
104
106
  - !ruby/object:Gem::Version
105
107
  version: '0'
106
108
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.2.0
109
- signing_key:
109
+ rubyforge_project:
110
+ rubygems_version: 2.1.9
111
+ signing_key:
110
112
  specification_version: 4
111
113
  summary: Create encapsulated environments for your objects.
112
114
  test_files:
113
115
  - test/context_access_test.rb
114
116
  - test/context_shortcuts_test.rb
117
+ - test/east_oriented_triggers_test.rb
115
118
  - test/example_proxy_test.rb
116
119
  - test/example_threaded_test.rb
117
120
  - test/example_wrapper_test.rb