manana 0.1.0 → 0.5.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4260f96ef0f5a33bc8a66db747e1759388927bc1
4
+ data.tar.gz: 9cb8a090b23e690c940fdefbbd1ababa97c41fd7
5
+ SHA512:
6
+ metadata.gz: bd56b8099f8cfad6e654fb4c2093d95e583c96dd433d3a690661e63d98c0228337e6c48739feda76a5757a8232ffb90d4bd63785cff5179d90d1181b17ee91a3
7
+ data.tar.gz: 46bcc0990610755a158174ce7715c41c2d70bbd55d7858e289714a013bee6cb4e460bc910f178dab0ec6ef7541089795ab4063401d40d2fd96fdd3b90c9372d7
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.2
4
4
  - 1.9.3
5
+ - 2.1.5
5
6
  env:
6
7
  global:
7
8
  - "TRAVIS=1"
data/Gemfile CHANGED
@@ -10,10 +10,12 @@ unless ENV["TRAVIS"] == "1"
10
10
  gem 'yard'
11
11
  gem 'redcarpet'
12
12
 
13
- gem 'pry'
14
- gem 'pry-debugger'
15
- gem 'pry-rescue'
16
- gem 'pry-stack_explorer'
13
+ if RUBY_VERSION =~ /^2\./
14
+ gem 'pry-byebug'
15
+ else
16
+ gem 'pry'
17
+ end
18
+
17
19
  end
18
20
 
19
21
  group :samples do
@@ -29,6 +31,5 @@ end
29
31
 
30
32
  # for travis.cl
31
33
  group :test do
32
- gem 'rake'
33
34
  gem 'mocha'
34
35
  end
data/README.md CHANGED
@@ -58,7 +58,7 @@ Or install it yourself as:
58
58
  require 'manana'
59
59
 
60
60
  # initialization...
