coactive 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: caf295bc360ec4f4551be981b1233660a33406714b2627d1d7c3118cfde42ba1
4
- data.tar.gz: 55a5254e390a82bf22188fb8d84253d2382e52360abc2a36a007ef129b74572f
3
+ metadata.gz: 0e5b954d90120e156df60ee60c5c271cd7e8666bc507018c6814a5594f62e21b
4
+ data.tar.gz: 1923a89bba5c5b58c8be13f052ef902e2fb8744bccc6fe513bc3f0d84d70a02c
5
5
  SHA512:
6
- metadata.gz: 477b7ff382d1697943a0898ac2d8703aaa98fde5088e1f88c6e6a05f7cdee08d4071914d5a8308103ec0dd7a553df777a5d0382bf088db44bdf0d2e5f80c9b7c
7
- data.tar.gz: 6c038fdee9aed452ac716abd2d6f29149164c57e0db32777fde17bad46652f25ba1ad34c86cad1139e90c8e41911cdae46428df9572e9b80efb783afafe815a1
6
+ metadata.gz: e6b0e3585803ebfe054851c4f55db0276e4544f0eeb169375d20e9901126377a804e3e56e10b836092b7fcab41b1dd025ecc5cfc0f9fac2ec7743c757bdd4efc
7
+ data.tar.gz: 4dc336fd5a76d3be0c303febe8d8a05d3b0dcfc4dc6ad2d6dbbcb977286c73e1e24a8a203212cb60fa051ceb8d1a8445ad055f83c01efbfe34407a681683bc8f
@@ -4,21 +4,29 @@ on: [push, pull_request]
4
4
 
5
5
  jobs:
6
6
  test:
7
- runs-on: ubuntu-18.04
7
+ runs-on: ubuntu-20.04
8
8
  strategy:
9
9
  fail-fast: false
10
10
  matrix:
11
- ruby: [2.3, 2.4, 2.5, 2.6, 2.7, 3.0]
12
- gemfile: ['rails50', 'rails51', 'rails52', 'rails60', 'rails61']
11
+ ruby: [2.3, 2.4, 2.5, 2.6, 2.7, '3.0']
12
+ gemfile: ['rails50', 'rails51', 'rails52', 'rails60', 'rails61', 'rails70']
13
13
  exclude:
14
14
  - ruby: 2.3
15
15
  gemfile: rails60
16
16
  - ruby: 2.3
17
17
  gemfile: rails61
18
+ - ruby: 2.3
19
+ gemfile: rails70
18
20
  - ruby: 2.4
19
21
  gemfile: rails60
20
22
  - ruby: 2.4
21
23
  gemfile: rails61
24
+ - ruby: 2.4
25
+ gemfile: rails70
26
+ - ruby: 2.5
27
+ gemfile: rails70
28
+ - ruby: 2.6
29
+ gemfile: rails70
22
30
  - ruby: 3.0
23
31
  gemfile: rails50
24
32
  - ruby: 3.0
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  .bundle/
2
2
  Gemfile.lock
3
3
  coverage/
4
+ gemfiles/*.lock
4
5
  pkg/
5
6
  tmp/
6
7
  spec/dummy/db/*.sqlite3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 1.0.0
3
+ ## 0.2.1
4
+
5
+ * Truncate string for context.
6
+
7
+ ## 0.2.0
8
+
9
+ * Add context feature.
10
+ * Add priority to coaction.
11
+
12
+ ## 0.1.2
13
+
14
+ * Clear lookup cache when reloaded.
15
+ * Use require_dependency instead of require.
16
+
17
+ ## 0.1.1
18
+
19
+ * Reassign config data when configured.
20
+
21
+ ## 0.1.0
4
22
 
5
23
  * First release.
data/README.md CHANGED
@@ -21,6 +21,8 @@ Then execute:
21
21
 
22
22
  ## Usage
23
23
 
24
+ ### Coactors
25
+
24
26
  Include `Coactive::Base` to your base class:
25
27
 
26
28
  ```ruby
@@ -51,7 +53,7 @@ C.new.coactors
51
53
  # => [A, B]
52
54
  ```
53
55
 
54
- ### Named coactors
56
+ #### Named coactors
55
57
 
56
58
  You can also define coactive classes by using specific name:
57
59
 
@@ -88,30 +90,30 @@ class Base
88
90
  end
89
91
  ```
90
92
 
91
- ### Object-based coactors
93
+ #### Object-based coactors
92
94
 
93
95
  You can also define coactive classes by using object:
94
96
 
95
97
  ```ruby
96
- class ModelA
98
+ class ItemA
97
99
  end
98
100
 
99
- class ModelB
101
+ class ItemB
100
102
  end
101
103
 
102
- class Base::ModelA < Base
104
+ class Base::ItemA < Base
103
105
  end
104
106
 
105
- class Base::ModelB < Base
107
+ class Base::ItemB < Base
106
108
  end
107
109
 
108
110
  class Base::C < Base
109
- coact ModelA
110
- coact ModelB
111
+ coact ItemA
112
+ coact ItemB
111
113
  end
112
114
 
113
115
  Base::C.new.coactors
114
- #=> [Base::ModelA, Base::ModelB]
116
+ #=> [Base::ItemA, Base::ItemB]
115
117
  ```
116
118
 
117
119
  Coactors are looked up from the namespace corresponding with caller classes.
@@ -130,7 +132,7 @@ class Base
130
132
  end
131
133
  ```
132
134
 
133
- ### Dynamic coactors
135
+ #### Dynamic coactors
134
136
 
135
137
  You can also dynamically lookup coactors by using block or instance method:
136
138
 
@@ -184,7 +186,7 @@ D.new('B').coactors
184
186
  #=> [B]
185
187
  ```
186
188
 
187
- ### Nested coactors
189
+ #### Nested coactors
188
190
 
189
191
  You can define nested coactors. For example:
190
192
 
@@ -212,6 +214,110 @@ C.new.coactors.map { |klass| [klass] + klass.new.coactors }.flatten
212
214
  #=> [A, NestedA, B, NestedB]
213
215
  ```
214
216
 
217
+ ### Context
218
+
219
+ You can define variables used in a coactor as a context by including `Coactive::Initializer`.
220
+ The variables are stored in `context` as follows:
221
+
222
+ ```ruby
223
+ class Base
224
+ include Coactive::Base
225
+ include Coactive::Initializer
226
+ end
227
+
228
+ class A < Base
229
+ context :input
230
+ end
231
+
232
+ coactor = A.new(input: 'something')
233
+ coactor.context.input
234
+ #=> something
235
+ ```
236
+
237
+ #### Required context
238
+
239
+ You can also define required context as follows:
240
+
241
+ ```ruby
242
+ class A < Base
243
+ context :input, required: true
244
+ end
245
+
246
+ A.new
247
+ #=> Coactive::MissingContextError (missing required context: input)
248
+ ```
249
+
250
+ #### Default value
251
+
252
+ You can also define default value as follows:
253
+
254
+ ```ruby
255
+ class A < Base
256
+ context :input, default: 'something'
257
+ end
258
+
259
+ coactor = A.new
260
+ coactor.context.input
261
+ #=> something
262
+ ```
263
+
264
+ ### Contextualizer
265
+
266
+ You can copy context variables to a coactor by calling `contextualize`:
267
+
268
+ ```ruby
269
+ class Base
270
+ include Coactive::Base
271
+ include Coactive::Initializer
272
+ include Coactive::Contextualizer
273
+ end
274
+
275
+ class A < Base
276
+ context :input
277
+ end
278
+
279
+ coactor = A.new(input: 'something')
280
+ coactor.contextualize
281
+ coactor.input
282
+ #=> something
283
+ coactor.instance_variable_get(:@input)
284
+ #=> something
285
+ ```
286
+
287
+ #### Output
288
+
289
+ You can also set context when finished `contextualize` block:
290
+
291
+ ```ruby
292
+ class A < Base
293
+ context :result, output: true
294
+
295
+ def call
296
+ @result = 'something'
297
+ end
298
+ end
299
+
300
+ coactor = A.new
301
+ coactor.contextualize { coactor.call }
302
+ coactor.context.result
303
+ #=> something
304
+ ```
305
+
306
+ #### Output return value
307
+
308
+ You can also set context from return value of `contextualize` block:
309
+
310
+ ```ruby
311
+ class A < Base
312
+ context :result, output: :return
313
+ end
314
+
315
+ coactor = A.new
316
+ coactor.contextualize { 'return value' }
317
+ coactor.context.result
318
+ #=> return value
319
+ ```
320
+
215
321
  ### Configuration
216
322
 
217
323
  You can set configurations in your base class as follows:
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "rails", "~> 7.0.0"
4
+
5
+ gemspec path: "../"
data/lib/coactive/base.rb CHANGED
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'configure'
4
- require_relative 'coact'
5
- require_relative 'coaction'
6
- require_relative 'coactors'
7
- require_relative 'loader'
4
+ require_relative 'coactor'
5
+ require_relative 'interface'
6
+ require_relative 'errors'
8
7
 
9
8
  module Coactive
10
9
  module Base
@@ -12,9 +11,7 @@ module Coactive
12
11
 
13
12
  included do
14
13
  include Configure
15
- include Coact
16
- include Coaction
17
- include Coactors
14
+ include Coactor
18
15
  end
19
16
  end
20
17
  end
@@ -1,10 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'loader'
3
4
  require_relative 'lookup'
5
+ require_relative 'coactors/coactants'
6
+ require_relative 'coactors/coactions'
4
7
 
5
8
  module Coactive
6
- module Coactors
9
+ module Coactor
7
10
  extend ActiveSupport::Concern
11
+ include Coactors::Coactants
12
+ include Coactors::Coactions
8
13
 
9
14
  def coactors
10
15
  self.class._coactants.map do |coactant|
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coactive
4
+ module Coactors
5
+ module Coactants
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ class_attribute :_coactants
10
+ self._coactants = []
11
+ end
12
+
13
+ class_methods do
14
+ def coact(*coactants, **options, &block)
15
+ if block
16
+ self._coactants = _coactants + [block]
17
+ elsif options[:before]
18
+ index = self._coactants.index { |coactant| coactant == options[:before] }
19
+ self._coactants = self._coactants.insert(index, *coactants)
20
+ else
21
+ self._coactants = _coactants + coactants
22
+ end
23
+ end
24
+
25
+ def coactants
26
+ self._coactants
27
+ end
28
+
29
+ def clear_coactants
30
+ self._coactants = []
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coactive
4
+ module Coactors
5
+ class Coaction < Struct.new(:name, :options)
6
+ def priority
7
+ options[:priority]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'coaction'
4
+
5
+ module Coactive
6
+ module Coactors
7
+ module Coactions
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ class_attribute :_coactions
12
+ self._coactions = []
13
+ end
14
+
15
+ class_methods do
16
+ def coaction(*names, **options)
17
+ self._coactions = _coactions + names.map { |name| Coaction.new(name, options) }
18
+ end
19
+
20
+ def coactions
21
+ self._coactions
22
+ end
23
+
24
+ def clear_coactions
25
+ self._coactions = []
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -11,8 +11,13 @@ module Coactive
11
11
  lookup_superclass_until: ['ActiveRecord::Base', 'ActiveModel::Base'],
12
12
  }
13
13
 
14
- def initialize
14
+ attr_accessor :data
15
+
16
+ def initialize(attrs = {})
15
17
  @data = DEFAULTS.deep_dup
18
+ attrs.each do |key, value|
19
+ send("#{key}=", value)
20
+ end
16
21
  end
17
22
 
18
23
  DEFAULTS.keys.each do |key|
@@ -14,6 +14,7 @@ module Coactive
14
14
 
15
15
  class_methods do
16
16
  def configure_coactive
17
+ self.coactive_config = Config.new(coactive_config.data)
17
18
  yield coactive_config
18
19
  end
19
20
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coactive
4
+ class Context
5
+ attr_reader :_data
6
+
7
+ def initialize(data = {}, &block)
8
+ data = data.to_h if data.respond_to?(:to_h)
9
+ @_data = data
10
+ end
11
+
12
+ def [](key)
13
+ @_data[key]
14
+ end
15
+
16
+ def []=(key, value)
17
+ @_data[key] = value
18
+ end
19
+
20
+ def key?(key)
21
+ @_data.key?(key)
22
+ end
23
+
24
+ def to_h
25
+ @_data
26
+ end
27
+
28
+ def to_s
29
+ attrs = @_data.map { |k, v| "#{k}=#{v.to_s.truncate(300)}" }.join(', ')
30
+ "#<#{self.class} #{attrs}>"
31
+ end
32
+
33
+ def define_accessors!(keys)
34
+ Array(keys).each do |key|
35
+ define_singleton_method key do
36
+ @_data[key]
37
+ end
38
+ define_singleton_method "#{key}=" do |value|
39
+ @_data[key] = value
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coactive
4
+ module Contextualizer
5
+ extend ActiveSupport::Concern
6
+
7
+ def contextualize
8
+ self.class._contexts.each do |var|
9
+ instance_variable_set("@#{var.name}", @context[var.name])
10
+ define_singleton_method var.name do
11
+ instance_variable_get("@#{var.name}")
12
+ end
13
+ end
14
+
15
+ return_value = yield if block_given?
16
+
17
+ self.class._contexts.each do |var|
18
+ if var.output_return?
19
+ @context[var.name] = return_value
20
+ elsif var.output? && instance_variable_defined?("@#{var.name}")
21
+ @context[var.name] = instance_variable_get("@#{var.name}")
22
+ end
23
+ end
24
+
25
+ return_value
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coactive
4
+ class MissingContextError < StandardError
5
+ end
6
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'context'
4
+ require_relative 'initializers/contexts'
5
+
6
+ module Coactive
7
+ module Initializer
8
+ extend ActiveSupport::Concern
9
+ include Initializers::Contexts
10
+
11
+ included do
12
+ class_attribute :context_class
13
+ self.context_class = Context
14
+ attr_reader :context
15
+ end
16
+
17
+ def initialize(args = {}, &block)
18
+ @context = self.class.context_class.new(args, &block)
19
+ @context.define_accessors!(self.class._contexts.map(&:name))
20
+
21
+ self.class._contexts.each do |var|
22
+ if var.required? && !@context.key?(var.name)
23
+ raise MissingContextError.new("missing required context: #{var.name}")
24
+ end
25
+ if var.default && !@context.key?(var.name)
26
+ @context[var.name] = Initializer.resolve(self, var.default)
27
+ end
28
+ end
29
+ end
30
+
31
+ class << self
32
+ def resolve(instance, value)
33
+ if value.respond_to?(:call)
34
+ instance.instance_exec(&value)
35
+ elsif value.is_a?(Symbol) && instance.respond_to?(value, true)
36
+ instance.send(value)
37
+ else
38
+ value.deep_dup
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'variable'
4
+
5
+ module Coactive
6
+ module Initializers
7
+ module Contexts
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ class_attribute :_contexts
12
+ self._contexts = []
13
+ end
14
+
15
+ class_methods do
16
+ def context(*names, **options)
17
+ self._contexts = self._contexts + names.map { |name| Variable.new(name, options) }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coactive
4
+ module Initializers
5
+ class Variable < Struct.new(:name, :options)
6
+ def default
7
+ options[:default] if options
8
+ end
9
+
10
+ def required?
11
+ options[:required] if options
12
+ end
13
+
14
+ def output?
15
+ options[:output] if options
16
+ end
17
+
18
+ def output_return?
19
+ options[:output] == :return if options
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'initializer'
4
+ require_relative 'contextualizer'
5
+
6
+ module Coactive
7
+ module Interface
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ include Initializer
12
+ include Contextualizer
13
+ end
14
+ end
15
+ end
@@ -11,7 +11,7 @@ module Coactive
11
11
  engines = [Rails] + Rails::Engine.subclasses.map(&:instance)
12
12
  engines.each do |engine|
13
13
  Dir["#{engine.root}/{#{Array(paths).join(',')}}/**/*.rb"].each do |file|
14
- require file
14
+ require_dependency file
15
15
  end
16
16
  end
17
17
  end
@@ -13,19 +13,19 @@ module Coactive
13
13
  class_attribute :cache
14
14
  self.cache = {}
15
15
 
16
- def call(klass, coactivation)
17
- with_cache(klass, coactivation) do
18
- lookup = lookups.detect { |lookup| lookup.callable?(coactivation) }
19
- lookup.new(klass, coactivation).call if lookup
16
+ def call(klass, coactant)
17
+ with_cache(klass, coactant) do
18
+ lookup = lookups.detect { |lookup| lookup.callable?(coactant) }
19
+ lookup.new(klass, coactant).call if lookup
20
20
  end
21
21
  end
22
22
 
23
23
  private
24
24
 
25
- def with_cache(klass, coactivation)
25
+ def with_cache(klass, coactant)
26
26
  if klass.coactive_config.use_cache
27
27
  self.cache[klass] ||= {}
28
- self.cache[klass][coactivation] ||= yield
28
+ self.cache[klass][coactant] ||= yield
29
29
  else
30
30
  yield
31
31
  end
@@ -15,9 +15,10 @@ module Coactive
15
15
  end
16
16
 
17
17
  def lookup
18
- @klass.coactive_config.base_class.descendants.select do |coactor|
19
- coactor._coactions.any? { |coaction| coaction == @coactant }
20
- end
18
+ @klass.coactive_config.base_class.descendants.each_with_object({}).with_index do |(coactor, hash), i|
19
+ coaction = coactor.coactions.detect { |coaction| coaction.name == @coactant }
20
+ hash[[coaction.priority || 1 << 63, i]] = coactor if coaction
21
+ end.sort.map { |x| x[1] }
21
22
  end
