messages_dictionary 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
  require 'hashie'
5
+ require 'zeitwerk'
6
+
7
+ loader = Zeitwerk::Loader.for_gem
8
+ loader.setup
3
9
 
4
- require_relative 'messages_dictionary/utils/snake_case'
5
- require_relative 'messages_dictionary/utils/dict'
6
- require_relative 'messages_dictionary/injector'
10
+ # Store your messages anywhere and fetch them anytime.
11
+ # For example:
12
+ #
13
+ # class MyClass
14
+ # include MessagesDictionary
15
+ # has_messages_dictionary
7
16
 
17
+ # def calculate(a)
18
+ # result = a ** 2
19
+ # pretty_output(:show_result, result: result)
20
+ # end
21
+ # end
8
22
  module MessagesDictionary
23
+ def self.included(klass)
24
+ klass.include MessagesDictionary::Injector
25
+ end
9
26
  end
10
-
@@ -1,24 +1,35 @@
1
- require File.expand_path("../lib/messages_dictionary/version", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('lib/messages_dictionary/version', __dir__)
2
4
 
3
5
  Gem::Specification.new do |spec|
4
- spec.name = "messages_dictionary"
6
+ spec.name = 'messages_dictionary'
5
7
  spec.version = MessagesDictionary::VERSION
6
- spec.authors = ["Ilya Bodrov", "anilika"]
7
- spec.email = ["golosizpru@gmail.com"]
8
- spec.summary = %q{Store your messages anywhere and fetch them anytime.}
9
- spec.description = %q{This gem allows you to store some text in a simple-key value format and fetch it whenever you need from your methods. Various classes may have different messages attached and apply different fetching logic. Messages also support interpolation and can be stored in separate YAML files.}
10
- spec.homepage = "https://github.com/bodrovis-learning/messages_dictionary"
11
- spec.license = "MIT"
8
+ spec.authors = ['Ilya Krukowski', 'anilika']
9
+ spec.email = ['golosizpru@gmail.com']
10
+ spec.summary = 'Store your messages anywhere and fetch them anytime.'
11
+ spec.description = 'This gem allows you to store some text in a simple-key value format and fetch ' \
12
+ 'it whenever you need from your methods. Various classes may have different ' \
13
+ 'messages attached and apply different fetching logic. Messages also support ' \
14
+ 'interpolation and can be stored in separate YAML files.'
15
+ spec.homepage = 'https://github.com/bodrovis-learning/messages_dictionary'
16
+ spec.license = 'MIT'
12
17
  spec.platform = Gem::Platform::RUBY
13
-
18
+ spec.required_ruby_version = '>= 2.7.0'
14
19
  spec.files = `git ls-files`.split("\n")
15
- spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
- spec.extra_rdoc_files = ["README.md"]
17
- spec.require_paths = ["lib"]
20
+ spec.extra_rdoc_files = ['README.md']
21
+ spec.require_paths = ['lib']
18
22
 
19
- spec.add_dependency 'hashie', '~> 3.4'
23
+ spec.add_dependency 'hashie', '~> 5.0'
24
+ spec.add_dependency 'zeitwerk', '~> 2.4'
20
25
 
21
- spec.add_development_dependency "rake", "~> 12.0"
22
- spec.add_development_dependency "rspec", "~> 3.6"
23
- spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0"
24
- end
26
+ spec.add_development_dependency 'codecov', '~> 0.1'
27
+ spec.add_development_dependency 'rake', '~> 13.0'
28
+ spec.add_development_dependency 'rspec', '~> 3.6'
29
+ spec.add_development_dependency 'rubocop', '~> 1.6'
30
+ spec.add_development_dependency 'rubocop-performance', '~> 1.5'
31
+ spec.add_development_dependency 'rubocop-rake', '~> 0.6'
32
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.0'
33
+ spec.add_development_dependency 'simplecov', '~> 0.16'
34
+ spec.metadata['rubygems_mfa_required'] = 'true'
35
+ end
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe MessagesDictionary::Injector do
4
+ let(:dummy) { Class.new { include MessagesDictionary::Injector } }
5
+
6
+ context 'with messages' do
7
+ context 'when outputting' do
8
+ it 'uses STDOUT by default' do
9
+ dummy.class_eval do
10
+ has_messages_dictionary messages: {test: 'string'}
11
+ end
12
+
13
+ expect(dummy::DICTIONARY_CONF[:output]).to eq($stdout)
14
+ end
15
+
16
+ it 'uses puts method by default' do
17
+ dummy.class_eval do
18
+ has_messages_dictionary messages: {test: 'string'}
19
+ end
20
+
21
+ expect(dummy::DICTIONARY_CONF[:method]).to eq(:puts)
22
+ end
23
+
24
+ it 'allows customizing output and method' do
25
+ output = instance_double(IO)
26
+
27
+ allow(output).to receive(:print)
28
+
29
+ dummy.class_eval do
30
+ has_messages_dictionary messages: {test: 'string'}, output: output, method: :print
31
+ end
32
+
33
+ object = dummy.new
34
+
35
+ object.send(:pretty_output, :test)
36
+
37
+ expect(output).to have_received(:print).with('string').exactly(1).time
38
+ end
39
+
40
+ it 'aliases pretty_output as pou' do
41
+ output = instance_double(IO)
42
+
43
+ allow(output).to receive(:puts)
44
+
45
+ dummy.class_eval do
46
+ has_messages_dictionary messages: {test: 'string'}, output: output
47
+ end
48
+
49
+ object = dummy.new
50
+
51
+ object.send(:pou, :test)
52
+
53
+ expect(output).to have_received(:puts).with('string').exactly(1).time
54
+ end
55
+ end
56
+
57
+ context 'when passed as hash' do
58
+ it 'supports nesting' do
59
+ dummy.class_eval do
60
+ has_messages_dictionary messages: {parent: {child: 'child_string'}}
61
+ end
62
+
63
+ object = dummy.new
64
+ expect(object.send(:pretty_output, 'parent.child') { |msg| msg }).to eq('child_string')
65
+ end
66
+ end
67
+
68
+ context 'when passed in file' do
69
+ it 'works with anonymous classes' do
70
+ in_dir 'unknown.yml' do
71
+ dummy.class_eval do
72
+ has_messages_dictionary
73
+ end
74
+
75
+ object = dummy.new
76
+ expect(object.send(:pretty_output, :test) { |msg| msg }).to eq('string')
77
+ end
78
+ end
79
+
80
+ it 'searches file named after class name by default' do
81
+ in_dir 'fake_class.yml' do
82
+ stub_const 'FakeClass', dummy
83
+
84
+ FakeClass.class_eval do
85
+ has_messages_dictionary
86
+ end
87
+
88
+ object = FakeClass.new
89
+ expect(object.send(:pretty_output, :test) { |msg| msg }).to eq('string')
90
+ end
91
+ end
92
+
93
+ it 'allows passing path and file' do
94
+ in_dir 'my_test_file.yml', 'my_test_dir' do
95
+ dummy.class_eval do
96
+ has_messages_dictionary file: 'my_test_file.yml', dir: 'my_test_dir'
97
+ end
98
+
99
+ object = dummy.new
100
+ expect(object.send(:pretty_output, :test) { |msg| msg }).to eq('string')
101
+ expect(object.send(:pretty_output, :interpolated, a: 42) { |msg| msg }).to eq('Value is 42')
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ context 'with error' do
108
+ it 'is raised when key is not found' do
109
+ dummy.class_eval do
110
+ has_messages_dictionary messages: {test: 'string'}
111
+ end
112
+
113
+ object = dummy.new
114
+ expect { object.send(:pretty_output, :does_not_exist) }.to raise_error(KeyError)
115
+ end
116
+
117
+ it 'is raised when file is not found and the program aborts' do
118
+ expect do
119
+ dummy.class_eval do
120
+ has_messages_dictionary dir: 'random', file: 'not_exist.yml'
121
+ end
122
+ end.to raise_error(
123
+ an_instance_of(SystemExit).
124
+ and(having_attributes(message: "File #{File.expand_path('random/not_exist.yml')} does not exist..."))
125
+ )
126
+ end
127
+ end
128
+
129
+ context 'with transformations' do
130
+ it 'applies per-method transformations' do
131
+ dummy.class_eval do
132
+ has_messages_dictionary messages: {test: 'string'}
133
+ end
134
+
135
+ object = dummy.new
136
+ expect(object.send(:pretty_output, :test, &:upcase)).to eq('STRING')
137
+ end
138
+
139
+ it 'applies per-class transformations' do
140
+ dummy.class_eval do
141
+ has_messages_dictionary messages: {test: 'string'},
142
+ transform: ->(msg) { puts msg.upcase }
143
+
144
+ define_method :run do
145
+ pou(:test)
146
+ end
147
+ end
148
+
149
+ object = dummy.new
150
+
151
+ allow($stdout).to receive(:puts).with('STRING')
152
+
153
+ object.run
154
+
155
+ expect($stdout).to have_received(:puts).exactly(1).time
156
+ end
157
+
158
+ it 'per-method takes higher priority than per-class' do
159
+ dummy.class_eval do
160
+ has_messages_dictionary messages: {test: 'string'},
161
+ transform: ->(msg) { msg.reverse }
162
+ end
163
+
164
+ object = dummy.new
165
+ expect(object.send(:pretty_output, :test, &:upcase)).to eq('STRING')
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe MessagesDictionary::Utils::Dict do
4
+ let(:dummy) { described_class.new key: 'value' }
5
+
6
+ it 'allows indifferent access' do
7
+ expect(dummy[:key]).to eq('value')
8
+ expect(dummy['key']).to eq('value')
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe MessagesDictionary do
4
+ let(:dummy) { Class.new { include MessagesDictionary } }
5
+
6
+ it 'includes the necessary methods' do
7
+ dummy.class_eval do
8
+ has_messages_dictionary messages: {parent: {child: 'child_string'}}
9
+
10
+ define_method :run do
11
+ pou('parent.child', &:upcase)
12
+ end
13
+ end
14
+
15
+ object = dummy.new
16
+ expect(object.send(:pou, 'parent.child') { |msg| msg }).to eq('child_string')
17
+ expect(object.send(:pretty_output, 'parent.child') { |msg| msg }).to eq('child_string')
18
+ expect(object.run).to eq('CHILD_STRING')
19
+ end
20
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,16 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'simplecov'
2
4
  SimpleCov.start do
3
- add_filter "/spec/"
4
- add_filter "/bin/"
5
+ add_filter '/spec/'
6
+ add_filter '/bin/'
7
+ end
8
+
9
+ if ENV.fetch('CI', nil) == 'true'
10
+ require 'codecov'
11
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
5
12
  end
6
13
 
7
- $LOAD_PATH << File.expand_path('../../../lib', __FILE__)
8
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
14
+ $LOAD_PATH << File.expand_path('../../lib', __dir__)
15
+
16
+ RSPEC_ROOT = File.dirname __FILE__
17
+
18
+ Dir["#{RSPEC_ROOT}/support/**/*.rb"].sort.each { |f| require f }
9
19
 
10
20
  require 'messages_dictionary'
11
21
 
12
22
  RSpec.configure do |config|
13
- config.include SpecAddons
14
23
  config.include SpecFilesSetup
15
24
  config.include SpecUtils
16
- end
25
+ end
@@ -1,14 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
 
3
5
  module SpecFilesSetup
4
6
  def setup_env!(path, file)
5
- FileUtils.mkdir_p(path)
6
- f = File.new("#{path}/#{file}", 'w+')
7
- f.write('test: string')
7
+ full_path = "#{RSPEC_ROOT}/dummy/#{path}"
8
+
9
+ FileUtils.mkdir_p full_path
10
+
11
+ f = File.new(File.join(full_path, file), 'w+')
12
+ f.write("test: string\ninterpolated: Value is {{a}}")
8
13
  f.close
9
14
  end
10
15
 
11
16
  def clear_env!(path)
12
- FileUtils.remove_entry(path)
17
+ FileUtils.remove_entry("#{RSPEC_ROOT}/dummy/#{path}")
13
18
  end
14
- end
19
+ end
@@ -1,23 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SpecUtils
2
- def capture_stderr(&block)
3
- original_stderr = $stderr
4
- $stderr = fake = StringIO.new
5
- begin
6
- yield
7
- ensure
8
- $stderr = original_stderr
9
- end
10
- fake.string
11
- end
4
+ def in_dir(file, path = '')
5
+ return unless block_given?
6
+
7
+ setup_env!(path, file)
8
+
9
+ initial_path = Dir.getwd
10
+
11
+ Dir.chdir "#{RSPEC_ROOT}/dummy"
12
+
13
+ yield
14
+
15
+ Dir.chdir initial_path
12
16
 
13
- def capture_stdout(&block)
14
- original_stdout = $stdout
15
- $stdout = fake = StringIO.new
16
- begin
17
- yield
18
- ensure
19
- $stdout = original_stdout
20
- end
21
- fake.string
17
+ clear_env!(path)
22
18
  end
23
- end
19
+ end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: messages_dictionary
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Ilya Bodrov
7
+ - Ilya Krukowski
8
8
  - anilika
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-05-08 00:00:00.000000000 Z
12
+ date: 2022-11-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: hashie
@@ -17,28 +17,56 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '3.4'
20
+ version: '5.0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '3.4'
27
+ version: '5.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: zeitwerk
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '2.4'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '2.4'
42
+ - !ruby/object:Gem::Dependency
43
+ name: codecov
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.1'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '0.1'
28
56
  - !ruby/object:Gem::Dependency
29
57
  name: rake
30
58
  requirement: !ruby/object:Gem::Requirement
31
59
  requirements:
32
60
  - - "~>"
33
61
  - !ruby/object:Gem::Version
34
- version: '12.0'
62
+ version: '13.0'
35
63
  type: :development
36
64
  prerelease: false
37
65
  version_requirements: !ruby/object:Gem::Requirement
38
66
  requirements:
39
67
  - - "~>"
40
68
  - !ruby/object:Gem::Version
41
- version: '12.0'
69
+ version: '13.0'
42
70
  - !ruby/object:Gem::Dependency
43
71
  name: rspec
44
72
  requirement: !ruby/object:Gem::Requirement
@@ -54,19 +82,75 @@ dependencies:
54
82
  - !ruby/object:Gem::Version
55
83
  version: '3.6'
56
84
  - !ruby/object:Gem::Dependency
57
- name: codeclimate-test-reporter
85
+ name: rubocop
58
86
  requirement: !ruby/object:Gem::Requirement
59
87
  requirements:
60
88
  - - "~>"
61
89
  - !ruby/object:Gem::Version
62
- version: '1.0'
90
+ version: '1.6'
63
91
  type: :development
64
92
  prerelease: false
65
93
  version_requirements: !ruby/object:Gem::Requirement
66
94
  requirements:
67
95
  - - "~>"
68
96
  - !ruby/object:Gem::Version
69
- version: '1.0'
97
+ version: '1.6'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rubocop-performance
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '1.5'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '1.5'
112
+ - !ruby/object:Gem::Dependency
113
+ name: rubocop-rake
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '0.6'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '0.6'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rubocop-rspec
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: '2.0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '2.0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: simplecov
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - "~>"
145
+ - !ruby/object:Gem::Version
146
+ version: '0.16'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - "~>"
152
+ - !ruby/object:Gem::Version
153
+ version: '0.16'
70
154
  description: This gem allows you to store some text in a simple-key value format and
71
155
  fetch it whenever you need from your methods. Various classes may have different
72
156
  messages attached and apply different fetching logic. Messages also support interpolation
@@ -78,9 +162,17 @@ extensions: []
78
162
  extra_rdoc_files:
79
163
  - README.md
80
164
  files:
165
+ - ".github/CODE_OF_CONDUCT.md"
166
+ - ".github/CONTRIBUTING.md"
167
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
168
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
169
+ - ".github/PULL_REQUEST_TEMPLATE.md"
170
+ - ".github/dependabot.yml"
171
+ - ".github/workflows/ci.yml"
81
172
  - ".gitignore"
82
173
  - ".rspec"
83
- - ".travis.yml"
174
+ - ".rubocop.yml"
175
+ - CHANGELOG.md
84
176
  - Gemfile
85
177
  - Gemfile.lock
86
178
  - LICENSE
@@ -89,21 +181,21 @@ files:
89
181
  - lib/messages_dictionary.rb
90
182
  - lib/messages_dictionary/injector.rb
91
183
  - lib/messages_dictionary/utils/dict.rb
92
- - lib/messages_dictionary/utils/snake_case.rb
184
+ - lib/messages_dictionary/utils/string_utils.rb
93
185
  - lib/messages_dictionary/version.rb
94
186
  - messages_dictionary.gemspec
95
- - spec/injector_spec.rb
187
+ - spec/lib/messages_dictionary/injector_spec.rb
188
+ - spec/lib/messages_dictionary/utils/dict_spec.rb
189
+ - spec/lib/messages_dictionary_spec.rb
96
190
  - spec/spec_helper.rb
97
191
  - spec/support/spec_files_setup.rb
98
192
  - spec/support/spec_utils.rb
99
- - spec/support/test_class.rb
100
- - spec/utils/dict_spec.rb
101
- - spec/utils/snake_case_spec.rb
102
193
  homepage: https://github.com/bodrovis-learning/messages_dictionary
103
194
  licenses:
104
195
  - MIT
105
- metadata: {}
106
- post_install_message:
196
+ metadata:
197
+ rubygems_mfa_required: 'true'
198
+ post_install_message:
107
199
  rdoc_options: []
108
200
  require_paths:
109
201
  - lib
@@ -111,16 +203,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
203
  requirements:
112
204
  - - ">="
113
205
  - !ruby/object:Gem::Version
114
- version: '0'
206
+ version: 2.7.0
115
207
  required_rubygems_version: !ruby/object:Gem::Requirement
116
208
  requirements:
117
209
  - - ">="
118
210
  - !ruby/object:Gem::Version
119
211
  version: '0'
120
212
  requirements: []
121
- rubyforge_project:
122
- rubygems_version: 2.6.12
123
- signing_key:
213
+ rubygems_version: 3.3.26
214
+ signing_key:
124
215
  specification_version: 4
125
216
  summary: Store your messages anywhere and fetch them anytime.
126
217
  test_files: []
data/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- language: ruby
2
-
3
- rvm:
4
- - 2.1.5
5
- - 2.2.5
6
- - 2.3.4
7
- - ruby-head
8
-
9
- install: bundle install --retry=3
10
-
11
- after_success:
12
- - bundle exec codeclimate-test-reporter
@@ -1,17 +0,0 @@
1
- module MessagesDictionary
2
- class SpecialString
3
- attr_accessor :string
4
-
5
- def initialize(string)
6
- @string = string
7
- end
8
-
9
- def snake_case
10
- string.gsub(/::/, '/').
11
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
12
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
13
- tr("-", "_").
14
- downcase
15
- end
16
- end
17
- end