61
- client = Manana.deferred_init {
61
+ client = Manana.wrap {
62
62
  Weather.setup # web service adapter setup
63
63
  Weather # return the class instance
64
64
  }
@@ -1,3 +1,3 @@
1
1
  class Manana
2
- VERSION = "0.1.0"
2
+ VERSION = "0.5.0"
3
3
  end
data/lib/manana.rb CHANGED
@@ -4,7 +4,7 @@ require "manana/version"
4
4
  # *Manana* lets you defer the initialization of an object until its methods are called.
5
5
  # @example basic usage - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
6
6
  # # initialization...
7
- # client = Manana.deferred_init {
7
+ # client = Manana.wrap {
8
8
  # Weather.setup
9
9
  # Weather
10
10
  # }
@@ -16,50 +16,52 @@ require "manana/version"
16
16
  # }
17
17
  #
18
18
  class Manana
19
-
20
- # wraps an initialization block so that it can be deferred to a later time when object methods are called.
19
+ private_class_method :new
20
+
21
+ # wraps the initialization of an object so that it can be deferred to a later time when object methods are called.
21
22
  # @example wrap an object - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
22
- # client = Manana.deferred_init {
23
+ # client = Manana.wrap {
23
24
  # Weather.setup # initialize the class
24
25
  # Weather # return the Weather class
25
26
  # }
26
27
  #
27
28
  # @param initialization_block [Proc] object initialization. the block must return the object to be wrapped.
28
- # @return [Manana] a wrapped version of the object.
29
- def self.deferred_init(&initialization_block)
30
- Manana.new(&initialization_block)
29
+ # @return [Deferrable] a wrapped version of the object.
30
+ def self.wrap(&initialization_block)
31
+ Deferrable.send(:new,&initialization_block)
31
32
  end
32
33
 
33
- # passes any method call through to the wrapped object after ensuring that the initialization block has
34
- # successfully completed once (setting a valid instance of the object).
35
- # @note Once the initialization block succeeds, it keeps the resulting object instance for subsequent method calls.
36
- #
37
- # @example calling a wrapped object - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
38
- # weather = client.city_weather("02201")
39
- #
40
- def method_missing(method, *args, &block)
41
- instance = safe_get_instance
42
- instance.send(method, *args, &block);
43
- end
44
-
45
- private
34
+ # class that proxies all requests to the wrapped object, ensuring that the object has been correctly initialized first.
35
+ class Deferrable < ::BasicObject
36
+ private_class_method :new
46
37
 
47
- def initialize(&initialization_block)
48
- @mutex = Mutex.new
49
- @deferred_initialization = initialization_block
50
- end
38
+ # passes any method call through to the wrapped object after ensuring that the initialization block has
39
+ # successfully completed once (thereby initializing the wrapped object).
40
+ # @note Once the initialization block succeeds, it keeps the resulting object for subsequent method calls.
41
+ #
42
+ # @example calling a wrapped object - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
43
+ # weather = client.city_weather("02201")
44
+ #
45
+ def method_missing(method, *args, &block)
46
+ _object.send(method, *args, &block);
47
+ end
51
48
 
52
- def safe_get_instance
53
- @mutex.synchronize do
54
- get_instance
49
+ # allows direct access to the wrapped object -- useful for debugging
50
+ # @return [Object] the object being wrapped
51
+ def _object
52
+ @mutex.synchronize do
53
+ if @object.nil?
54
+ @object = @deferred_initialization.call
55
+ end
56
+ @object
57
+ end
55
58
  end
56
- end
57
59
 
58
- def get_instance
59
- if @instance.nil?
60
- @instance = @deferred_initialization.call
60
+ private
61
+ def initialize(&initialization_block)
62
+ @mutex = ::Mutex.new
63
+ @deferred_initialization = initialization_block
61
64
  end
62
- @instance
63
65
  end
64
66
 
65
67
  end
data/manana.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "bundler"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "minitest"
24
24
  end
@@ -31,7 +31,7 @@ end
31
31
 
32
32
  # ------------ initialization code
33
33
 
34
- client = Manana.deferred_init {
34
+ client = Manana.wrap {
35
35
  # exponential backkoff logic in the initialization block
36
36
  retries = 0
37
37
  obj = nil
@@ -44,7 +44,7 @@ mini_death_star = nil
44
44
  puts "[Vader]: requsition a new DeathStar and make it snappy!"
45
45
  # boss said requisitions have to be faster*! Manana to the rescue!
46
46
  puts Benchmark.measure {
47
- mini_death_star = Manana.deferred_init {
47
+ mini_death_star = Manana.wrap {
48
48
  DeathStar.new
49
49
  }
50
50
  }
@@ -47,7 +47,7 @@ end
47
47
 
48
48
  # Before we start, we use Manana to wrap the client setup so that method calls on the client can be self-healing in case of failure.
49
49
  # NOTE: that the caller doesn't have to deal with whether or not this initialization succeeded, they can just call the client methods repeatedly.
50
- client = Manana.deferred_init {
50
+ client = Manana.wrap {
51
51
  Weather.setup
52
52
  Weather
53
53
  }
@@ -0,0 +1,17 @@
1
+ # something like ActiveRecord::Base
2
+ class BaseKlass
3
+
4
+ def self.connected?
5
+ @@connected ||= false
6
+ end
7
+
8
+ def self.establish_connection
9
+ @@connected = true
10
+ end
11
+
12
+ def self.find
13
+ raise "not connected!" unless self.connected?
14
+ [1,2,3]
15
+ end
16
+
17
+ end
@@ -9,6 +9,7 @@ end
9
9
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
10
10
  require 'manana'
11
11
 
12
+
12
13
  require 'minitest/autorun'
13
14
  require 'mocha/setup'
14
15
 
data/test/test_manana.rb CHANGED
@@ -33,10 +33,10 @@ class TestManana < Minitest::Test
33
33
  end
34
34
  end
35
35
 
36
- def test_deferred_init
36
+ def test_wrap
37
37
  obj = nil
38
38
  out, err = capture_io do
39
- obj = Manana.deferred_init {
39
+ obj = Manana.wrap {
40
40
  Klass.new
41
41
  }
42
42
  end
@@ -65,11 +65,12 @@ class TestManana < Minitest::Test
65
65
  end
66
66
  end
67
67
 
68
+
68
69
  # https://github.com/coldnebo/manana/issues/1
69
70
  def test_that_init_is_threadsafe
70
71
  Klass.reset
71
72
 
72
- klass = Manana.deferred_init {
73
+ klass = Manana.wrap {
73
74
  sleep(1)
74
75
  Klass.incr
75
76
  Klass
@@ -0,0 +1,42 @@
1
+ require 'minitest_helper'
2
+ require 'base_klass'
3
+
4
+ class TestWithSubclass < Minitest::Test
5
+
6
+ # initialize a very generic example object that does some stuff in initialization and has some instance methods you can call.
7
+ def setup
8
+ BaseKlass.class_variable_set(:@@connected, false)
9
+ end
10
+
11
+ # sanity check
12
+ def test_that_things_work_without_manana
13
+ @subklass = Class.new(BaseKlass)
14
+
15
+ assert_raises RuntimeError do
16
+ res = @subklass.find
17
+ end
18
+
19
+ BaseKlass.establish_connection
20
+
21
+ res = @subklass.find
22
+ refute_empty(res)
23
+
24
+ end
25
+
26
+ def test_wrap
27
+
28
+ @subklass = Manana.wrap {
29
+ unless BaseKlass.connected?
30
+ BaseKlass.establish_connection
31
+ end
32
+ subklass = Class.new(BaseKlass)
33
+ }
34
+
35
+ res = @subklass.find
36
+ refute_empty(res)
37
+ assert(BaseKlass.connected?)
38
+
39
+ end
40
+
41
+
42
+ end
metadata CHANGED
@@ -1,62 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manana
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 0.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - coldnebo
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-12-17 00:00:00.000000000 Z
11
+ date: 2015-04-10 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
- version: '1.3'
19
+ version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: '1.3'
26
+ version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: minitest
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  description: provides a simple way to defer initialization of an object until its
@@ -67,9 +60,9 @@ executables: []
67
60
  extensions: []
68
61
  extra_rdoc_files: []
69
62
  files:
70
- - .gitignore
71
- - .travis.yml
72
- - .yardopts
63
+ - ".gitignore"
64
+ - ".travis.yml"
65
+ - ".yardopts"
73
66
  - Gemfile
74
67
  - LICENSE.txt
75
68
  - README.md
@@ -83,43 +76,40 @@ files:
83
76
  - samples/exponential_backoff.rb
84
77
  - samples/fast_startup.rb
85
78
  - samples/self_healing.rb
79
+ - test/base_klass.rb
86
80
  - test/klass.rb
87
81
  - test/minitest_helper.rb
88
82
  - test/test_manana.rb
83
+ - test/test_with_subclass.rb
89
84
  homepage: https://github.com/coldnebo/manana
90
85
  licenses:
91
86
  - MIT
87
+ metadata: {}
92
88
  post_install_message:
93
89
  rdoc_options: []
94
90
  require_paths:
95
91
  - lib
96
92
  required_ruby_version: !ruby/object:Gem::Requirement
97
- none: false
98
93
  requirements:
99
- - - ! '>='
94
+ - - ">="
100
95
  - !ruby/object:Gem::Version
101
96
  version: '0'
102
- segments:
103
- - 0
104
- hash: -3306959934859244204
105
97
  required_rubygems_version: !ruby/object:Gem::Requirement
106
- none: false
107
98
  requirements:
108
- - - ! '>='
99
+ - - ">="
109
100
  - !ruby/object:Gem::Version
110
101
  version: '0'
111
- segments:
112
- - 0
113
- hash: -3306959934859244204
114
102
  requirements: []
115
103
  rubyforge_project:
116
- rubygems_version: 1.8.25
104
+ rubygems_version: 2.4.3
117
105
  signing_key:
118
- specification_version: 3
106
+ specification_version: 4
119
107
  summary: provides a simple way to defer initialization of an object until its methods
120
108
  are called
121
109
  test_files:
110
+ - test/base_klass.rb
122
111
  - test/klass.rb
123
112
  - test/minitest_helper.rb
124
113
  - test/test_manana.rb
114
+ - test/test_with_subclass.rb
125
115
  has_rdoc: