callbacks_attachable 1.0.3 → 1.1.0

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: 841ea199caa6811569cc442f4bb49848cae85667
4
- data.tar.gz: 559a012545ba5b1721f0c603ff6abceda05920a7
3
+ metadata.gz: 2585bc2a52a1a090b2d8792ce16a1b2b674769d9
4
+ data.tar.gz: b9212eaecc4af017f087bdbc17e0083c1678e048
5
5
  SHA512:
6
- metadata.gz: 0446b729f4bebdff0e3b2c2c304dcc1c54a83807e59c296ed4eb7623fb4e31328a3c94d091154dd8f755618e1846fc98c5024cdfb079d53fd61b039234d7b718
7
- data.tar.gz: eed08c3f04df0b8a8c0908d5da139b6fdfaf814201dfbdd4bb2a481002e78be1c561cb8bdcd73f9d6a4028f9b84db07025f29b8c257709006aebb9674faaabd6
6
+ metadata.gz: 68601c07625b6fb386431b10bab77bae900a91d813aba44b50e7755a9c803e157cfd124d319d0dd133852a547ab3deaccd3e28bff38722a625c0d981329cf70c
7
+ data.tar.gz: 5caa67e516872ba4e4a46bacf92c77d954193517a4d5d062b59a05cbd2e230cc7e4603f1001a5e820470d8473b207c8b67dc56248dd15296850285add0890494
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015 Christopher Aue
3
+ Copyright (c) 2015, 2016 Christopher Aue
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # CallbacksAttachable
2
2
 
3
- Attach callbacks to every ruby object including this mixin. Trigger all
4
- callbacks attached under the same namespace and detach callback when you no
5
- longer need them.
3
+ Attach callbacks to a class and trigger them for all its instances or just one
4
+ particular instance. Additionally, instances can also have their own set of
5
+ individual callbacks.
6
6
 
7
7
  ## Installation
8
8
 
@@ -25,57 +25,54 @@ Or install it yourself as:
25
25
  ```ruby
26
26
  require 'callbacks_attachable'
27
27
 
28
- class CallbacksHolder
28
+ class AClass
29
29
  include CallbacksAttachable
30
30
  end
31
31
  ```
32
32
 
33
33
  ### Callbacks attached to the class
34
34
 
35
- Attach callbacks to the class:
35
+ Attach callbacks for an event to the class with:
36
36
 
37
37
  ```ruby
38
- callback = CallbacksHolder.on(:event) do |method|
38
+ callback = AClass.on(:event) do |method|
39
39
  puts self.__send__(method)
40
40
  end
41
41
  ```
42
42
 
43
- Callbacks attached to the class are executed in the context of it, i.e. `self`
44
- points to the class.
45
-
46
- Trigger all `:event` callbacks with:
43
+ Callbacks attached to a class are executed in the context of each existing
44
+ instance. To trigger all `:event` callbacks for all instances of `AClass`, use:
47
45
 
48
46
  ```ruby
49
- CallbacksHolder.trigger(:event, :name) # => puts 'CallbacksHolder'
47
+ AClass.trigger(:event, :name) # => puts 'AClass'
50
48
  ```
51
49
 
52
- The second and further arguments given to `.trigger` are passed down to the
53
- callback.
50
+ The second and other arguments given to `.trigger` are passed to the callback.
54
51
 
55
- Callbacks can be executed in the context of a different context by passing the
56
- `context` option to `.trigger`:
52
+ Callbacks attached to a class can also be triggered for just one of its
53
+ instances with `.trigger_for`:
57
54
 
58
55
  ```ruby
59
- object = Object.new
60
- CallbacksHolder.trigger(:event, :__id__, context: object)
61
- # => puts the result of object.__id__
56
+ an_instance = AClass.new
57
+ AClass.trigger_for(an_instance, :event, :__id__)
58
+ # => puts the result of an_instance.__id__
62
59
  ```
63
60
 
64
- To detach a callback call `.off` with the event namespace and the callback
65
- handle returned by `.on`:
61
+ To detach a callback call `.off` with the event's name and the callback handle
62
+ returned by `.on`:
66
63
 
