mini_object 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 42c7b681ee29460d5b652d07069aa46b50dbd3f7
4
+ data.tar.gz: 6b9083abe99eed8a6c42b777984e7f0cab6491ae
5
+ SHA512:
6
+ metadata.gz: fae92c73f7def24ddb55120650925f6ecfedb8e322ce1be48d6aa970be5979e8a76ebbb29625ea8d5efae1f03b468e7a57204378d4f2b4b2fcb90445d777c59d
7
+ data.tar.gz: 696a5b683d06e54a23ebecb377245c71fd2620c8b785b5502671dc6134eec557253fb5c2241fef0c6711e30803952bd72a1e8a551f31f93f17ee868a39e8381c
data/.gitignore ADDED
File without changes
data/.yardoc/checksums ADDED
@@ -0,0 +1,7 @@
1
+ lib/lazy.rb 7e4d5fabe9a99f5a2751823cd1ea4e67f446ee2e
2
+ lib/inline.rb df7b92b051d5e5072ad5b486576a801fb3a336a7
3
+ lib/section.rb b05f398196140a836f5e125c20f9988f7a7ef000
4
+ lib/version.rb 2b03a00fee65075ba6f4715792ec212a3b47d654
5
+ lib/resolver.rb c4cf365fd98c2d454e2d11404be070b3d46690f6
6
+ lib/injectable.rb c95a2ea2a7500684d293be0c89196887c72ee68a
7
+ lib/mini_object.rb c4541e47c74f1d904221f2067ad9c0fc0e551ea9
Binary file
Binary file
Binary file
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test, :development do
6
+ gem 'rspec', require: false
7
+ gem 'pry', require: false
8
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,39 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mini_object (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ coderay (1.1.0)
10
+ diff-lcs (1.2.5)
11
+ method_source (0.8.2)
12
+ pry (0.10.1)
13
+ coderay (~> 1.1.0)
14
+ method_source (~> 0.8.1)
15
+ slop (~> 3.4)
16
+ rake (10.4.2)
17
+ rspec (3.1.0)
18
+ rspec-core (~> 3.1.0)
19
+ rspec-expectations (~> 3.1.0)
20
+ rspec-mocks (~> 3.1.0)
21
+ rspec-core (3.1.7)
22
+ rspec-support (~> 3.1.0)
23
+ rspec-expectations (3.1.2)
24
+ diff-lcs (>= 1.2.0, < 2.0)
25
+ rspec-support (~> 3.1.0)
26
+ rspec-mocks (3.1.3)
27
+ rspec-support (~> 3.1.0)
28
+ rspec-support (3.1.2)
29
+ slop (3.6.0)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ bundler (~> 1.3)
36
+ mini_object!
37
+ pry
38
+ rake
39
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2014 Manuel Morales, Workshare ltd., et al.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # MiniObject
2
+
3
+ A set of tools which will make easier to work with objects instead of classes
4
+ and injecting dependencies.
5
+
6
+
7
+ ## Inline
8
+
9
+ Allows defining objects ad-hoc passing an initialization block.
10
+
11
+ ```ruby
12
+ homer = Inline.new 'Homer Simpson' do
13
+ def talk
14
+ 'Doh!'
15
+ end
16
+
17
+ def sleep
18
+ end
19
+ end
20
+ # => < Homer Simpson / Inline : talk, sleep >
21
+
22
+ homer.talk
23
+ # => 'Doh!'
24
+ ```
25
+
26
+ ## Injectable
27
+
28
+ Makes easier and nicer to assign values and inject dependencies to objects.
29
+ The key feature is the ability to assign lambdas as way to resolve the value:
30
+
31
+ ```ruby
32
+ class UsersRepository
33
+ include Injectable
34
+ attr_injectable :store
35
+ end
36
+
37
+ users_repo = UsersRepository.new
38
+ users_repo.store{ app.stores.redis }
39
+ ```
40
+
41
+ In the example, if `app.stores.persistent` changes, the repository
42
+ will inmediately see the new store.
43
+
44
+
45
+ ## RemarkableInspect
46
+
47
+ Provides an `inspect` and `to_s` which focus on methods:
48
+
49
+ ```ruby
50
+ class Application
51
+ include RemarkableInspect
52
+
53
+ def config; end
54
+ def config=; end
55
+ def stores; end
56
+ end
57
+ # => Application( config/=, stores )
58
+
59
+ Application.new
60
+ # => < Application : config/=, stores >
61
+ ```
62
+
63
+ ## Lazy
64
+
65
+ A proxy that will lazy evaluate the proxied object.
66
+ Useful when an object expect an dependency but we want to
67
+ instantiate it only on demand:
68
+
69
+ ```ruby
70
+ users_repository.store = Lazy.new { Redis.new }
71
+ ```
72
+
73
+ This way `Redis.new` will only be executed when `users_repository.store`
74
+ it is called for the first time.
75
+
76
+ It also allows defining build callbacks:
77
+
78
+ ```ruby
79
+ users_repository.store = Lazy.new { Redis.new }
80
+ users_repository.build_step(:clear) { |redis| redis.flushdb }
81
+ ```
82
+
83
+
84
+ ## Resolver
85
+
86
+ A proxy that will always evaluate the given block.
87
+ Useful when an object expect an dependency but we want it
88
+ to be resolved on demand:
89
+
90
+ ```ruby
91
+ users_repository.store = Lazy.new{ app.stores.redis }
92
+ ```
93
+
94
+ In the example, if `app.stores.redis`, the repository
95
+ will inmediately see the new store.
96
+
97
+
98
+ ## Contributing
99
+
100
+ Do not forget to run the tests with:
101
+
102
+ ```bash
103
+ rake
104
+ ```
105
+
106
+ And bump the version with any of:
107
+
108
+ ```bash
109
+ $ gem bump --version 1.1.1 # Bump the gem version to the given version number
110
+ $ gem bump --version major # Bump the gem version to the next major level (e.g. 0.0.1 to 1.0.0)
111
+ $ gem bump --version minor # Bump the gem version to the next minor level (e.g. 0.0.1 to 0.1.0)
112
+ $ gem bump --version patch # Bump the gem version to the next patch level (e.g. 0.0.1 to 0.0.2)
113
+ ```
114
+
115
+
116
+ ## License
117
+
118
+ Released under the MIT License.
119
+ See the [LICENSE](LICENSE.txt) file for further details.
120
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake'
3
+
4
+ require 'rspec/core/rake_task'
5
+ task :default => :spec
6
+ task :test => :spec
7
+ desc 'Run all specs'
8
+ RSpec::Core::RakeTask.new('spec') do |spec|
9
+ spec.rspec_opts = %w{}
10
+ end
data/lib/box.rb ADDED
@@ -0,0 +1,10 @@
1
+ module MiniObject
2
+ class Box
3
+ include Injectable
4
+ include RemarkableInspect
5
+
6
+ def initialize attrs = {}
7
+ self.attributes= attrs
8
+ end
9
+ end
10
+ end
data/lib/injectable.rb ADDED
@@ -0,0 +1,73 @@
1
+ module MiniObject
2
+ module Injectable
3
+ NULL = Object.new
4
+
5
+ def initialize &block
6
+ super
7
+ block.call self if block
8
+ end
9
+
10
+ def self.included klass
11
+ klass.extend self
12
+ end
13
+
14
+ def self.getsetter_definition_for name
15
+ lambda do |value = NULL, &block|
16
+ if block
17
+ if value == NULL || value == nil
18
+ instance_variable_set("@#{name}_proc", block)
19
+ else
20
+ send("#{name}=", value)
21
+ end
22
+ else
23
+ if value == NULL
24
+ p = instance_variable_get("@#{name}_proc")
25
+ p || raise("No #{name} defined yet for #{inspect}")
26
+ p.call
27
+ else
28
+ send("#{name}=", value)
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.setter_definition_for name
35
+ lambda do |value|
36
+ instance_variable_set("@#{name}_proc", lambda{ value })
37
+ value
38
+ end
39
+ end
40
+
41
+ def cattr_injectable name
42
+ define_singleton_method name, &Injectable.getsetter_definition_for(name)
43
+ define_singleton_method "#{name}=", &Injectable.setter_definition_for(name)
44
+ end
45
+
46
+ def attr_injectable name
47
+ define_method name, &Injectable.getsetter_definition_for(name)
48
+ define_method "#{name}=", &Injectable.setter_definition_for(name)
49
+ end
50
+
51
+ def let name, &block
52
+ var_name = :"@#{name}"
53
+
54
+ define_singleton_method "#{name}=" do |value|
55
+ instance_variable_set var_name, value
56
+ end
57
+
58
+ define_singleton_method name do
59
+ if instance_variable_defined? var_name
60
+ instance_variable_get var_name
61
+ else
62
+ instance_variable_set var_name, block.call(self)
63
+ end
64
+ end
65
+ end
66
+
67
+ def attributes= attrs
68
+ attrs.each do |k,v|
69
+ public_send "#{k}=", v
70
+ end
71
+ end
72
+ end
73
+ end
data/lib/inline.rb ADDED
@@ -0,0 +1,24 @@
1
+ module MiniObject
2
+ class Inline
3
+ include Injectable
4
+ include RemarkableInspect
5
+
6
+ attr_accessor :inline_name
7
+
8
+ def initialize name = nil, &block
9
+ @inline_name = name || 'inline'
10
+ instance_exec self, &block if block
11
+ end
12
+
13
+ def remarkable_methods
14
+ methods - self.class.instance_methods
15
+ end
16
+
17
+ def remarkable_name
18
+ "#{inline_name || 'anon'} / Inline"
19
+ end
20
+
21
+ # TODO: Explore the possiblity of allowing access to methods and
22
+ # vars defined outside the block.
23
+ end
24
+ end
data/lib/lazy.rb ADDED
@@ -0,0 +1,63 @@
1
+ require 'delegate'
2
+
3
+ module MiniObject
4
+ class Lazy < Delegator
5
+ attr_accessor :lazy_name
6
+
7
+ def initialize name = nil, &block
8
+ self.lazy_name = name
9
+ @block = block
10
+ end
11
+
12
+ def __getobj__
13
+ @obj ||= @block.call.tap do |obj|
14
+ build_steps.each do |name, block|
15
+ block.call obj
16
+ end
17
+ end
18
+ end
19
+
20
+ alias get_obj __getobj__
21
+
22
+ def resolver_bound
23
+ @block.binding.eval('self')
24
+ end
25
+
26
+ def build_step name, &block
27
+ build_steps[name] = block
28
+ end
29
+
30
+ def build &block
31
+ @block = block
32
+ end
33
+
34
+ def inspect
35
+ prefix = lazy_name ? "#{lazy_name}: " : ""
36
+ steps = " " + build_steps.keys.join(", ") if build_steps.any?
37
+ "< #{prefix}Lazy(#{formatted_block_source}#{steps}) >"
38
+ end
39
+
40
+ alias to_s inspect
41
+
42
+ private
43
+
44
+ def build_steps
45
+ @build_steps ||= {}
46
+ end
47
+
48
+ def block_source
49
+ require 'method_source'
50
+ begin
51
+ MethodSource.source_helper(@block.source_location)
52
+ rescue MethodSource::SourceNotFoundError
53
+ '{???}'
54
+ end
55
+ end
56
+
57
+ def formatted_block_source
58
+ code = block_source.split("\n").map(&:strip).join("; ")
59
+ code = code[0..59] + "\u2026" if code.length > 60
60
+ code.inspect
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,12 @@
1
+ require "version"
2
+
3
+ module MiniObject
4
+ autoload :Lazy, 'lazy'
5
+ autoload :Injectable, 'injectable'
6
+ autoload :Resolver, 'resolver'
7
+ autoload :Inline, 'inline'
8
+ autoload :Toolbox, 'toolbox'
9
+ autoload :Tool, 'tool'
10
+ autoload :ForwardingDSL, 'forwarding_dsl'
11
+ autoload :RemarkableInspect, 'remarkable_inspect'
12
+ end
@@ -0,0 +1,47 @@
1
+ module MiniObject
2
+ module RemarkableInspect
3
+ def to_s
4
+ "< #{remarkable_name} : #{remarkable_methods.join(", ")} >"
5
+ end
6
+
7
+ alias inspect to_s
8
+
9
+ def self.included klass
10
+ klass.extend ClassMethods
11
+ end
12
+
13
+ private
14
+
15
+ def remarkable_methods
16
+ self.class.remarkable_methods
17
+ end
18
+
19
+ def remarkable_name
20
+ self.class.name
21
+ end
22
+
23
+ module ClassMethods
24
+ def inspect
25
+ "#{formatted_name}( #{remarkable_methods.join(", ")} )"
26
+ end
27
+
28
+ def remarkable_methods
29
+ (self.instance_methods - Box.instance_methods).map(&:to_s).tap do |mm|
30
+ # Substittues [my_method, my_method=] by [my_method/=]
31
+ mm.grep(/\=$/).each do |setter|
32
+ getter = setter.gsub /\=$/, ''
33
+ if mm.include? getter
34
+ mm.delete setter
35
+ mm[mm.find_index(getter)] = setter.gsub /\=$/, '/='
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def formatted_name
42
+ first_ancestor_name = ancestors.map(&:name).compact.first
43
+ name || "#{first_ancestor_name}:0x#{'%x' % (object_id << 1)}"
44
+ end
45
+ end
46
+ end
47
+ end
data/lib/resolver.rb ADDED
@@ -0,0 +1,15 @@
1
+ module MiniObject
2
+ class Resolver < Delegator
3
+ def initialize &block
4
+ @block = block
5
+ end
6
+
7
+ def __getobj__
8
+ @block.call
9
+ end
10
+
11
+ def resolver_bound
12
+ @block.binding.eval('self')
13
+ end
14
+ end
15
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module MiniObject
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ gem_name = "mini_object"
3
+
4
+ lib = File.expand_path('../lib', __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require "#{gem_name}"
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = gem_name
10
+ spec.version = MiniObject::VERSION
11
+ spec.authors = ["Manuel Morales"]
12
+ spec.email = ['manuelmorales@gmail.com']
13
+ spec.description = File.read('README.md').split("\n").reject{|l| l.length == 0 || l =~ /^[#=]+/ }.first
14
+ spec.summary = spec.description
15
+ spec.homepage = "https://github.com/manuelmorales/#{spec.name.gsub('_','-')}"
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files`.split($/)
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
data/spec/box_spec.rb ADDED
@@ -0,0 +1,126 @@
1
+ require_relative 'spec_helper'
2
+ require 'box'
3
+
4
+ describe 'Box' do
5
+ it 'allows nested boxes' do
6
+
7
+ stub_const 'Stores', Class.new(Box) {
8
+ def memory
9
+ :memory_store
10
+ end
11
+ }
12
+
13
+ stub_const 'BoxApp', Class.new(Box) {
14
+ def stores
15
+ @stores ||= Stores.new
16
+ end
17
+ }
18
+
19
+ expect(BoxApp.new.stores.memory).to eq :memory_store
20
+ end
21
+
22
+ it 'allows tools requiring a config' do
23
+
24
+ stub_const 'Stores', Class.new(Box) {
25
+ attr_accessor :config
26
+
27
+ def hash; {}; end
28
+ def array; []; end
29
+
30
+ def default
31
+ case config[:default]
32
+ when 'array' then array
33
+ when 'hash' then hash
34
+ end
35
+ end
36
+ }
37
+
38
+ stub_const 'Config', Class.new(Box) {
39
+ def stores
40
+ @stores ||= { default: 'hash' }
41
+ end
42
+ }
43
+
44
+ stub_const 'BoxApp', Class.new(Box) {
45
+ def stores
46
+ @stores ||= Stores.new config: config.stores
47
+ end
48
+
49
+ def config
50
+ @config ||= Config.new
51
+ end
52
+ }
53
+
54
+ subject = BoxApp.new
55
+ expect(subject.stores.default).to eq({})
56
+
57
+ subject.config.stores[:default] = 'array'
58
+ expect(subject.stores.default).to eq([])
59
+ end
60
+
61
+ it 'allows overriding a tool' do
62
+
63
+ stub_const 'BoxApp', Class.new(Box) {
64
+ attr_accessor :store
65
+
66
+ def store
67
+ @store ||= :memory
68
+ end
69
+ }
70
+
71
+ subject = BoxApp.new
72
+ expect(subject.store).to be :memory
73
+
74
+ subject.store = :persistent
75
+ expect(subject.store).to be :persistent
76
+ end
77
+
78
+ it 'allows overriding config files with inheritance' do
79
+ stub_const 'Defaults', { persistent: true, adapter: 'mysql' }
80
+ stub_const 'Overrides', { adapter: 'postgres' }
81
+
82
+ stub_const 'Conf', Class.new(Box) {
83
+ def db
84
+ @db ||= Defaults.merge db_overrides
85
+ end
86
+
87
+ def db_overrides
88
+ {}
89
+ end
90
+ }
91
+
92
+ stub_const 'BoxApp', Class.new(Box) {
93
+ def config
94
+ @config ||= Conf.new
95
+ end
96
+ }
97
+
98
+ stub_const 'TestConf', Class.new(Conf) {
99
+ def db_overrides
100
+ Overrides
101
+ end
102
+ }
103
+
104
+ stub_const 'TestBoxApp', Class.new(BoxApp) {
105
+ def config
106
+ @config ||= TestConf.new
107
+ end
108
+ }
109
+
110
+ expect(BoxApp.new.config.db).to eq({ persistent: true, adapter: 'mysql' })
111
+ expect(TestBoxApp.new.config.db).to eq({ persistent: true, adapter: 'postgres' })
112
+ end
113
+
114
+ it 'looks pretty' do
115
+ stub_const 'BoxApp', Class.new(Box){
116
+ def config; end
117
+ def config=; end
118
+ def stores; end
119
+ }
120
+
121
+ subject = BoxApp.new
122
+
123
+ expect(subject.to_s).to eq('< BoxApp : config/=, stores >')
124
+ expect(BoxApp.inspect).to eq('BoxApp( config/=, stores )')
125
+ end
126
+ end
@@ -0,0 +1,81 @@
1
+ require_relative 'spec_helper'
2
+ require 'injectable'
3
+
4
+ RSpec.describe 'Injectable' do
5
+ shared_examples_for 'having an injectable name' do
6
+ it 'provides getter and setter' do
7
+ expect(subject.name = 'A name').to eq 'A name'
8
+ expect(subject.name).to eq 'A name'
9
+ end
10
+
11
+ it 'allows setting a value without the = sign' do
12
+ expect(subject.name 'A name').to eq 'A name'
13
+ expect(subject.name).to eq 'A name'
14
+ end
15
+
16
+ it 'allows setting nil' do
17
+ subject.name = 'A name'
18
+ expect(subject.name nil).to eq nil
19
+ expect(subject.name).to eq nil
20
+ end
21
+
22
+ it 'allows setting a value with a lambda' do
23
+ subject.name { 'A name' }
24
+ expect(subject.name).to eq 'A name'
25
+ end
26
+
27
+ it 'does not memoize the lambda' do
28
+ counter = 0
29
+ subject.name { counter += 1 }
30
+ expect(subject.name).to eq 1
31
+ expect(subject.name).to eq 2
32
+ end
33
+
34
+ it 'gives priority to the value if both, block and value == nil are given' do
35
+ subject.name('value'){ 'block' }
36
+ expect(subject.name).to eq('value')
37
+
38
+ subject.name(nil) { 'block' }
39
+ expect(subject.name).to eq('block')
40
+ end
41
+ end
42
+
43
+ context 'attr_accessor within a class' do
44
+ let(:subject_class) do
45
+ Class.new do
46
+ include Injectable
47
+ attr_injectable :name
48
+ end
49
+ end
50
+
51
+ subject { subject_class.new }
52
+ it_behaves_like 'having an injectable name'
53
+ end
54
+
55
+ context 'cattr_accessor within a class' do
56
+ let(:subject_class) do
57
+ Class.new do
58
+ include Injectable
59
+ cattr_injectable :name
60
+ end
61
+ end
62
+
63
+ subject { subject_class }
64
+ it_behaves_like 'having an injectable name'
65
+ end
66
+
67
+ describe '#attributes=' do
68
+ let(:subject_class) do
69
+ Class.new do
70
+ include Injectable
71
+ cattr_injectable :name
72
+ end
73
+ end
74
+
75
+ it 'assings each attr' do
76
+ subject = subject_class
77
+ subject.attributes=({ name: 'MyName' })
78
+ expect(subject.name).to eq 'MyName'
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,28 @@
1
+ require_relative 'spec_helper'
2
+
3
+ RSpec.describe 'Inline' do
4
+ it 'allows defining methods with an initialization block' do
5
+ subject = Inline.new do
6
+ def bark
7
+ 'woof'
8
+ end
9
+ end
10
+
11
+ expect(subject.bark).to eq('woof')
12
+ end
13
+
14
+ it 'has an inspect and to_s' do
15
+ subject = Inline.new 'some name' do
16
+ def bark
17
+ 'woof'
18
+ end
19
+
20
+ def sleep
21
+ 'zzz'
22
+ end
23
+ end
24
+
25
+ expect(subject.inspect).to eq("< some name / Inline : bark, sleep >")
26
+ expect(subject.to_s).to eq("< some name / Inline : bark, sleep >")
27
+ end
28
+ end
data/spec/lazy_spec.rb ADDED
@@ -0,0 +1,71 @@
1
+ require_relative 'spec_helper'
2
+
3
+ RSpec.describe 'Lazy' do
4
+ let(:klass) { double('class', new: instance) }
5
+ let(:instance) { double('instance', a_method: 'a_result') }
6
+
7
+ it 'forwards messages to the result of the lambda' do
8
+ subject = Lazy.new{ klass.new }
9
+ expect(subject.a_method).to eq('a_result')
10
+ end
11
+
12
+ it 'is lazy' do
13
+ expect(klass).not_to receive(:new)
14
+ subject = Lazy.new{ klass.new }
15
+ end
16
+
17
+ it 'memoizes the result' do
18
+ expect(klass).to receive(:new).once
19
+ subject = Lazy.new{ klass.new }
20
+
21
+ subject.a_method
22
+ subject.a_method
23
+ end
24
+
25
+ describe 'inspect' do
26
+ it 'has the source code' do
27
+ subject = Lazy.new { klass.new }
28
+ expect(subject.inspect).to match('klass.new')
29
+ end
30
+
31
+ it 'has a name' do
32
+ subject = Lazy.new('The Subject') { klass.new }
33
+ expect(subject.inspect).to match('The Subject')
34
+ end
35
+
36
+ it 'doesn\'t have the name when blank' do
37
+ subject = Lazy.new { klass.new }
38
+ expect(subject.inspect).to match('< Lazy')
39
+ end
40
+
41
+ it 'is aliased as to_s' do
42
+ subject = Lazy.new { klass.new }
43
+ expect(subject.to_s).to match('klass.new')
44
+ end
45
+ end
46
+
47
+ describe 'build_steps' do
48
+ it 'invokes them at build time' do
49
+ subject = Lazy.new { [] }
50
+ subject.build_step(:add_one) { |array| array << 1 }
51
+
52
+ expect(subject.get_obj).to eq([1])
53
+ end
54
+
55
+ it 'allows substituting them' do
56
+ subject = Lazy.new { [] }
57
+ subject.build_step(:add_one) { |array| array << 1 }
58
+ subject.build_step(:add_one) { |array| array << :one }
59
+
60
+ expect(subject.get_obj).to eq([:one])
61
+ end
62
+ end
63
+
64
+ describe 'build' do
65
+ it 'assigns the build block' do
66
+ subject = Lazy.new
67
+ subject.build { :one }
68
+ expect(subject.get_obj).to eq :one
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe MiniObject do
4
+ it 'has a version' do
5
+ expect(MiniObject::VERSION).not_to be_nil
6
+ end
7
+ end
@@ -0,0 +1,43 @@
1
+ require_relative 'spec_helper'
2
+
3
+ RSpec.describe 'RemarkableInspect' do
4
+ subject { SubjectClass.new }
5
+
6
+ before do
7
+ stub_const 'SubjectClass', Class.new {
8
+ include RemarkableInspect
9
+
10
+ def config; end
11
+ def config=; end
12
+ def stores; end
13
+ }
14
+ end
15
+
16
+ describe '#to_s' do
17
+ it 'contains class name and class specific methods' do
18
+ expect(subject.to_s).to eq('< SubjectClass : config/=, stores >')
19
+ end
20
+ end
21
+
22
+ describe '#inspect' do
23
+ it 'contains class name and class specific methods' do
24
+ expect(subject.inspect).to eq('< SubjectClass : config/=, stores >')
25
+ end
26
+ end
27
+
28
+ describe '.to_s' do
29
+ it 'contains just the class name' do
30
+ expect(SubjectClass.to_s).to eq('SubjectClass')
31
+ end
32
+ end
33
+
34
+ describe '.inspect' do
35
+ it 'contains class name and class specific methods' do
36
+ expect(SubjectClass.inspect).to eq('SubjectClass( config/=, stores )')
37
+ end
38
+
39
+ it 'contains the object hash in anonymous classes' do
40
+ expect(Class.new(SubjectClass).inspect).to match(/SubjectClass:0x.*\( config\/=, stores \)/)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'spec_helper'
2
+
3
+ RSpec.describe 'Resolver' do
4
+ it 'delegates to the result of evaluating the lambda' do
5
+ target = double('target')
6
+ subject = Resolver.new { target }
7
+
8
+ expect(target).to receive(:a_method)
9
+ subject.a_method
10
+ end
11
+
12
+ it 'will always point to the latest value' do
13
+ target = old_target = double('OLD target')
14
+ subject = Resolver.new { target }
15
+
16
+ target = new_target = double('NEW target')
17
+ expect(new_target).to receive(:a_method)
18
+
19
+ subject.a_method
20
+ end
21
+
22
+ it '#resolver_bound returns the object owner of the binding' do
23
+ subject = Resolver.new { 2 + 2 }
24
+ expect(subject.resolver_bound).to eq self
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require 'pry'
4
+
5
+ RSpec.configure do |config|
6
+ config.color = true
7
+ config.tty = true
8
+ end
9
+
10
+ $LOAD_PATH.unshift File.expand_path('lib')
11
+ require 'mini_object'
12
+ include MiniObject
13
+
14
+ $LOAD_PATH.unshift File.expand_path('spec/support')
15
+
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mini_object
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Manuel Morales
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: A set of tools which will make easier to work with objects instead of
42
+ classes
43
+ email:
44
+ - manuelmorales@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".yardoc/checksums"
51
+ - ".yardoc/object_types"
52
+ - ".yardoc/objects/root.dat"
53
+ - ".yardoc/proxy_types"
54
+ - Gemfile
55
+ - Gemfile.lock
56
+ - LICENSE.txt
57
+ - README.md
58
+ - Rakefile
59
+ - lib/box.rb
60
+ - lib/injectable.rb
61
+ - lib/inline.rb
62
+ - lib/lazy.rb
63
+ - lib/mini_object.rb
64
+ - lib/remarkable_inspect.rb
65
+ - lib/resolver.rb
66
+ - lib/version.rb
67
+ - mini_object.gemspec
68
+ - spec/box_spec.rb
69
+ - spec/injectable_spec.rb
70
+ - spec/inline_spec.rb
71
+ - spec/lazy_spec.rb
72
+ - spec/mini_object_spec.rb
73
+ - spec/remarkable_inspect_spec.rb
74
+ - spec/resolver_spec.rb
75
+ - spec/spec_helper.rb
76
+ homepage: https://github.com/manuelmorales/mini-object
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.2.2
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: A set of tools which will make easier to work with objects instead of classes
100
+ test_files:
101
+ - spec/box_spec.rb
102
+ - spec/injectable_spec.rb
103
+ - spec/inline_spec.rb
104
+ - spec/lazy_spec.rb
105
+ - spec/mini_object_spec.rb
106
+ - spec/remarkable_inspect_spec.rb
107
+ - spec/resolver_spec.rb
108
+ - spec/spec_helper.rb
109
+ has_rdoc: