rails_core_extensions 0.11.3 → 0.13.1

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: cb01e71e0bcfd0cfbeb33038f8b4d0c352963b1e038281cc7b367efb857a0c4a
4
- data.tar.gz: 420d2f75e7177bc8e830f3e664d715e05b7edfbe926bc1c1d8281bfded08e631
3
+ metadata.gz: ccc0583ffb6264c6f3a3c4ec35caf8028c263dc37403eae6417a2e2a398b01c9
4
+ data.tar.gz: e332a69c6ed44ab4cec2f12608a0af873ab799d6f7274f818ab9c211eff05ee2
5
5
  SHA512:
6
- metadata.gz: b6ae22bd6a58fe5e52c7d87ccd3638bd61f207845634b1121974ca1f9c9c193d263e476ecc457012e189df62291b4aacfe318f4329943b30051643d355ba380e
7
- data.tar.gz: '096f622ef44ccf9a96a2d08ea38604ecd73eeb42edcdff939ddae5d2256235546a8c5c31c37d796a691aaa71702796282ff5c2ab39a640ade77c9a22171eac87'
6
+ metadata.gz: c73627135e3553892c98facf3071f2599db2f222d0c35e9b8fa9a0f372fa3f40dbdf10f42ccfc2d5df20fa37ae6136aba5199c98e8ef093f406989d16dd23443
7
+ data.tar.gz: 634791e2c66ab5972318a1a8f44c15ba00dd6257ae7110487c56ca2f9c8406dcf779c94558606242923ec626541486aa0bfe53913fb2cdc28cf3a9ba8422bdcd
@@ -5,8 +5,8 @@ jobs:
5
5
  strategy:
6
6
  fail-fast: false
7
7
  matrix:
8
- gemfile: [rails60, rails61]
9
- ruby: ["2.6", "2.7", "3.0"]
8
+ gemfile: [rails60, rails61, rails70]
9
+ ruby: ["2.7", "3.0", "3.1"]
10
10
  runs-on: ubuntu-latest
11
11
  env:
12
12
  BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
@@ -17,3 +17,8 @@ jobs:
17
17
  ruby-version: ${{ matrix.ruby }}
18
18
  bundler-cache: true
19
19
  - run: bundle exec rake
20
+ - name: Coveralls
21
+ uses: coverallsapp/github-action@master
22
+ with:
23
+ github-token: ${{ secrets.GITHUB_TOKEN }}
24
+ path-to-lcov: coverage/lcov.info
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.0.0
1
+ 3.1.0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.13.1
4
+
5
+ - [PLAT-384] Fix the liquid extension
6
+
7
+ ## 0.13.0
8
+
9
+ - [PLAT-378] Improve bundler startup time; Drop Concurrency
10
+
11
+ ## 0.12.0
12
+
13
+ - [PLAT-183] Ruby 3.1, Rails 7.0 and publish coverage with github action
14
+
3
15
  ## 0.11.3
4
16
 
5
17
  - [TT-8647] Fix issue with position_helpers_for active record change
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ gemspec :path => '../'
3
+
4
+ group :development, :test do
5
+ gem 'activerecord', '~> 7.0'
6
+ end
@@ -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,32 +1,30 @@
1
1
  module RailsCoreExtensions
2
2
  module ActiveRecordLiquidExtensions
3
- def self.included(base)
4
- base.extend ClassMethods
5
- end
6
- end
3
+ extend ActiveSupport::Concern
7
4
 