67
64
  ```ruby
68
- CallbacksHolder.off(:event, callback)
69
- CallbacksHolder.trigger(:event, :name) # => nothing will happen
65
+ callback = AClass.on(:event) { do_something }
66
+ AClass.off(:event, callback)
70
67
  ```
71
68
 
72
69
  If you want to execute a callback just a single time attach it with `.once_on`:
73
70
 
74
71
  ```ruby
75
- CallbacksHolder.once_on(:singularity) { puts 'callback called!' }
76
- CallbacksHolder.trigger(:singularity) # => puts 'callback called!' and immediately
72
+ AClass.once_on(:singularity) { puts 'callback called!' }
73
+ AClass.trigger(:singularity) # => puts 'callback called!' and immediately
77
74
  # detaches the callback
78
- CallbacksHolder.trigger(:singularity) # => does nothing
75
+ AClass.trigger(:singularity) # => does nothing
79
76
  ```
80
77
 
81
78
  To detach a callback when a condition is met use `.until_true_on`. The callback
@@ -83,43 +80,42 @@ will be detached if it has a truthy (!) return value.
83
80
 
84
81
  ```ruby
85
82
  counter = 0
86
- CallbacksHolder.until_true_on(:count_to_two) do
83
+ AClass.until_true_on(:count_to_two) do
87
84
  puts counter
88
85
  counter >= 2
89
86
  end
90
87
 
91
- CallbacksHolder.trigger(:count_to_two) # => puts 0
92
- CallbacksHolder.trigger(:count_to_two) # => puts 1
93
- CallbacksHolder.trigger(:count_to_two) # => puts 2 and detaches the callback
94
- CallbacksHolder.trigger(:count_to_two) # => does nothing
88
+ AClass.trigger(:count_to_two) # => puts 0
89
+ AClass.trigger(:count_to_two) # => puts 1
90
+ AClass.trigger(:count_to_two) # => puts 2 and detaches the callback
91
+ AClass.trigger(:count_to_two) # => does nothing
95
92
  ```
96
93
 
97
94
  ### Callbacks attached to an instance
98
95
 
99
96
  All above mentioned methods on the class level also exist for each instance of
100
- the class. Callbacks are executed if the instance they are attached to or their
101
- class calls `#trigger`.
97
+ the class. Callbacks for an individual instance are executed by calling
98
+ `#trigger` on it. They are also called, when calling `.trigger` or
99
+ `.trigger_for(instance, ...)` on its class.
102
100
 
103
- Callbacks are called in their lexical scope. So, `self` inside and outside
104
- the callback is the same object. The context of a callback cannot be changed
105
- with the `context` option of the `#trigger` method as it is possible for
106
- class callbacks.
101
+ Callbacks attached to individual instances are evaluated in their lexical scope.
102
+ So, `self` inside and outside the callback is the same object.
107
103
 
108
104
  ```ruby
109
- callbacks_holder1 = CallbacksHolder.new
110
- callbacks_holder2 = CallbacksHolder.new
105
+ an_instance1 = AClass.new
106
+ an_instance2 = AClass.new
111
107
 
112
- callback1 = callbacks_holder1.on(:event) { puts 'This is #1!' }
113
- callback2 = callbacks_holder2.on(:event) { puts 'This is #2!' }
108
+ callback1 = an_instance1.on(:event) { puts 'This is #1!' }
109
+ callback2 = an_instance2.on(:event) { puts 'This is #2!' }
114
110
 
115
- callbacks_holder1.trigger(:event) # => puts 'This is #1!'
116
- callbacks_holder2.trigger(:event) # => puts 'This is #2!'
111
+ an_instance1.trigger(:event) # => puts 'This is #1!'
112
+ an_instance2.trigger(:event) # => puts 'This is #2!'
117
113
 
118
- CallbacksHolder.trigger(:event) # => puts 'This is #1!' and 'This is #2!'
114
+ AClass.trigger(:event) # => puts 'This is #1!' and 'This is #2!'
119
115
 
120
- callbacks_holder1.off(:event, callback)
121
- callbacks_holder2.off(:event, callback)
116
+ an_instance1.off(:event, callback)
117
+ an_instance2.off(:event, callback)
122
118
  ```
