rails_core_extensions 0.12.0 → 0.13.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
  SHA256:
3
- metadata.gz: 4e362185defe03c222c8b0d0cf77b3281f0fac38fde27f90ed1273d026bb28d7
4
- data.tar.gz: 4f91461d5666fdb4ce836c50e11d0808a27da50605f40343e3c0b17cf53e441f
3
+ metadata.gz: 2b1eb7cf498a2e96bf6b76cf957ae9f1e3a9bd98dfe3a295a993614b2d6c964b
4
+ data.tar.gz: 833f7a348a0df83860057188a63d7c8a0b7b41165e772440bdf806cfdd3ff244
5
5
  SHA512:
6
- metadata.gz: b73a245c3f1039fed5d0b2246d3b758a452364a114af36972ecfbeef970c426389271b9eac2feab4da7d0147b133532477dea28506f5b9cdb486ab943b396b3d
7
- data.tar.gz: 101efda04a0f37b08757be11b4e2d89314e99d3e8935de832d550bd0dae4046d3c69eb9ec124c428dd9c62d59341a2f9015fc98d6619ca8a16329818b2613e83
6
+ metadata.gz: 220a9b391ae6601bd5e6b3163dba1c1ea3a93a80ec5790421777e0905ed2fffd0932f6f2f66fed51f4be93fe3882737494d55ca779e65de4149f1008b5651a80
7
+ data.tar.gz: 3f77384f933a2565f0e043fae0afc6444016f1468a7b53ad46de3e5c89d8d3620dd1273a3453ff3e21c43c7326ab10f50759bf4ea31d3610e57dd0295a78120c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.13.0
4
+
5
+ - [PLAT-378] Improve bundler startup time; Drop Concurrency
6
+
3
7
  ## 0.12.0
4
8
 
5
9
  - [PLAT-183] Ruby 3.1, Rails 7.0 and publish coverage with github action
@@ -1,8 +1,6 @@
1
1
  module RailsCoreExtensions
2
2
  module ActionControllerSortable
3
- def self.included(base)
4
- base.extend ClassMethods
5
- end
3
+ extend ActiveSupport::Concern
6
4
 
7
5
  module ClassMethods
8
6
  def sortable
@@ -28,5 +28,7 @@ module RailsCoreExtensions
28
28
  end
29
29
  end
30
30
 
31
- ActionView::Base.send(:include, RailsCoreExtensions::HasManyExtensions::Tags) if defined?(ActionView::Base)
32
- ActionView::Helpers::FormBuilder.send(:include, RailsCoreExtensions::HasManyExtensions::FormBuilder) if defined?(ActionView::Base)
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,8 +1,6 @@
1
1
  module ActiveModelExtensions
2
2
  module Validations
3
- def self.included(base)
4
- base.extend ClassMethods
5
- end
3
+ extend ActiveSupport::Concern
6
4
 
7
5
  # Validates the presence of the required fields identified in a rule-string.
8
6
  #
@@ -1,7 +1,5 @@
1
1
  module ActiveRecordCloning
2
- def self.included(base)
3
- base.extend(ClassMethods)
4
- end
2
+ extend ActiveSupport::Concern
5
3
 
6
4
  module ClassMethods
7
5
 
@@ -1,7 +1,5 @@
1
1
  module ActiveRecordExtensions
2
- def self.included(base)
3
- base.extend ClassMethods
4
- end
2
+ extend ActiveSupport::Concern
5
3
 
6
4
  module ClassMethods
7
5
  # Like establish_connection but postfixes the key with the rails environment
@@ -1,8 +1,6 @@
1
1
  module RailsCoreExtensions
2
2
  module ActiveRecordLiquidExtensions
3
- def self.included(base)
4
- base.extend ClassMethods
5
- end
3
+ extend ActiveSupport::Concern
6
4
  end
7
5
 
8
6
  module ClassMethods
@@ -1,8 +1,6 @@
1
1
  module RailsCoreExtensions
2
2
  module Translations
3
- def self.included(base)
4
- base.extend ClassMethods
5
- end
3
+ extend ActiveSupport::Concern
6
4
 
7
5
  module ClassMethods
8
6
  def translate(key, options = {})
@@ -1,3 +1,3 @@
1
1
  module RailsCoreExtensions
2
- VERSION = '0.12.0'
2
+ VERSION = '0.13.0'
3
3
  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
- ActionController::Base.send(:include, Activatable)
16
- ActionController::Base.send(:include, ActionControllerSortable)
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
- ActionView::Base.send(:include, RailsCoreExtensions::ActionViewExtensions)
23
+ ActiveSupport.on_load(:active_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
- ActiveRecord::Base.send(:include, ActiveRecordCloning)
34
- ActiveRecord::Base.send(:include, ActiveRecordExtensions)
35
- ActiveRecord::Base.send(:include, RailsCoreExtensions::ActiveRecordLiquidExtensions)
36
- ActiveRecord::Base.send(:include, ActiveRecordExtensions::InstanceMethods)
37
- ActiveRecord::Base.send(:include, RailsCoreExtensions::Translations)
38
- ActiveRecord::Base.send(:include, ActiveModelExtensions::Validations)
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
@@ -1,3 +1,3 @@
1
1
  require 'coverage/kit'
2
2
 
3
- Coverage::Kit.setup(minimum_coverage: 86.7)
3
+ Coverage::Kit.setup(minimum_coverage: 84.1)
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.12.0
4
+ version: 0.13.0
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-01-25 00:00:00.000000000 Z
12
+ date: 2022-07-02 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
@@ -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