rails_core_extensions 0.12.0 → 0.13.2
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 +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/rails_core_extensions/action_controller_sortable.rb +1 -3
- data/lib/rails_core_extensions/action_view_has_many_extensions.rb +4 -2
- data/lib/rails_core_extensions/active_model_extensions.rb +1 -3
- data/lib/rails_core_extensions/active_record_cloning.rb +1 -3
- data/lib/rails_core_extensions/active_record_extensions.rb +1 -3
- data/lib/rails_core_extensions/active_record_liquid_extensions.rb +20 -22
- data/lib/rails_core_extensions/translations.rb +1 -3
- data/lib/rails_core_extensions/version.rb +1 -1
- data/lib/rails_core_extensions.rb +15 -11
- data/spec/support/coverage_loader.rb +1 -1
- metadata +2 -6
- data/lib/rails_core_extensions/active_support_concern.rb +0 -134
- data/lib/rails_core_extensions/concurrency.rb +0 -152
- data/spec/concurrency_spec.rb +0 -110
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9a3bc99415c6959119365c5b542dc8ae3c912d004d7a4ae809755c7eeaccc44
|
4
|
+
data.tar.gz: 3a3db36a2823a7116674253ede3efe09222829285e038561de663b33bf8b9671
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b02c74b69ba727097ecea9edbba9db615c517ac15f9573c12770f0ce9893bb31d5beaa8701e259854db15fe41f7f3b49fc269784fabdcf3d51a7c6d0243aec2
|
7
|
+
data.tar.gz: deeab7f200cd2439ea720c4c2338dd82d9feb370be4d650bd25675d6cab826c6701e95bdc716f133740a95a083e06d07d977d5c7a7510049a6184ff4a2a10f63
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.13.2
|
4
|
+
|
5
|
+
- [PLAT-390] Fix broken `action_view` extensions
|
6
|
+
|
7
|
+
## 0.13.1
|
8
|
+
|
9
|
+
- [PLAT-384] Fix the liquid extension
|
10
|
+
|
11
|
+
## 0.13.0
|
12
|
+
|
13
|
+
- [PLAT-378] Improve bundler startup time; Drop Concurrency
|
14
|
+
|
3
15
|
## 0.12.0
|
4
16
|
|
5
17
|
- [PLAT-183] Ruby 3.1, Rails 7.0 and publish coverage with github action
|
@@ -28,5 +28,7 @@ module RailsCoreExtensions
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
ActionView::
|
31
|
+
ActiveSupport.on_load :action_view do
|
32
|
+
ActionView::Base.send(:include, RailsCoreExtensions::HasManyExtensions::Tags)
|
33
|
+
ActionView::Helpers::FormBuilder.send(:include, RailsCoreExtensions::HasManyExtensions::FormBuilder)
|
34
|
+
end
|
@@ -1,32 +1,30 @@
|
|
1
1
|
module RailsCoreExtensions
|
2
2
|
module ActiveRecordLiquidExtensions
|
3
|
-
|
4
|
-
base.extend ClassMethods
|
5
|
-
end
|
6
|
-
end
|
3
|
+
extend ActiveSupport::Concern
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
module ClassMethods
|
6
|
+
def validates_liquid(field)
|
7
|
+
field = field.to_sym
|
8
|
+
before_validation do |record|
|
9
|
+
begin
|
10
|
+
Liquid::Template.parse(record.send(field), error_mode: :strict)
|
11
|
+
rescue Liquid::SyntaxError => e
|
12
|
+
record.errors.add(field, "Liquid Syntax Error: #{e}")
|
13
|
+
end
|
16
14
|
end
|
17
15
|
end
|
18
|
-
end
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
def liquid_field(field)
|
18
|
+
class_eval <<-CODE
|
19
|
+
def parsed_#{field}
|
20
|
+
Liquid::Template.parse(#{field})
|
21
|
+
end
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
def render_#{field}(*args)
|
24
|
+
parsed_#{field}.render!(*args)
|
25
|
+
end
|
26
|
+
CODE
|
27
|
+
end
|
30
28
|
end
|
31
29
|
end
|
32
30
|
end
|
@@ -3,8 +3,6 @@ module RailsCoreExtensions
|
|
3
3
|
require 'rails_core_extensions/position_initializer'
|
4
4
|
require 'rails_core_extensions/time_with_zone'
|
5
5
|
require 'rails_core_extensions/transfer_records'
|
6
|
-
require 'rails_core_extensions/active_support_concern'
|
7
|
-
require 'rails_core_extensions/concurrency'
|
8
6
|
|
9
7
|
require 'rails_core_extensions/railtie' if defined?(Rails)
|
10
8
|
|
@@ -12,15 +10,19 @@ module RailsCoreExtensions
|
|
12
10
|
require 'rails_core_extensions/activatable'
|
13
11
|
require 'rails_core_extensions/action_controller_sortable'
|
14
12
|
|
15
|
-
|
16
|
-
|
13
|
+
ActiveSupport.on_load(:action_controller) do
|
14
|
+
ActionController::Base.send(:include, Activatable)
|
15
|
+
ActionController::Base.send(:include, ActionControllerSortable)
|
16
|
+
end
|
17
17
|
end
|
18
18
|
|
19
19
|
if defined? ActionView
|
20
20
|
require 'rails_core_extensions/action_view_extensions'
|
21
21
|
require 'rails_core_extensions/action_view_has_many_extensions'
|
22
22
|
|
23
|
-
|
23
|
+
ActiveSupport.on_load(:action_view) do
|
24
|
+
ActionView::Base.send(:include, RailsCoreExtensions::ActionViewExtensions)
|
25
|
+
end
|
24
26
|
end
|
25
27
|
|
26
28
|
if defined? ActiveRecord
|
@@ -30,11 +32,13 @@ module RailsCoreExtensions
|
|
30
32
|
require 'rails_core_extensions/translations'
|
31
33
|
require 'rails_core_extensions/active_model_extensions'
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
ActiveSupport.on_load(:active_record) do
|
36
|
+
ActiveRecord::Base.send(:include, ActiveRecordCloning)
|
37
|
+
ActiveRecord::Base.send(:include, ActiveRecordExtensions)
|
38
|
+
ActiveRecord::Base.send(:include, RailsCoreExtensions::ActiveRecordLiquidExtensions)
|
39
|
+
ActiveRecord::Base.send(:include, ActiveRecordExtensions::InstanceMethods)
|
40
|
+
ActiveRecord::Base.send(:include, RailsCoreExtensions::Translations)
|
41
|
+
ActiveRecord::Base.send(:include, ActiveModelExtensions::Validations)
|
42
|
+
end
|
39
43
|
end
|
40
44
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_core_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Noack
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-07-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -167,8 +167,6 @@ files:
|
|
167
167
|
- lib/rails_core_extensions/active_record_cloning.rb
|
168
168
|
- lib/rails_core_extensions/active_record_extensions.rb
|
169
169
|
- lib/rails_core_extensions/active_record_liquid_extensions.rb
|
170
|
-
- lib/rails_core_extensions/active_support_concern.rb
|
171
|
-
- lib/rails_core_extensions/concurrency.rb
|
172
170
|
- lib/rails_core_extensions/position_initializer.rb
|
173
171
|
- lib/rails_core_extensions/railtie.rb
|
174
172
|
- lib/rails_core_extensions/sortable.rb
|
@@ -183,7 +181,6 @@ files:
|
|
183
181
|
- spec/active_model_extensions_spec.rb
|
184
182
|
- spec/active_record_cloning_spec.rb
|
185
183
|
- spec/active_record_extensions_spec.rb
|
186
|
-
- spec/concurrency_spec.rb
|
187
184
|
- spec/en.yml
|
188
185
|
- spec/position_initializer_spec.rb
|
189
186
|
- spec/schema.rb
|
@@ -221,7 +218,6 @@ test_files:
|
|
221
218
|
- spec/active_model_extensions_spec.rb
|
222
219
|
- spec/active_record_cloning_spec.rb
|
223
220
|
- spec/active_record_extensions_spec.rb
|
224
|
-
- spec/concurrency_spec.rb
|
225
221
|
- spec/en.yml
|
226
222
|
- spec/position_initializer_spec.rb
|
227
223
|
- spec/schema.rb
|
@@ -1,134 +0,0 @@
|
|
1
|
-
module ActiveSupport
|
2
|
-
# A typical module looks like this:
|
3
|
-
#
|
4
|
-
# module M
|
5
|
-
# def self.included(base)
|
6
|
-
# base.extend ClassMethods
|
7
|
-
# base.send(:include, InstanceMethods)
|
8
|
-
# scope :disabled, where(:disabled => true)
|
9
|
-
# end
|
10
|
-
#
|
11
|
-
# module ClassMethods
|
12
|
-
# ...
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# module InstanceMethods
|
16
|
-
# ...
|
17
|
-
# end
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be written as:
|
21
|
-
#
|
22
|
-
# require 'active_support/concern'
|
23
|
-
#
|
24
|
-
# module M
|
25
|
-
# extend ActiveSupport::Concern
|
26
|
-
#
|
27
|
-
# included do
|
28
|
-
# scope :disabled, where(:disabled => true)
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# module ClassMethods
|
32
|
-
# ...
|
33
|
-
# end
|
34
|
-
#
|
35
|
-
# module InstanceMethods
|
36
|
-
# ...
|
37
|
-
# end
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# Moreover, it gracefully handles module dependencies. Given a +Foo+ module and a +Bar+
|
41
|
-
# module which depends on the former, we would typically write the following:
|
42
|
-
#
|
43
|
-
# module Foo
|
44
|
-
# def self.included(base)
|
45
|
-
# base.class_eval do
|
46
|
-
# def self.method_injected_by_foo
|
47
|
-
# ...
|
48
|
-
# end
|
49
|
-
# end
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# module Bar
|
54
|
-
# def self.included(base)
|
55
|
-
# base.method_injected_by_foo
|
56
|
-
# end
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# class Host
|
60
|
-
# include Foo # We need to include this dependency for Bar
|
61
|
-
# include Bar # Bar is the module that Host really needs
|
62
|
-
# end
|
63
|
-
#
|
64
|
-
# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We could try to hide
|
65
|
-
# these from +Host+ directly including +Foo+ in +Bar+:
|
66
|
-
#
|
67
|
-
# module Bar
|
68
|
-
# include Foo
|
69
|
-
# def self.included(base)
|
70
|
-
# base.method_injected_by_foo
|
71
|
-
# end
|
72
|
-
# end
|
73
|
-
#
|
74
|
-
# class Host
|
75
|
-
# include Bar
|
76
|
-
# end
|
77
|
-
#
|
78
|
-
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt> is the +Bar+ module,
|
79
|
-
# not the +Host+ class. With <tt>ActiveSupport::Concern</tt>, module dependencies are properly resolved:
|
80
|
-
#
|
81
|
-
# require 'active_support/concern'
|
82
|
-
#
|
83
|
-
# module Foo
|
84
|
-
# extend ActiveSupport::Concern
|
85
|
-
# included do
|
86
|
-
# class_eval do
|
87
|
-
# def self.method_injected_by_foo
|
88
|
-
# ...
|
89
|
-
# end
|
90
|
-
# end
|
91
|
-
# end
|
92
|
-
# end
|
93
|
-
#
|
94
|
-
# module Bar
|
95
|
-
# extend ActiveSupport::Concern
|
96
|
-
# include Foo
|
97
|
-
#
|
98
|
-
# included do
|
99
|
-
# self.method_injected_by_foo
|
100
|
-
# end
|
101
|
-
# end
|
102
|
-
#
|
103
|
-
# class Host
|
104
|
-
# include Bar # works, Bar takes care now of its dependencies
|
105
|
-
# end
|
106
|
-
#
|
107
|
-
module Concern
|
108
|
-
def self.extended(base)
|
109
|
-
base.instance_variable_set("@_dependencies", [])
|
110
|
-
end
|
111
|
-
|
112
|
-
def append_features(base)
|
113
|
-
if base.instance_variable_defined?("@_dependencies")
|
114
|
-
base.instance_variable_get("@_dependencies") << self
|
115
|
-
return false
|
116
|
-
else
|
117
|
-
return false if base < self
|
118
|
-
@_dependencies.each { |dep| base.send(:include, dep) }
|
119
|
-
super
|
120
|
-
base.extend const_get("ClassMethods") if const_defined?("ClassMethods")
|
121
|
-
base.send :include, const_get("InstanceMethods") if const_defined?("InstanceMethods")
|
122
|
-
base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def included(base = nil, &block)
|
127
|
-
if base.nil?
|
128
|
-
@_included_block = block
|
129
|
-
else
|
130
|
-
super
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
@@ -1,152 +0,0 @@
|
|
1
|
-
module Concurrency
|
2
|
-
extend ActiveSupport::Concern
|
3
|
-
|
4
|
-
module ClassMethods
|
5
|
-
|
6
|
-
def concurrency_safe(*methods)
|
7
|
-
options = methods.extract_options!
|
8
|
-
methods.each do |method|
|
9
|
-
add_concurrency_check(method, options)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
|
14
|
-
def concurrency_safe_method_locked?(method)
|
15
|
-
concurrency_cache.read(concurrency_safe_method_cache_name(method)) == 'locked'
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
def concurrency_cache
|
20
|
-
@concurrency_cache ||= ::Rails.cache
|
21
|
-
end
|
22
|
-
|
23
|
-
|
24
|
-
def concurrency_cache=(cache)
|
25
|
-
[:read,:write,:delete].each do |method|
|
26
|
-
raise ConcurrencyCacheException, "#{cache} does not implement #{method}" unless cache.respond_to?(method)
|
27
|
-
end
|
28
|
-
@concurrency_cache = cache
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def add_concurrency_check(method, options = {})
|
35
|
-
method_definition = <<-DEFINITION
|
36
|
-
def #{method}_with_concurrency_lock(*args)
|
37
|
-
if concurrency_safe_method_locked?(:#{method})
|
38
|
-
raise ConcurrentCallException.new(self,:#{method}), "#{self.name}.#{method} is already running"
|
39
|
-
end
|
40
|
-
lock_concurrency_safe_method(:#{method})
|
41
|
-
return_value = nil
|
42
|
-
begin
|
43
|
-
return_value = #{method}_without_concurrency_lock(*args)
|
44
|
-
ensure
|
45
|
-
unlock_concurrency_safe_method(:#{method})
|
46
|
-
end
|
47
|
-
return_value
|
48
|
-
end
|
49
|
-
alias_method :#{method}_without_concurrency_lock, :#{method}
|
50
|
-
alias_method :#{method}, :#{method}_with_concurrency_lock
|
51
|
-
DEFINITION
|
52
|
-
|
53
|
-
if method_type(method, options[:type]) == 'class'
|
54
|
-
method_definition = <<-DEFINITION
|
55
|
-
class << self
|
56
|
-
#{method_definition}
|
57
|
-
end
|
58
|
-
DEFINITION
|
59
|
-
end
|
60
|
-
|
61
|
-
module_eval method_definition
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
def lock_concurrency_safe_method(method)
|
66
|
-
concurrency_cache.write(concurrency_safe_method_cache_name(method), 'locked')
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
|
-
def unlock_concurrency_safe_method(method)
|
71
|
-
concurrency_cache.delete(concurrency_safe_method_cache_name(method))
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
def concurrency_safe_method_cache_name(method)
|
76
|
-
"#{self.name.underscore}_concurrency_safe_class_method_#{method}"
|
77
|
-
end
|
78
|
-
|
79
|
-
|
80
|
-
def method_type(method, type = nil)
|
81
|
-
types = method_types(method, type)
|
82
|
-
raise AmbiguousMethodException.new(self, method), "#{method} for #{self.name} is ambiguous. Please specify the type (instance/class) option" if types.count == 2
|
83
|
-
raise NoMethodException.new(self, method), "#{method} is not not a valid method for #{self.name}." if types.blank?
|
84
|
-
types.first
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
def method_types(method, type = nil)
|
89
|
-
['class', 'instance'].select do |mt|
|
90
|
-
(type.blank? || type.to_s == mt) && self.send("#{mt}_method?", method)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
|
95
|
-
def class_method?(method)
|
96
|
-
self.respond_to?(method, true)
|
97
|
-
end
|
98
|
-
|
99
|
-
|
100
|
-
def instance_method?(method)
|
101
|
-
(self.instance_methods + self.private_instance_methods).map(&:to_s).include?(method.to_s)
|
102
|
-
end
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
module InstanceMethods
|
108
|
-
|
109
|
-
def concurrency_cache
|
110
|
-
self.class.concurrency_cache
|
111
|
-
end
|
112
|
-
|
113
|
-
|
114
|
-
def concurrency_safe_method_locked?(method)
|
115
|
-
concurrency_cache.read(concurrency_safe_method_cache_name(method)) == 'locked'
|
116
|
-
end
|
117
|
-
|
118
|
-
|
119
|
-
private
|
120
|
-
|
121
|
-
def lock_concurrency_safe_method(method)
|
122
|
-
concurrency_cache.write(concurrency_safe_method_cache_name(method), 'locked')
|
123
|
-
end
|
124
|
-
|
125
|
-
|
126
|
-
def unlock_concurrency_safe_method(method)
|
127
|
-
concurrency_cache.delete(concurrency_safe_method_cache_name(method))
|
128
|
-
end
|
129
|
-
|
130
|
-
|
131
|
-
def concurrency_safe_method_cache_name(method)
|
132
|
-
"#{self.class.name.underscore}_concurrency_safe_instance_method_#{method}"
|
133
|
-
end
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
|
138
|
-
class ConcurrencyException < ::Exception; end
|
139
|
-
class ConcurrencyCacheException < ConcurrencyException; end
|
140
|
-
class MethodException < ConcurrencyException
|
141
|
-
attr_reader :object, :method
|
142
|
-
|
143
|
-
def initialize(object, method)
|
144
|
-
@object = object
|
145
|
-
@method = method
|
146
|
-
end
|
147
|
-
end
|
148
|
-
class ConcurrentCallException < MethodException; end
|
149
|
-
class NoMethodException < MethodException; end
|
150
|
-
class AmbiguousMethodException < MethodException; end
|
151
|
-
|
152
|
-
end
|
data/spec/concurrency_spec.rb
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
class TestConcurrencyCache
|
4
|
-
@@cache = {}
|
5
|
-
|
6
|
-
def self.read(key)
|
7
|
-
@@cache[key]
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.write(key, value)
|
11
|
-
@@cache[key] = value
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.delete(key)
|
15
|
-
@@cache.delete(key)
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.clear
|
19
|
-
@@cache = {}
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe Concurrency do
|
24
|
-
before :each do
|
25
|
-
TestConcurrencyCache.clear
|
26
|
-
|
27
|
-
class ConcurrencyTest
|
28
|
-
include Concurrency
|
29
|
-
|
30
|
-
self.concurrency_cache = TestConcurrencyCache
|
31
|
-
|
32
|
-
def self.class_test_method
|
33
|
-
sleep(1)
|
34
|
-
end
|
35
|
-
|
36
|
-
def instance_test_method
|
37
|
-
sleep(1)
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.both_instance_and_class_test_method; end
|
41
|
-
def both_instance_and_class_test_method; end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
after :each do
|
46
|
-
Object.send(:remove_const, :ConcurrencyTest)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should allow specifying which methods should implement the concurrency check" do
|
50
|
-
expect { ConcurrencyTest.send(:concurrency_safe, :instance_test_method) }
|
51
|
-
.to_not raise_error
|
52
|
-
expect { ConcurrencyTest.send(:concurrency_safe, :class_test_method) }
|
53
|
-
.to_not raise_error
|
54
|
-
expect { ConcurrencyTest.send(:concurrency_safe, :both_instance_and_class_test_method) }
|
55
|
-
.to raise_error(Concurrency::AmbiguousMethodException)
|
56
|
-
expect { ConcurrencyTest.send(:concurrency_safe, :both_instance_and_class_test_method, type: :instance) }
|
57
|
-
.to_not raise_error
|
58
|
-
expect { ConcurrencyTest.send(:concurrency_safe, :both_instance_and_class_test_method, type: :class) }
|
59
|
-
.to_not raise_error
|
60
|
-
expect { ConcurrencyTest.send(:concurrency_safe, :unknown_method) }
|
61
|
-
.to raise_error(Concurrency::NoMethodException)
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should allow identyfying the type of a method" do
|
65
|
-
expect(ConcurrencyTest.send(:method_types, :class_test_method)).to eq ['class']
|
66
|
-
expect(ConcurrencyTest.send(:method_types, :instance_test_method)).to eq ['instance']
|
67
|
-
expect(ConcurrencyTest.send(:method_types, :both_instance_and_class_test_method)).to eq ['class','instance']
|
68
|
-
expect(ConcurrencyTest.send(:method_types, :unknown_method)).to be_blank
|
69
|
-
expect(ConcurrencyTest.send(:method_type, :class_test_method)).to eq 'class'
|
70
|
-
expect(ConcurrencyTest.send(:method_type, :instance_test_method)).to eq 'instance'
|
71
|
-
expect { ConcurrencyTest.send(:method_type, :both_instance_and_class_test_method) }
|
72
|
-
.to raise_error(Concurrency::AmbiguousMethodException)
|
73
|
-
expect { ConcurrencyTest.send(:method_type, :unknown_method) }
|
74
|
-
.to raise_error(Concurrency::NoMethodException)
|
75
|
-
end
|
76
|
-
|
77
|
-
it "should allow checking the concurrency lock for specified class methods" do
|
78
|
-
ConcurrencyTest.send(:concurrency_safe, :class_test_method)
|
79
|
-
started = false
|
80
|
-
expect(ConcurrencyTest.concurrency_safe_method_locked?(:class_test_method)).to be false
|
81
|
-
thread = Thread.new { ConcurrencyTest.send(:class_test_method); started = true }
|
82
|
-
thread.join
|
83
|
-
expect(ConcurrencyTest.concurrency_safe_method_locked?(:class_test_method)).to be true until started
|
84
|
-
end
|
85
|
-
|
86
|
-
it "should allow checking the concurrency lock for specified instance methods" do
|
87
|
-
ConcurrencyTest.send(:concurrency_safe, :class_test_method)
|
88
|
-
instance = ConcurrencyTest.new
|
89
|
-
started = false
|
90
|
-
expect(instance.concurrency_safe_method_locked?(:instance_test_method)).to be false
|
91
|
-
thread = Thread.new { instance.send(:instance_test_method); started = true }
|
92
|
-
thread.join
|
93
|
-
expect(instance.concurrency_safe_method_locked?(:instance_test_method)).to be true until started
|
94
|
-
end
|
95
|
-
|
96
|
-
it "should implement the concurrency check for specified class methods" do
|
97
|
-
ConcurrencyTest.send(:concurrency_safe, :class_test_method)
|
98
|
-
threads = 2.times.map { Thread.new { ConcurrencyTest.send(:class_test_method) } }
|
99
|
-
expect { threads.each(&:join) }
|
100
|
-
.to raise_error(Concurrency::ConcurrentCallException)
|
101
|
-
end
|
102
|
-
|
103
|
-
it "should implement the concurrency check for specified instance methods" do
|
104
|
-
ConcurrencyTest.send(:concurrency_safe, :instance_test_method)
|
105
|
-
instance = ConcurrencyTest.new
|
106
|
-
threads = 2.times.map { Thread.new { instance.send(:instance_test_method) } }
|
107
|
-
expect { threads.each(&:join) }
|
108
|
-
.to raise_error(Concurrency::ConcurrentCallException)
|
109
|
-
end
|
110
|
-
end
|