123
119
 
124
120
  The two methods `#once_on` and `#until_true_on` are available for instances,
125
- too, and work as you'd expect.
121
+ too. They work as you'd expect.
@@ -1,17 +1,20 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'callbacks_attachable/version'
2
+ require_relative 'mrblib/version'
5
3
 
6
4
  Gem::Specification.new do |spec|
7
5
  spec.name = "callbacks_attachable"
8
6
  spec.version = CallbacksAttachable::VERSION
9
- spec.authors = ["Christopher Aue"]
10
- spec.email = ["mail@christopheraue.net"]
7
+ spec.summary = %q{Attach callbacks to classes or individual instances.}
8
+ spec.description = <<-DESC
9
+ Attach callbacks to a class and trigger them for all its instances or just one
10
+ particular instance. Additionally, instances can also have their own set of
11
+ individual callbacks.
12
+ DESC
11
13
 
12
- spec.summary = %q{Attach callbacks to ruby objects. Then, trigger and detach them.}
13
14
  spec.homepage = "https://github.com/christopheraue/ruby-callbacks_attachable"
14
15
  spec.license = "MIT"
16
+ spec.authors = ["Christopher Aue"]
17
+ spec.email = "rubygems@christopheraue.net"
15
18
 
16
19
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -20,6 +23,4 @@ Gem::Specification.new do |spec|
20
23
  spec.add_development_dependency "bundler", "~> 1.8"
21
24
  spec.add_development_dependency "rake", "~> 10.0"
22
25
  spec.add_development_dependency "rspec", "~> 3.4"
23
- spec.add_development_dependency "rspec-its"
24
- spec.add_development_dependency "rspec-mocks-matchers-send_message", "~> 0.3"
25
26
  end
@@ -1,64 +1,5 @@
1
- require "callbacks_attachable/version"
2
- require "callbacks_attachable/callback_handler"
3
- require "callbacks_attachable/instance_callback"
4
- require "callbacks_attachable/all_instances_callback"
5
-
6
- module CallbacksAttachable
7
- def self.included(klass)
8
- klass.extend ClassMethods
9
- end
10
-
11
- module ClassMethods
12
- def on(*args, &block)
13
- __callback_handler__.on(*args, &block)
14
- end
15
-
16
- def once_on(*args, &block)
17
- __callback_handler__.once_on(*args, &block)
18
- end
19
-
20
- def until_true_on(*args, &block)
21
- __callback_handler__.until_true_on(*args, &block)
22
- end
23
-
24
- def off(*args)
25
- __callback_handler__.off(*args)
26
- end
27
-
28
- def trigger(*args)
29
- __callback_handler__.trigger(*args)
30
- end
31
-
32
- private
33
-
34
- def __callback_handler__
35
- @__callback_handler__ ||= CallbackHandler.new(self, AllInstancesCallback)
36
- end
37
- end
38
-
39
- def on(*args, &block)
40
- __callback_handler__.on(*args, &block)
41
- end
42
-
43
- def once_on(*args, &block)
44
- __callback_handler__.once_on(*args, &block)
45
- end
46
-
47
- def until_true_on(*args, &block)
48
- __callback_handler__.until_true_on(*args, &block)
49
- end
50
-
51
- def off(*args)
52
- __callback_handler__.off(*args)
53
- end
54
-
55
- def trigger(*args)
56
- self.class.trigger(*args, instance: self) and __callback_handler__.trigger(*args)
57
- end
58
-
59
- private
60
-
61
- def __callback_handler__
62
- @__callback_handler__ ||= CallbackHandler.new(self, InstanceCallback)
63
- end
64
- end
1
+ require_relative "../mrblib/callbacks_attachable"
2
+ require_relative "../mrblib/version"
3
+ require_relative "../mrblib/callback_registry"
4
+ require_relative "../mrblib/instance_callback"
5
+ require_relative "../mrblib/all_instances_callback"
data/mrbgem.rake ADDED
@@ -0,0 +1,16 @@
1
+ require_relative 'mrblib/version'
2
+
3
+ MRuby::Gem::Specification.new('mruby-callbacks_attachable') do |spec|
4
+ spec.version = CallbacksAttachable::VERSION
5
+ spec.summary = %q{Attach callbacks to classes or individual instances.}
6
+ spec.description = <<-DESC
7
+ Attach callbacks to a class and trigger them for all its instances or just one
8
+ particular instance. Additionally, instances can also have their own set of
9
+ individual callbacks.
10
+ DESC
11
+ spec.homepage = "https://github.com/christopheraue/ruby-callbacks_attachable"
12
+ spec.license = 'MIT'
13
+ spec.authors = ['Christopher Aue']
14
+
15
+ spec.add_dependency 'mruby-objectspace', :core => 'mruby-objectspace'
16
+ end
@@ -1,21 +1,13 @@
1
1
  module CallbacksAttachable