22
23
 
23
24
  class << self
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coactive
4
+ module Railtie
5
+ ActiveSupport::Reloader.to_prepare do
6
+ Coactive::Lookup.cache.clear
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Coactive
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.1'
5
5
  end
data/lib/coactive.rb CHANGED
@@ -2,3 +2,4 @@ require 'active_support'
2
2
 
3
3
  require 'coactive/version'
4
4
  require 'coactive/base'
5
+ require 'coactive/railtie' if defined?(Rails)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coactive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoshikazu Kaneta
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-28 00:00:00.000000000 Z
11
+ date: 2022-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -117,18 +117,28 @@ files:
117
117
  - gemfiles/rails52.gemfile
118
118
  - gemfiles/rails60.gemfile
119
119
  - gemfiles/rails61.gemfile
120
+ - gemfiles/rails70.gemfile
120
121
  - lib/coactive.rb
121
122
  - lib/coactive/base.rb
122
- - lib/coactive/coact.rb
123
- - lib/coactive/coaction.rb
124
- - lib/coactive/coactors.rb
123
+ - lib/coactive/coactor.rb
124
+ - lib/coactive/coactors/coactants.rb
125
+ - lib/coactive/coactors/coaction.rb
126
+ - lib/coactive/coactors/coactions.rb
125
127
  - lib/coactive/config.rb