8
- module ClassMethods
9
- def validates_liquid(field)
10
- field = field.to_sym
11
- before_validation do |record|
12
- begin
13
- Liquid::Template.parse(record.send(field), error_mode: :strict)
14
- rescue Liquid::SyntaxError => e
15
- record.errors.add(field, "Liquid Syntax Error: #{e}")
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
- def liquid_field(field)
21
- class_eval <<-CODE
22
- def parsed_#{field}
23
- Liquid::Template.parse(#{field})
24
- end
17
+ def liquid_field(field)
18
+ class_eval <<-CODE
19
+ def parsed_#{field}
20
+ Liquid::Template.parse(#{field})
21
+ end
25
22
 
26
- def render_#{field}(*args)
27
- parsed_#{field}.render!(*args)
28
- end
29
- CODE
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
@@ -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.11.3'
2
+ VERSION = '0.13.1'
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
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ['lib']
21
- spec.required_ruby_version = '>= 2.6'
21
+ spec.required_ruby_version = '>= 2.7'
22
22
 
23
23
  spec.add_dependency 'activerecord', ['>= 6.0.0']
24
24
  spec.add_dependency 'actionpack', ['>= 6.0.0']
@@ -28,8 +28,6 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency 'rspec'
29
29
  spec.add_development_dependency 'activerecord-nulldb-adapter'
30
30
  spec.add_development_dependency 'coverage-kit'
31
- spec.add_development_dependency 'simplecov-rcov'
32
- spec.add_development_dependency 'coveralls'
33
31
  spec.add_development_dependency 'rubocop'
34
32
  spec.add_development_dependency 'sqlite3'
35
33
  end
@@ -1,5 +1,3 @@
1
- require 'simplecov-rcov'
2
- require 'coveralls'
3
1
  require 'coverage/kit'
4
2
 
5
- 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.11.3
4
+ version: 0.13.1
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: 2021-01-06 00:00:00.000000000 Z
12
+ date: 2022-07-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -109,34 +109,6 @@ dependencies:
109
109
  - - ">="
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
- - !ruby/object:Gem::Dependency
113
- name: simplecov-rcov
114
- requirement: !ruby/object:Gem::Requirement
115
- requirements:
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- version: '0'
119
- type: :development
120
- prerelease: false
121
- version_requirements: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: coveralls
128
- requirement: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - ">="
131
- - !ruby/object:Gem::Version
132
- version: '0'
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - ">="
138
- - !ruby/object:Gem::Version
139
- version: '0'
140
112
  - !ruby/object:Gem::Dependency
141
113
  name: rubocop
142
114
  requirement: !ruby/object:Gem::Requirement
@@ -176,9 +148,7 @@ files:
176
148
  - ".github/workflows/release.yml"
177
149
  - ".github/workflows/ruby.yml"
178
150
  - ".gitignore"
179
- - ".hound.yml"
180
151
  - ".rspec"
181
- - ".ruby-style.yml"
182
152
  - ".ruby-version"
183
153
  - CHANGELOG.md
184
154
  - Gemfile
@@ -187,6 +157,7 @@ files:
187
157
  - Rakefile
188
158
  - gemfiles/rails60.gemfile
189
159
  - gemfiles/rails61.gemfile
160
+ - gemfiles/rails70.gemfile
190
161
  - lib/rails_core_extensions.rb
191
162
  - lib/rails_core_extensions/action_controller_sortable.rb
192
163
  - lib/rails_core_extensions/action_view_extensions.rb
@@ -196,8 +167,6 @@ files:
196
167
  - lib/rails_core_extensions/active_record_cloning.rb
197
168
  - lib/rails_core_extensions/active_record_extensions.rb
198
169
  - lib/rails_core_extensions/active_record_liquid_extensions.rb
199
- - lib/rails_core_extensions/active_support_concern.rb
200
- - lib/rails_core_extensions/concurrency.rb
201
170
  - lib/rails_core_extensions/position_initializer.rb
202
171
  - lib/rails_core_extensions/railtie.rb
203
172
  - lib/rails_core_extensions/sortable.rb
@@ -212,7 +181,6 @@ files:
212
181
  - spec/active_model_extensions_spec.rb
213
182
  - spec/active_record_cloning_spec.rb
214
183
  - spec/active_record_extensions_spec.rb
215
- - spec/concurrency_spec.rb
216
184
  - spec/en.yml
217
185
  - spec/position_initializer_spec.rb
218
186
  - spec/schema.rb
@@ -233,14 +201,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
233
201
  requirements:
234
202
  - - ">="
235
203
  - !ruby/object:Gem::Version
236
- version: '2.6'
204
+ version: '2.7'
237
205
  required_rubygems_version: !ruby/object:Gem::Requirement
238
206
  requirements:
239
207
  - - ">="
240
208
  - !ruby/object:Gem::Version
241
209
  version: '0'
242
210
  requirements: []
243
- rubygems_version: 3.2.3
211
+ rubygems_version: 3.3.3
244
212
  signing_key:
245
213
  specification_version: 4
246
214
  summary: Set of extensions to core rails libraries.
@@ -250,7 +218,6 @@ test_files:
250
218
  - spec/active_model_extensions_spec.rb
251
219
  - spec/active_record_cloning_spec.rb
252
220
  - spec/active_record_extensions_spec.rb
253
- - spec/concurrency_spec.rb
254
221
  - spec/en.yml
255
222
  - spec/position_initializer_spec.rb
256
223
  - spec/schema.rb
data/.hound.yml DELETED
@@ -1,2 +0,0 @@
1
- ruby:
2
- config_file: .ruby-style.yml
data/.ruby-style.yml DELETED
@@ -1,217 +0,0 @@
1
- AllCops:
2
- Exclude:
3
- - "vendor/**/*"
4
- - "db/schema.rb"
5
- UseCache: false
6
- Style/CollectionMethods:
7
- Description: Preferred collection methods.
8
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size
9
- Enabled: true
10
- PreferredMethods:
11
- collect: map
12
- collect!: map!
13
- find: detect
14
- find_all: select
15
- reduce: inject
16
- Layout/DotPosition:
17
- Description: Checks the position of the dot in multi-line method calls.
18
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains
19
- Enabled: true
20
- EnforcedStyle: trailing
21
- SupportedStyles:
22
- - leading
23
- - trailing
24
- Naming/FileName:
25
- Description: Use snake_case for source file names.
26
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-files
27
- Enabled: false
28
- Exclude: []
29
- Style/GuardClause:
30
- Description: Check for conditionals that can be replaced with guard clauses
31
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
32
- Enabled: false
33
- MinBodyLength: 1
34
- Style/IfUnlessModifier:
35
- Description: Favor modifier if/unless usage when you have a single-line body.
36
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier
37
- Enabled: false
38
- Style/OptionHash:
39
- Description: Don't use option hashes when you can use keyword arguments.
40
- Enabled: false
41
- Style/PercentLiteralDelimiters:
42
- Description: Use `%`-literal delimiters consistently
43
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces
44
- Enabled: false
45
- PreferredDelimiters:
46
- "%": "()"
47
- "%i": "()"
48
- "%q": "()"
49
- "%Q": "()"
50
- "%r": "{}"
51
- "%s": "()"
52
- "%w": "()"
53
- "%W": "()"
54
- "%x": "()"
55
- Naming/PredicateName:
56
- Description: Check the names of predicate methods.
57
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark
58
- Enabled: true
59
- NamePrefix:
60
- - is_
61
- - has_
62
- - have_
63
- NamePrefixBlacklist:
64
- - is_
65
- Exclude:
66
- - spec/**/*
67
- Style/RaiseArgs:
68
- Description: Checks the arguments passed to raise/fail.
69
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages
70
- Enabled: false
71
- EnforcedStyle: exploded
72
- SupportedStyles:
73
- - compact
74
- - exploded
75
- Style/SignalException:
76
- Description: Checks for proper usage of fail and raise.
77
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
78
- Enabled: false
79
- EnforcedStyle: semantic
80
- SupportedStyles:
81
- - only_raise
82
- - only_fail
83
- - semantic
84
- Style/SingleLineBlockParams:
85
- Description: Enforces the names of some block params.
86
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks
87
- Enabled: false
88
- Methods:
89
- - reduce:
90
- - a
91
- - e
92
- - inject:
93
- - a
94
- - e
95
- Style/SingleLineMethods:
96
- Description: Avoid single-line methods.
97
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods
98
- Enabled: false
99
- AllowIfMethodIsEmpty: true
100
- Style/TrailingCommaInArguments:
101
- Description: Checks for trailing comma in argument lists.
102
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas
103
- EnforcedStyleForMultiline: comma
104
- Enabled: true
105
- Style/TrailingCommaInArrayLiteral:
106
- Description: Checks for trailing comma in array and hash literals.
107
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas
108
- EnforcedStyleForMultiline: comma
109
- Enabled: true
110
- Metrics/AbcSize:
111
- Description: A calculated magnitude based on number of assignments, branches, and
112
- conditions.
113
- Enabled: false
114
- Max: 15
115
- Metrics/ClassLength:
116
- Description: Avoid classes longer than 100 lines of code.
117
- Enabled: false
118
- CountComments: false
119
- Max: 100
120
- Metrics/ModuleLength:
121
- CountComments: false
122
- Max: 100
123
- Description: Avoid modules longer than 100 lines of code.
124
- Enabled: false
125
- Metrics/CyclomaticComplexity:
126
- Description: A complexity metric that is strongly correlated to the number of test
127
- cases needed to validate a method.
128
- Enabled: false
129
- Max: 6
130
- Metrics/MethodLength:
131
- Description: Avoid methods longer than 10 lines of code.
132
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
133
- Enabled: false
134
- CountComments: false
135
- Max: 10
136
- Metrics/ParameterLists:
137
- Description: Avoid parameter lists longer than three or four parameters.
138
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params
139
- Enabled: false
140
- Max: 5
141
- CountKeywordArgs: true
142
- Metrics/PerceivedComplexity:
143
- Description: A complexity metric geared towards measuring complexity for a human
144
- reader.
145
- Enabled: false
146
- Max: 7
147
- Lint/AssignmentInCondition:
148
- Description: Don't use assignment in conditions.
149
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition
150
- Enabled: false
151
- AllowSafeAssignment: true
152
- Style/InlineComment:
153
- Description: Avoid inline comments.
154
- Enabled: false
155
- Naming/AccessorMethodName:
156
- Description: Check the naming of accessor methods for get_/set_.
157
- Enabled: false
158
- Style/Alias:
159
- Description: Use alias_method instead of alias.
160
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method
161
- Enabled: false
162
- Style/Documentation:
163
- Description: Document classes and non-namespace modules.
164
- Enabled: false
165
- Style/DoubleNegation:
166
- Description: Checks for uses of double negation (!!).
167
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang
168
- Enabled: false
169
- Style/EachWithObject:
170
- Description: Prefer `each_with_object` over `inject` or `reduce`.
171
- Enabled: false
172
- Style/EmptyLiteral:
173
- Description: Prefer literals to Array.new/Hash.new/String.new.
174
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash
175
- Enabled: false
176
- Style/ModuleFunction:
177
- Description: Checks for usage of `extend self` in modules.
178
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function
179
- Enabled: false
180
- Style/OneLineConditional:
181
- Description: Favor the ternary operator(?:) over if/then/else/end constructs.
182
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator
183
- Enabled: false
184
- Style/PerlBackrefs:
185
- Description: Avoid Perl-style regex back references.
186
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers
187
- Enabled: false
188
- Style/Send:
189
- Description: Prefer `Object#__send__` or `Object#public_send` to `send`, as `send`
190
- may overlap with existing methods.
191
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#prefer-public-send
192
- Enabled: false
193
- Style/SpecialGlobalVars:
194
- Description: Avoid Perl-style global variables.
195
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms
196
- Enabled: false
197
- Style/VariableInterpolation:
198
- Description: Don't interpolate global, instance and class variables directly in
199
- strings.
200
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate
201
- Enabled: false
202
- Style/WhenThen:
203
- Description: Use when x then ... for one-line cases.
204
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases
205
- Enabled: false
206
- Lint/EachWithObjectArgument:
207
- Description: Check for immutable argument given to each_with_object.
208
- Enabled: true
209
- Lint/HandleExceptions:
210
- Description: Don't suppress exception.
211
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions
212
- Enabled: false
213
- Lint/LiteralInInterpolation:
214
- Description: Checks for literals used in interpolation.
215
- Enabled: false
216
- Style/FrozenStringLiteralComment:
217
- Enabled: false
@@ -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