casting 0.7.1 → 0.7.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: b2c87cd8917d7140a16d55d487f4f0999ee44824
4
- data.tar.gz: 2ffb23af2a79836b0705efe5aa8ac00df0144881
3
+ metadata.gz: c87234df3ca2237a6d2e9d0d6de0f4beb8808cae
4
+ data.tar.gz: 114ccf9e9984a2323288b66982465ef7068a4dd0
5
5
  SHA512:
6
- metadata.gz: 82e5c33d84c41df11ead6966456bd8b42d0f665c0ba50345ba9b5fa3241dd4b42eaf74a9cd6c08b6212007b7ca1d009f8fe4a6c41a76a1a81ace87e2800be759
7
- data.tar.gz: 502e4254feb758ddff742e3296eed05282b7690d5dda8ab530475da871603db0f3926a31150edcc4140120035ac1f06e059c000b8dbff4eda9337fa81a132bea
6
+ metadata.gz: cc11494446dad4f1b1cd367d9fbd485ad78cf961884348344d076ff9456e1e8235af7be0d8547c1db84c0f953d79428da99d1a649702aa61d7b397d00b776fb9
7
+ data.tar.gz: e3d49bea1aaa35a9c08220cd3c07407fcf34657cdd02934ea2f9bd37adb999e3130e37690eebd21b44c884e5a542381b135f207eaaffe3919583877bee70fee4
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/saturnflyer/casting.png?branch=master)](https://travis-ci.org/saturnflyer/casting)
4
4
  [![Code Climate](https://codeclimate.com/github/saturnflyer/casting.png)](https://codeclimate.com/github/saturnflyer/casting)
5
- [![Coverage Status](https://coveralls.io/repos/saturnflyer/casting/badge.png)](https://coveralls.io/r/saturnflyer/casting)
5
+ [![Test Coverage](https://codeclimate.com/github/saturnflyer/casting/badges/coverage.svg)](https://codeclimate.com/github/saturnflyer/casting/coverage)
6
6
  [![Gem Version](https://badge.fury.io/rb/casting.png)](http://badge.fury.io/rb/casting)
7
7
 
8
8
  ## Add behavior to your objects without using extend
@@ -18,7 +18,7 @@ Here's a quick example that you might try in a Rails project:
18
18
  # implement a module that contains information for the request response
19
19
  # and apply it to an object in your system.
20
20
  def show
21
- respond_with user.cast_as(UserRepresenter)
21
+ @user = user.cast_as(UserRepresenter)
22
22
  end
23
23
  ```
24
24
 
@@ -293,22 +293,14 @@ Person.instance_method(:hello) #=> #<UnboundMethod: Person#hello>
293
293
  But if you attempt to use that `UnboundMethod` on an object that is not a `Person` you'll get
294
294
  an error about a type mismatch.
295
295
 
296
- Casting will bind an unbound method to a client object and execute the method as though it is
296
+ Casting will bind an UnboundMethod method to a client object and execute the method as though it is
297
297
  defined on the client object. Any reference to `self` from the method block will refer to the
298
298
  client object.
299
299
 
300
- This behavior is different in Ruby 1.9 vs. 2.x.
301
-
302
- According to [http://rubyspec.org](http://rubyspec.org) the behavior in MRI in 1.9 that allows this to happen is incorrect. In MRI (and JRuby) 1.9 you may unbind methods from an object that has been extended with a module, and bind them to another object of the same type that has *not* been extended with that module.
303
-
304
- Casting uses this as a way to trick the interpreter into using the method where we want it and avoid forever extending the object of concern.
305
-
306
- This changed in Ruby 2.0 and does not work. What does work (and is so much better) in 2.0 is that you may take any method from a module and apply it to any object. This means that Casting doesn't have to perform any tricks to temporarily apply behavior to an object.
307
-
308
- For example, this fails in 1.9, but works in 2.0:
300
+ Rather than define methods on classes, you may take any method from a module and apply it to any object regardless of its class.
309
301
 
310
302
  ```ruby
311
- GreetingModule.instance_method(:hello_world).bind(actor).call
303
+ GreetingModule.instance_method(:hello).bind(actor).call
312
304
  ```
313
305
 
314
306
  Casting provides a convenience for doing this.
@@ -350,12 +342,6 @@ If you are using Bundler, add this line to your application's Gemfile:
350
342
  gem 'casting'
351
343
  ```
352
344
 
353
- If you're using Ruby 1.9, be sure to use a version lower than 0.7
354
-
355
- ```ruby
356
- gem 'casting', '~> 0.6.9'
357
- ```
358
-
359
345
  And then execute:
360
346
 
361
347
  $ bundle
@@ -0,0 +1,125 @@
1
+ # This is an experimental implementation of allowing contextual use of behaviors.
2
+ #
3
+ # This relies on versions of Ruby supporting refinements.
4
+ #
5
+ # You *must* include the following module and use it for refinements, and
6
+ # you *must* set the current context for the thread:
7
+ #
8
+ # class SomeContext
9
+ # using Casting::Context
10
+ # include Casting::Context
11
+ #
12
+ # initialize(:some, :thing)
13
+ # # doing that defines your constructor but would cause it too look for
14
+ # # modules named Some and Thing
15
+ # module Some; end
16
+ # module Thing; end
17
+ #
18
+ # # if you want different module names (why would you?) then you'd need
19
+ # # to do all this:
20
+ # def initialize(some, thing)
21
+ # @assignments = []
22
+ # assign [some, SomeRole], [thing, OtherRole]
23
+ # Thread.current[:context] = self
24
+ # end
25
+ # attr_reader :some, :thing, :assignments
26
+ #
27
+ # module SomeRole; end
28
+ # module OtherRole; end
29
+ # end
30
+ #
31
+ # In order to use this the objects sent into the context contstructor *must*
32
+ # `include Casting::Client` so that the `cast` method is available to them
33
+ #
34
+ module Casting
35
+ module Context
36
+
37
+ def self.extended(base)
38
+ base.send(:include, InstanceMethods)
39
+ end
40
+
41
+ def initialize(*setup_args)
42
+ attr_reader(*setup_args)
43
+ private(*setup_args)
44
+
45
+ mod = Module.new
46
+ line = __LINE__; string = %<
47
+ def initialize(#{setup_args.map{|name| "#{name}:" }.join(',')})
48
+ @assignments = []
49
+ #{setup_args.map do |name|
50
+ ["assign(",name,", '",name,"')"].join
51
+ end.join("\n")}
52
+ Thread.current[:context] = self
53
+ end
54
+ attr_reader :assignments
55
+ >
56
+ mod.class_eval string, __FILE__, line
57
+ const_set('Initializer', mod)
58
+ include mod
59
+ end
60
+
61
+ module InstanceMethods
62
+ def context
63
+ self
64
+ end
65
+
66
+ # Keep track of objects and their behaviors
67
+ def assign(object, role_name)
68
+ instance_variable_set("@#{role_name}", object)
69
+ self.assignments << [object, self.role_for(role_name)]
70
+ end
71
+
72
+ def contains?(obj)
73
+ assignments.map(&:first).include?(obj)
74
+ end
75
+
76
+ # Execute the behavior from the role on the specifed object
77
+ def dispatch(object, method_name, *args, &block)
78
+ object.cast(method_name, context.role_implementing(object, method_name), *args, &block)
79
+ end
80
+
81
+ # Find the first assigned role which implements a response for the given method name
82
+ def role_implementing(object, method_name)
83
+ assigned_roles(object).find{|role| role.method_defined?(method_name) } || raise(NoMethodError, "unknown method '#{method_name}' expected for #{object}")
84
+ end
85
+
86
+ # Get the roles for the given object
87
+ def assigned_roles(object)
88
+ assignments.select{|pair|
89
+ pair.first == object
90
+ }.map(&:last)
91
+ end
92
+
93
+ # Get the behavior module for the named role.
94
+ # This role constant for special_person is SpecialPerson.
95
+ def role_for(name)
96
+ role_name = name.to_s.gsub(/(?:^|_)([a-z])/) { $1.upcase }
97
+ self.class.const_get(role_name)
98
+ rescue NameError
99
+ Module
100
+ end
101
+ end
102
+
103
+ refine Object do
104
+ def context
105
+ Thread.current[:context]
106
+ end
107
+
108
+ def context=(obj)
109
+ Thread.current[:context] = obj
110
+ end
111
+
112
+ # Get the object playing a particular role
113
+ def role(role_name)
114
+ context.send(role_name)
115
+ end
116
+
117
+ # Execute the named method on the object plaing the name role
118
+ def tell(role_name, method_name, *args, &block)
119
+ if context == self || context.contains?(self)
120
+ context.dispatch(role(role_name), method_name, *args, &block)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -7,7 +7,7 @@ module Casting
7
7
  private :prepared_delegation
8
8
 
9
9
  def initialize(delegated_method_name, client)
10
- @prepared_delegation = PreparedDelegation.new(:delegated_method_name => delegated_method_name, :client => client)
10
+ @prepared_delegation = PreparedDelegation.new(delegated_method_name: delegated_method_name, client: client)
11
11
  end
12
12
 
13
13
  def client
@@ -47,7 +47,12 @@ module Casting
47
47
  private
48
48
 
49
49
  def __delegates__
50
- @__delegates__ ||= []
50
+ return @__delegates__ if defined?(@__delegates__)
51
+ if frozen?
52
+ []
53
+ else
54
+ @__delegates__ = []
55
+ end
51
56
  end
52
57
 
53
58
  def method_missing(meth, *args, &block)
@@ -1,24 +1,24 @@
1
1
  module Casting
2
2
  module Null
3
- def self.instance_method(name)
3
+ def self.instance_method(_)
4
4
  Empty.instance_method(:null)
5
5
  end
6
- def self.method_defined?(meth)
6
+ def self.method_defined?(_)
7
7
  true
8
8
  end
9
9
  end
10
10
  module Blank
11
- def self.instance_method(name)
11
+ def self.instance_method(_)
12
12
  Empty.instance_method(:blank)
13
13
  end
14
- def self.method_defined?(meth)
14
+ def self.method_defined?(_)
15
15
  true
16
16
  end
17
17
  end
18
18
  module Empty
19
- def null(*args, &block); end
20
- def blank(*args, &block)
19
+ def null(*, &_block); end
20
+ def blank(*, &_block)
21
21
  ""
22
22
  end
23
23
  end
24
- end
24
+ end
@@ -10,15 +10,15 @@ module Casting
10
10
 
11
11
  class PreparedDelegation
12
12
 
13
- attr_reader :client
14
- attr_reader :delegated_method_name, :attendant, :arguments, :block
15
- private :delegated_method_name, :attendant, :arguments, :block
13
+ attr_accessor :client, :delegated_method_name, :attendant, :arguments, :block
14
+ private :block
16
15
 
17
- def initialize(settings)
16
+ def initialize(**settings, &block)
18
17
  @delegated_method_name = settings[:delegated_method_name]
19
18
  @client = settings[:client]
20
19
  @attendant = settings[:attendant]
21
20
  @arguments = settings[:arguments]
21
+ @block = block
22
22
  end
23
23
 
24
24
  def to(object_or_module)
@@ -59,7 +59,10 @@ module Casting
59
59
  end
60
60
 
61
61
  def method_module
62
- delegated_method.owner unless delegated_method.owner.is_a?(Class)
62
+ mod = delegated_method.owner
63
+ unless mod.is_a?(Class)
64
+ mod
65
+ end
63
66
  end
64
67
 
65
68
  def delegated_method
@@ -1,3 +1,3 @@
1
1
  module Casting
2
- VERSION = '0.7.1'
2
+ VERSION = '0.7.2'
3
3
  end
@@ -1,12 +1,5 @@
1
- require 'simplecov'
2
- SimpleCov.start do
3
- add_filter 'test'
4
- end
5
-
6
- require 'coveralls'
7
- if ENV['COVERALLS']
8
- Coveralls.wear!
9
- end
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
10
3
 
11
4
  require 'minitest/autorun'
12
5
  require 'casting'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: casting
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Gay
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-27 00:00:00.000000000 Z
11
+ date: 2016-07-28 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |-
14
14
  Casting assists in method delegation which preserves the binding of 'self' to the object receiving a message.
@@ -20,8 +20,12 @@ executables: []
20
20
  extensions: []
21
21
  extra_rdoc_files: []
22
22
  files:
23
+ - LICENSE
24
+ - README.md
25
+ - Rakefile
23
26
  - lib/casting.rb
24
27
  - lib/casting/client.rb
28
+ - lib/casting/context.rb
25
29
  - lib/casting/delegation.rb
26
30
  - lib/casting/method_consolidator.rb
27
31
  - lib/casting/missing_method_client.rb
@@ -30,10 +34,6 @@ files:
30
34
  - lib/casting/prepared_delegation.rb
31
35
  - lib/casting/super_delegate.rb
32
36
  - lib/casting/version.rb
33
- - LICENSE
34
- - Rakefile
35
- - README.md
36
- - test/test_helper.rb
37
37
  - test/casting_19_test.rb
38
38
  - test/casting_20_test.rb
39
39
  - test/casting_test.rb
@@ -42,9 +42,10 @@ files:
42
42
  - test/delegation_test.rb
43
43
  - test/method_consolidator_test.rb
44
44
  - test/missing_method_client_test.rb
45
- - test/null_module_test.rb
46
45
  - test/module_cleanup_test.rb
46
+ - test/null_module_test.rb
47
47
  - test/super_test.rb
48
+ - test/test_helper.rb
48
49
  homepage: http://github.com/saturnflyer/casting
49
50
  licenses:
50
51
  - MIT
@@ -55,17 +56,17 @@ require_paths:
55
56
  - lib
56
57
  required_ruby_version: !ruby/object:Gem::Requirement
57
58
  requirements:
58
- - - '>='
59
+ - - ">="
59
60
  - !ruby/object:Gem::Version
60
61
  version: '0'
61
62
  required_rubygems_version: !ruby/object:Gem::Requirement
62
63
  requirements:
63
- - - '>='
64
+ - - ">="
64
65
  - !ruby/object:Gem::Version
65
66
  version: '0'
66
67
  requirements: []
67
68
  rubyforge_project:
68
- rubygems_version: 2.0.14
69
+ rubygems_version: 2.6.6
69
70
  signing_key:
70
71
  specification_version: 4
71
72
  summary: Proper method delegation.