126
128
  - lib/coactive/configure.rb
129
+ - lib/coactive/context.rb
130
+ - lib/coactive/contextualizer.rb
131
+ - lib/coactive/errors.rb
132
+ - lib/coactive/initializer.rb
133
+ - lib/coactive/initializers/contexts.rb
134
+ - lib/coactive/initializers/variable.rb
135
+ - lib/coactive/interface.rb
127
136
  - lib/coactive/loader.rb
128
137
  - lib/coactive/lookup.rb
129
138
  - lib/coactive/lookups/base.rb
130
139
  - lib/coactive/lookups/name.rb
131
140
  - lib/coactive/lookups/object.rb
141
+ - lib/coactive/railtie.rb
132
142
  - lib/coactive/version.rb
133
143
  homepage: https://github.com/kanety/coactive
134
144
  licenses: []
@@ -148,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
158
  - !ruby/object:Gem::Version
149
159
  version: '0'
150
160
  requirements: []
151
- rubygems_version: 3.1.2
161
+ rubygems_version: 3.1.6
152
162
  signing_key:
153
163
  specification_version: 4
154
164
  summary: Make classes coactive
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coactive
4
- module Coact
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- class_attribute :_coactants
9
- self._coactants = []
10
- end
11
-
12
- class_methods do
13
- def coact(*coactants, **options, &block)
14
- if block
15
- self._coactants = _coactants + [block]
16
- elsif options[:before]
17
- index = self._coactants.index { |coactant| coactant == options[:before] }
18
- self._coactants = self._coactants.insert(index, *coactants)
19
- else
20
- self._coactants = _coactants + coactants
21
- end
22
- end
23
-
24
- def coactants
25
- self._coactants
26
- end
27
-
28
- def clear_coactants
29
- self._coactants = []
30
- end
31
- end
32
- end
33
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coactive
4
- module Coaction
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- class_attribute :_coactions
9
- self._coactions = []
10
- end
11
-
12
- class_methods do
13
- def coaction(*coactions)
14
- self._coactions = _coactions + coactions
15
- end
16
-
17
- def coactions
18
- self._coactions
19
- end
20
-
21
- def clear_coactions
22
- self._coactions = []
23
- end
24
- end
25
- end
26
- end