2
2
  class AllInstancesCallback
3
- def initialize(klass, skip: 0, &callback)
3
+ def initialize(klass, opts = {}, &callback)
4
4
  @class = klass
5
- @skip = skip
5
+ @skip = opts.fetch(:skip, 0)
6
6
  @callback = callback
7
7
  @call_counts = {}
8
8
  end
9
9
 
10
- def call(*args, **opts)
11
- if instance = opts[:instance]
12
- call_for_instance(instance, *args)
13
- else
14
- ObjectSpace.each_object(@class).all?{ |inst| call_for_instance(inst, *args) }
15
- end
16
- end
17
-
18
- def call_for_instance(instance, *args)
10
+ def call(instance, args)
19
11
  @call_counts[instance.__id__] = @call_counts[instance.__id__].to_i + 1
20
12
  return true if @call_counts[instance.__id__] <= @skip
21
13
  false != instance.instance_exec(*args, &@callback)
@@ -1,13 +1,13 @@
1
1
  module CallbacksAttachable
2
- class CallbackHandler
2
+ class CallbackRegistry
3
3
  def initialize(object, callback_class)
4
4
  @object = object
5
5
  @callback_class = callback_class
6
6
  end
7
7
 
8
- def on(event, skip: 0, &callback)
8
+ def on(event, opts = {}, &callback)
9
9
  __callbacks__[event] ||= []
10
- __callbacks__[event] << @callback_class.new(@object, skip: skip, &callback)
10
+ __callbacks__[event] << @callback_class.new(@object, opts, &callback)
11
11
  __callbacks__[event].last
12
12
  end
13
13
 
@@ -28,12 +28,12 @@ module CallbacksAttachable
28
28
  end
29
29
  end
30
30
 
31
- def trigger(event, *args, **opts)
31
+ def trigger(instance, event, args)
32
32
  return true if __callbacks__[event].nil?
33
33
 
34
34
  # dup the callback list so that removing callbacks while iterating does
35
35
  # still call all callbacks during map.
36
- __callbacks__[event].dup.all?{ |callback| callback.call(*args, **opts) }
36
+ __callbacks__[event].dup.all?{ |callback| callback.call(instance, args) }
37
37
  end
38
38
 
39
39
  def off(event, callback)
