added 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +19 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.md +90 -0
- data/added.gemspec +21 -0
- data/lib/added.rb +3 -0
- data/lib/added/.implementation.rb.swp +0 -0
- data/lib/added/core_ext.rb +3 -0
- data/lib/added/implementation.rb +24 -0
- data/lib/added/version.rb +3 -0
- data/spec/added_spec.rb +97 -0
- metadata +60 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a35937cb5def349f87957a9051eda9b48e43232c
|
4
|
+
data.tar.gz: 8624cfe16cf21d2ee5ef2c6c05f33bfb349ce97e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 28d662efff045b68a7c1f06f897ad481bb4200dad1d47f42e0025e1c38cde46c18acccab844969e72b8e428aac8cd9dd1a168045f7d30e5ea2402094b5f49f36
|
7
|
+
data.tar.gz: 21b0364c4be97b695bb2e71dd00390a7341b592ee4a63c3139fd392c1c66a93944592ff71ccf9bd5984e9c686a52d1c0b8246adf92a60cdd03d373162ffae221
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2015 Jan Lelis
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# Added Hook for Ruby [![[version]](https://badge.fury.io/rb/added.svg)](http://badge.fury.io/rb/added) [![[travis]](https://travis-ci.org/janlelis/added.png)](https://travis-ci.org/janlelis/added)
|
2
|
+
|
3
|
+
Module#added: A unified module hook to run code on all instances when adding the module.
|
4
|
+
|
5
|
+
|
6
|
+
## Warning
|
7
|
+
|
8
|
+
This is experimental stuff, using new/advanced language features. You should exactly know what you do, if you want to use it in production.
|
9
|
+
|
10
|
+
Besides this, I am really curious if you like the approach this gem is taking!
|
11
|
+
|
12
|
+
|
13
|
+
## Description
|
14
|
+
|
15
|
+
Ruby allows you to run hooks, when an module is inserted into another object:
|
16
|
+
|
17
|
+
* Module#extended
|
18
|
+
* Module#included
|
19
|
+
* Module#prepended
|
20
|
+
|
21
|
+
This gem unifies all these hooks into a single `Module#added` one, which will be fired for *all* instances that the module has been added to. An example use case might be that you want to set some instance variable for all instances that include the module. There are three different occassions a hook is fired:
|
22
|
+
|
23
|
+
* An object extends itself with the module -> The added hook will run for this object
|
24
|
+
* A class has included/prepended the module -> The added hook will run on newly initialized objects of this class
|
25
|
+
* A class has included/prepended the module -> The added hook will run on all existing instances of this class
|
26
|
+
|
27
|
+
|
28
|
+
## Setup
|
29
|
+
|
30
|
+
Add to your `Gemfile`
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
gem 'added'
|
34
|
+
```
|
35
|
+
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
module MyStateSetter
|
41
|
+
def self.added(instance)
|
42
|
+
instance.instance_variable_set(:@my, "state")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Extending
|
47
|
+
object = Object.new
|
48
|
+
object.extend(MyStateSetter)
|
49
|
+
object.instance_variable_get(:@my) # => "state"
|
50
|
+
|
51
|
+
# Including (new instances)
|
52
|
+
klass = Class.new
|
53
|
+
klass.include(MyStateSetter)
|
54
|
+
object = klass.new
|
55
|
+
object.instance_variable_get(:@my) # => "state"
|
56
|
+
|
57
|
+
# Including (existing instances)
|
58
|
+
klass = Class.new
|
59
|
+
object = klass.new
|
60
|
+
klass.include(MyStateSetter)
|
61
|
+
object.instance_variable_get(:@my) # => "state"
|
62
|
+
|
63
|
+
# Prepending (new instances)
|
64
|
+
klass = Class.new
|
65
|
+
klass.prepend(MyStateSetter)
|
66
|
+
object = klass.new
|
67
|
+
object.instance_variable_get(:@my) # => "state"
|
68
|
+
|
69
|
+
# Including (existing instances)
|
70
|
+
klass = Class.new
|
71
|
+
object = klass.new
|
72
|
+
klass.prepend(MyStateSetter)
|
73
|
+
object.instance_variable_get(:@my) # => "state"
|
74
|
+
|
75
|
+
```
|
76
|
+
|
77
|
+
|
78
|
+
## JRuby Notes
|
79
|
+
|
80
|
+
This gem requires a Module#prepend implementation and must have the ObjectSpace available. As JRuby user this means you will need to run JRuby 9000 with the -X+O option to use this gem.
|
81
|
+
|
82
|
+
|
83
|
+
# Also See
|
84
|
+
|
85
|
+
* [ActiveSupport::Concern](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/concern.rb)
|
86
|
+
|
87
|
+
|
88
|
+
## MIT License
|
89
|
+
|
90
|
+
Copyright (C) 2015 by [Jan Lelis](http://janlelis.com).
|
data/added.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path('../lib/added/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "added"
|
7
|
+
gem.version = Added::VERSION
|
8
|
+
gem.summary = 'Added hook.'
|
9
|
+
gem.description = 'Module#added: A unified module hook to run code on all instances when adding the module.'
|
10
|
+
gem.license = "MIT"
|
11
|
+
gem.authors = ["Jan Lelis"]
|
12
|
+
gem.email = "mail@janlelis.de"
|
13
|
+
gem.homepage = "https://github.com/janlelis/added"
|
14
|
+
|
15
|
+
gem.files = Dir['{**/}{.*,*}'].select { |path| File.file?(path) }
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ['lib']
|
19
|
+
|
20
|
+
gem.required_ruby_version = '~> 2.0'
|
21
|
+
end
|
data/lib/added.rb
ADDED
Binary file
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Added
|
2
|
+
def extended(instance)
|
3
|
+
super
|
4
|
+
added(instance) if respond_to? :added
|
5
|
+
end
|
6
|
+
|
7
|
+
def included(klass)
|
8
|
+
super
|
9
|
+
if respond_to? :added
|
10
|
+
mod = self
|
11
|
+
klass.prepend(Module.new do
|
12
|
+
define_method(:initialize){ |*args, &block|
|
13
|
+
super(*args, &block)
|
14
|
+
mod.added(self)
|
15
|
+
}
|
16
|
+
end)
|
17
|
+
ObjectSpace.each_object(klass){ |instance|
|
18
|
+
added(instance)
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
alias prepended included
|
24
|
+
end
|
data/spec/added_spec.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require_relative '../lib/added'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
describe Added do
|
5
|
+
let :object do
|
6
|
+
Object.new
|
7
|
+
end
|
8
|
+
|
9
|
+
let :klass do
|
10
|
+
Class.new
|
11
|
+
end
|
12
|
+
|
13
|
+
let :mod do
|
14
|
+
Module.new do
|
15
|
+
def self.added(instance)
|
16
|
+
instance.instance_variable_set(:@my, "state")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'Extending' do
|
22
|
+
it 'works' do
|
23
|
+
object.extend(mod)
|
24
|
+
|
25
|
+
assert_equal "state", object.instance_variable_get(:@my)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'Including (new instances)' do
|
30
|
+
it 'works' do
|
31
|
+
klass.send :include, mod
|
32
|
+
object = klass.new
|
33
|
+
|
34
|
+
assert_equal "state", object.instance_variable_get(:@my)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'Including (existing instances)' do
|
39
|
+
it 'works' do
|
40
|
+
object = klass.new
|
41
|
+
klass.send :include, mod
|
42
|
+
|
43
|
+
assert_equal "state", object.instance_variable_get(:@my)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'Prepending (new instances)' do
|
48
|
+
it 'works' do
|
49
|
+
klass.send :prepend, mod
|
50
|
+
object = klass.new
|
51
|
+
|
52
|
+
assert_equal "state", object.instance_variable_get(:@my)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'Prepending (existing instances)' do
|
57
|
+
it 'works' do
|
58
|
+
object = klass.new
|
59
|
+
klass.send :prepend, mod
|
60
|
+
|
61
|
+
assert_equal "state", object.instance_variable_get(:@my)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'More' do
|
66
|
+
it 'respects initializers before inclusion' do
|
67
|
+
klass.send :define_method, :initialize do |*args|
|
68
|
+
@my2 = args[0]
|
69
|
+
end
|
70
|
+
klass.include(mod)
|
71
|
+
object = klass.new("state2")
|
72
|
+
|
73
|
+
assert_equal "state", object.instance_variable_get(:@my)
|
74
|
+
assert_equal "state2", object.instance_variable_get(:@my2)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'respects initializers after inclusion' do
|
78
|
+
klass.include(mod)
|
79
|
+
klass.send :define_method, :initialize do |*args|
|
80
|
+
@my2 = args[0]
|
81
|
+
end
|
82
|
+
object = klass.new("state2")
|
83
|
+
|
84
|
+
assert_equal "state", object.instance_variable_get(:@my)
|
85
|
+
assert_equal "state2", object.instance_variable_get(:@my2)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'works with sub-classed classes' do
|
89
|
+
sub_klass = Class.new(klass)
|
90
|
+
klass.include(mod)
|
91
|
+
object = sub_klass.new
|
92
|
+
|
93
|
+
assert_equal "state", object.instance_variable_get(:@my)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: added
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jan Lelis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: 'Module#added: A unified module hook to run code on all instances when
|
14
|
+
adding the module.'
|
15
|
+
email: mail@janlelis.de
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- ".travis.yml"
|
22
|
+
- CHANGELOG.md
|
23
|
+
- Gemfile
|
24
|
+
- Gemfile.lock
|
25
|
+
- MIT-LICENSE.txt
|
26
|
+
- README.md
|
27
|
+
- added.gemspec
|
28
|
+
- lib/added.rb
|
29
|
+
- lib/added/.implementation.rb.swp
|
30
|
+
- lib/added/core_ext.rb
|
31
|
+
- lib/added/implementation.rb
|
32
|
+
- lib/added/version.rb
|
33
|
+
- spec/added_spec.rb
|
34
|
+
homepage: https://github.com/janlelis/added
|
35
|
+
licenses:
|
36
|
+
- MIT
|
37
|
+
metadata: {}
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2.0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 2.4.5
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: Added hook.
|
58
|
+
test_files:
|
59
|
+
- spec/added_spec.rb
|
60
|
+
has_rdoc:
|