@@ -0,0 +1,59 @@
1
+ module CallbacksAttachable
2
+ def self.included(klass)
3
+ klass.extend ClassMethods
4
+ end
5
+
6
+ module ClassMethods
7
+ def on(*args, &block)
8
+ __callback_registry__.on(*args, &block)
9
+ end
10
+
11
+ def once_on(*args, &block)
12
+ __callback_registry__.once_on(*args, &block)
13
+ end
14
+
15
+ def until_true_on(*args, &block)
16
+ __callback_registry__.until_true_on(*args, &block)
17
+ end
18
+
19
+ def off(*args)
20
+ __callback_registry__.off(*args)
21
+ end
22
+
23
+ def trigger(event, *args)
24
+ ObjectSpace.each_object(self).all?{ |inst| inst.trigger(event, *args) }
25
+ end
26
+
27
+ private
28
+
29
+ def __callback_registry__
30
+ @__callback_registry__ ||= CallbackRegistry.new(self, AllInstancesCallback)
31
+ end
32
+ end
33
+
34
+ def on(*args, &block)
35
+ __callback_registry__.on(*args, &block)
36
+ end
37
+
38
+ def once_on(*args, &block)
39
+ __callback_registry__.once_on(*args, &block)
40
+ end
41
+
42
+ def until_true_on(*args, &block)
43
+ __callback_registry__.until_true_on(*args, &block)
44
+ end
45
+
46
+ def off(*args)
47
+ __callback_registry__.off(*args)
48
+ end
49
+
50
+ def trigger(event, *args)
51
+ self.class.__send__(:__callback_registry__).trigger(self, event, args) and __callback_registry__.trigger(self, event, args)
52
+ end
53
+
54
+ private
55
+
56
+ def __callback_registry__
57
+ @__callback_registry__ ||= CallbackRegistry.new(self, InstanceCallback)
58
+ end
59
+ end
@@ -1,13 +1,13 @@
1
1
  module CallbacksAttachable
2
2
  class InstanceCallback
3
- def initialize(instance, skip: 0, &callback)
3
+ def initialize(instance, opts = {}, &callback)
4
4
  @instance = instance
5
- @skip = skip
5
+ @skip = opts.fetch(:skip, 0)
6
6
  @callback = callback
7
7
  @call_count = 0
8
8
  end
9
9
 
10
- def call(*args, **opts)
10
+ def call(instance, args)
11
11
  @call_count += 1
12
12
  return true if @call_count <= @skip
13
13
  @callback.call(*args) != false
@@ -1,3 +1,3 @@
1
1
  module CallbacksAttachable
2
- VERSION = "1.0.3"
2
+ VERSION = "1.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: callbacks_attachable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Aue
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-10 00:00:00.000000000 Z
11
+ date: 2016-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,37 +52,11 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.4'
55
- - !ruby/object:Gem::Dependency
56
- name: rspec-its
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rspec-mocks-matchers-send_message
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '0.3'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '0.3'
83
- description:
84
- email:
85
- - mail@christopheraue.net
55
+ description: |
56
+ Attach callbacks to a class and trigger them for all its instances or just one
57
+ particular instance. Additionally, instances can also have their own set of
58
+ individual callbacks.
59
+ email: rubygems@christopheraue.net
86
60
  executables: []
87
61
  extensions: []
88
62
  extra_rdoc_files: []
@@ -92,13 +66,14 @@ files:
92
66
  - Gemfile
93
67
  - LICENSE.txt
94
68
  - README.md
95
- - Rakefile
96
69
  - callbacks_attachable.gemspec
97
70
  - lib/callbacks_attachable.rb
98
- - lib/callbacks_attachable/all_instances_callback.rb
99
- - lib/callbacks_attachable/callback_handler.rb
100
- - lib/callbacks_attachable/instance_callback.rb
101
- - lib/callbacks_attachable/version.rb
71
+ - mrbgem.rake
72
+ - mrblib/all_instances_callback.rb
73
+ - mrblib/callback_registry.rb
74
+ - mrblib/callbacks_attachable.rb
75
+ - mrblib/instance_callback.rb
76
+ - mrblib/version.rb
102
77
  homepage: https://github.com/christopheraue/ruby-callbacks_attachable
103
78
  licenses:
104
79
  - MIT
@@ -119,8 +94,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
94
  version: '0'
120
95
  requirements: []
121
96
  rubyforge_project:
122
- rubygems_version: 2.4.5.1
97
+ rubygems_version: 2.5.1
123
98
  signing_key:
124
99
  specification_version: 4
125
- summary: Attach callbacks to ruby objects. Then, trigger and detach them.
100
+ summary: Attach callbacks to classes or individual instances.
126
101
  test_files: []
102
+ has_rdoc:
data/Rakefile DELETED
@@ -1,2 +0,0 @@
1
- require "bundler/gem_tasks"
2
-