persistent_hash 0.7.0 → 1.0.0

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/README.md +99 -0
  4. data/lib/persistent_hash/version.rb +1 -1
  5. data/spec/dummy/README.rdoc +28 -0
  6. data/spec/dummy/Rakefile +6 -0
  7. data/spec/dummy/app/assets/config/manifest.js +3 -0
  8. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  9. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  10. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  11. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  12. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  13. data/spec/dummy/bin/bundle +3 -0
  14. data/spec/dummy/bin/rails +4 -0
  15. data/spec/dummy/bin/rake +4 -0
  16. data/spec/dummy/bin/setup +29 -0
  17. data/spec/dummy/config/application.rb +33 -0
  18. data/spec/dummy/config/boot.rb +5 -0
  19. data/spec/dummy/config/database.yml +32 -0
  20. data/spec/dummy/config/environment.rb +5 -0
  21. data/spec/dummy/config/environments/development.rb +41 -0
  22. data/spec/dummy/config/environments/production.rb +79 -0
  23. data/spec/dummy/config/environments/test.rb +42 -0
  24. data/spec/dummy/config/initializers/assets.rb +11 -0
  25. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  26. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  27. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  28. data/spec/dummy/config/initializers/inflections.rb +16 -0
  29. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  30. data/spec/dummy/config/initializers/persistent_hash.rb +11 -0
  31. data/spec/dummy/config/initializers/session_store.rb +3 -0
  32. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  33. data/spec/dummy/config/locales/en.yml +23 -0
  34. data/spec/dummy/config/routes.rb +4 -0
  35. data/spec/dummy/config/secrets.yml +22 -0
  36. data/spec/dummy/config.ru +4 -0
  37. data/spec/dummy/db/schema.rb +23 -0
  38. data/spec/dummy/log/development.log +405 -0
  39. data/spec/dummy/log/test.log +3210 -0
  40. data/spec/dummy/public/404.html +67 -0
  41. data/spec/dummy/public/422.html +67 -0
  42. data/spec/dummy/public/500.html +66 -0
  43. data/spec/dummy/public/favicon.ico +0 -0
  44. data/spec/dummy/tmp/local_secret.txt +1 -0
  45. data/spec/models/persistent_hash/hash_spec.rb +79 -0
  46. data/spec/rails_helper.rb +26 -0
  47. data/spec/spec_helper.rb +61 -0
  48. metadata +95 -11
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/404.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The page you were looking for doesn't exist.</h1>
62
+ <p>You may have mistyped the address or the page may have moved.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
@@ -0,0 +1 @@
1
+ 23586b68cb36797b9863f4e7da53a90d899c8582166264c1902f1f7cc417d43831469157fe36d1c1d33a22e3f4b166aed752852af41015013f0aeb45ef18bf67
@@ -0,0 +1,79 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe PersistentHash::Hash, type: :model do
4
+
5
+ let(:subject) { PersistentHash::Hash }
6
+
7
+ after(:each) do
8
+ PersistentHash::Formatter.reset!
9
+ end
10
+
11
+ it "should get and set string values" do
12
+ subject['foo'] = 'bar'
13
+ expect(subject['foo']).to eq 'bar'
14
+ end
15
+
16
+ it "should sanitize unsafe strings" do
17
+ subject['foo\',\'bar\'); delete from persistent_hash;'] = 'foo'
18
+ expect(subject['foo\',\'bar\'); delete from persistent_hash;']).to eq 'foo'
19
+ end
20
+
21
+ it "should overwrite existing values on assignment" do
22
+ subject['foo'] = 'bar'
23
+ subject['foo'] = 'baz'
24
+ expect(subject['foo']).to eq 'baz'
25
+ end
26
+
27
+ it "should delete unwanted values" do
28
+ subject['foo'] = 'bar'
29
+ subject['foo'] = nil
30
+ expect(subject.count).to eq 0
31
+ end
32
+
33
+ it "should not error if nullifying an unknown value" do
34
+ subject['foo'] = nil
35
+ end
36
+
37
+ it "should return nil for unknown keys" do
38
+ expect(subject['missing']).to eq nil
39
+ end
40
+
41
+ it "should store non-string types" do
42
+ subject['int'] = 5
43
+ expect(subject['int'].class).to eq Integer
44
+
45
+ subject['time'] = Time.now
46
+ expect(subject['time'].class).to eq Time
47
+ end
48
+
49
+ it "should store updated_at time" do
50
+ now = Time.zone.now
51
+ Timecop.freeze(now) do
52
+ subject['foo'] = 'bar'
53
+ end
54
+
55
+ # to_i to fix resolution problems.
56
+ # (now has microseconds, which get removed by passing through the db)
57
+ expect(subject.find_by(key_name: 'foo').updated_at.to_i).to eq now.to_i
58
+
59
+ the_past = now - 2.days
60
+ Timecop.freeze(the_past) do
61
+ subject['foo'] = 'baz'
62
+ end
63
+
64
+ expect(subject.find_by(key_name: 'foo').updated_at.to_i).to eq the_past.to_i
65
+ end
66
+
67
+ it "should use formatters to set readable values" do
68
+ PersistentHash::Formatter.add(Time, ->(val) {val.utc.iso8601})
69
+
70
+ subject['time'] = '2013-05-20T00:12:30Z'.to_time
71
+ expect(subject.where(key_name: 'time').first.readable_value).to eq '2013-05-20T00:12:30Z'
72
+
73
+ PersistentHash::Formatter.add(Integer, ->(val) {val.to_f})
74
+
75
+ subject['fixnum'] = 12
76
+ expect(subject.where(key_name: 'fixnum').first.readable_value).to eq '12.0'
77
+ end
78
+
79
+ end
@@ -0,0 +1,26 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ ENV["RAILS_ENV"] ||= 'test'
3
+ require 'spec_helper'
4
+ require File.expand_path("../dummy/config/environment", __FILE__)
5
+ require 'rspec/rails'
6
+ require 'timecop'
7
+
8
+ # Requires supporting ruby files with custom matchers and macros, etc, in
9
+ # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
10
+ # run as spec files by default. This means that files in spec/support that end
11
+ # in _spec.rb will both be required and run as specs, causing the specs to be
12
+ # run twice. It is recommended that you do not name files matching this glob to
13
+ # end with _spec.rb. You can configure this pattern with the --pattern
14
+ # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
15
+ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
16
+
17
+ # Checks for pending migrations before tests are run.
18
+ # If you are not using ActiveRecord, you can remove this line.
19
+ ActiveRecord::Migration.maintain_test_schema!
20
+
21
+ RSpec.configure do |config|
22
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
23
+ # examples within a transaction, remove the following line or assign false
24
+ # instead of true.
25
+ config.use_transactional_fixtures = true
26
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
2
+
3
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
4
+ RSpec.configure do |config|
5
+ # The settings below are suggested to provide a good initial experience
6
+ # with RSpec, but feel free to customize to your heart's content.
7
+
8
+ # These two settings work together to allow you to limit a spec run
9
+ # to individual examples or groups you care about by tagging them with
10
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
11
+ # get run.
12
+ config.filter_run :focus
13
+ config.run_all_when_everything_filtered = true
14
+
15
+ # Many RSpec users commonly either run the entire suite or an individual
16
+ # file, and it's useful to allow more verbose output when running an
17
+ # individual spec file.
18
+ if config.files_to_run.one?
19
+ # Use the documentation formatter for detailed output,
20
+ # unless a formatter has already been configured
21
+ # (e.g. via a command-line flag).
22
+ config.default_formatter = 'doc'
23
+ end
24
+
25
+ # Print the 10 slowest examples and example groups at the
26
+ # end of the spec run, to help surface which specs are running
27
+ # particularly slow.
28
+ # config.profile_examples = 10
29
+
30
+ # Run specs in random order to surface order dependencies. If you find an
31
+ # order dependency and want to debug it, you can fix the order by providing
32
+ # the seed, which is printed after each run.
33
+ # --seed 1234
34
+ config.order = :random
35
+
36
+ # Seed global randomization in this process using the `--seed` CLI option.
37
+ # Setting this allows you to use `--seed` to deterministically reproduce
38
+ # test failures related to randomization by passing the same `--seed` value
39
+ # as the one that triggered the failure.
40
+ Kernel.srand config.seed
41
+
42
+ # rspec-expectations config goes here. You can use an alternate
43
+ # assertion/expectation library such as wrong or the stdlib/minitest
44
+ # assertions if you prefer.
45
+ config.expect_with :rspec do |expectations|
46
+ expectations.syntax = :expect
47
+ end
48
+
49
+ # rspec-mocks config goes here. You can use an alternate test double
50
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
51
+ config.mock_with :rspec do |mocks|
52
+ # Enable only the newer, non-monkey-patching expect syntax.
53
+ # For more details, see:
54
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
55
+ mocks.syntax = :expect
56
+
57
+ # Prevents you from mocking or stubbing a method that does not exist on
58
+ # a real object. This is generally recommended.
59
+ mocks.verify_partial_doubles = true
60
+ end
61
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: persistent_hash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Dean
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-07-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rails
@@ -16,14 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '5.0'
18
+ version: '7.2'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: '5.0'
25
+ version: '7.2'
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: mysql2
29
28
  requirement: !ruby/object:Gem::Requirement
@@ -116,7 +115,9 @@ executables: []
116
115
  extensions: []
117
116
  extra_rdoc_files: []
118
117
  files:
118
+ - CHANGELOG.md
119
119
  - MIT-LICENSE
120
+ - README.md
120
121
  - Rakefile
121
122
  - app/models/persistent_hash/formatter.rb
122
123
  - app/models/persistent_hash/hash.rb
@@ -127,11 +128,53 @@ files:
127
128
  - lib/persistent_hash/engine.rb
128
129
  - lib/persistent_hash/version.rb
129
130
  - lib/tasks/persistent_hash_tasks.rake
131
+ - spec/dummy/README.rdoc
132
+ - spec/dummy/Rakefile
133
+ - spec/dummy/app/assets/config/manifest.js
134
+ - spec/dummy/app/assets/javascripts/application.js
135
+ - spec/dummy/app/assets/stylesheets/application.css
136
+ - spec/dummy/app/controllers/application_controller.rb
137
+ - spec/dummy/app/helpers/application_helper.rb
138
+ - spec/dummy/app/views/layouts/application.html.erb
139
+ - spec/dummy/bin/bundle
140
+ - spec/dummy/bin/rails
141
+ - spec/dummy/bin/rake
142
+ - spec/dummy/bin/setup
143
+ - spec/dummy/config.ru
144
+ - spec/dummy/config/application.rb
145
+ - spec/dummy/config/boot.rb
146
+ - spec/dummy/config/database.yml
147
+ - spec/dummy/config/environment.rb
148
+ - spec/dummy/config/environments/development.rb
149
+ - spec/dummy/config/environments/production.rb
150
+ - spec/dummy/config/environments/test.rb
151
+ - spec/dummy/config/initializers/assets.rb
152
+ - spec/dummy/config/initializers/backtrace_silencers.rb
153
+ - spec/dummy/config/initializers/cookies_serializer.rb
154
+ - spec/dummy/config/initializers/filter_parameter_logging.rb
155
+ - spec/dummy/config/initializers/inflections.rb
156
+ - spec/dummy/config/initializers/mime_types.rb
157
+ - spec/dummy/config/initializers/persistent_hash.rb
158
+ - spec/dummy/config/initializers/session_store.rb
159
+ - spec/dummy/config/initializers/wrap_parameters.rb
160
+ - spec/dummy/config/locales/en.yml
161
+ - spec/dummy/config/routes.rb
162
+ - spec/dummy/config/secrets.yml
163
+ - spec/dummy/db/schema.rb
164
+ - spec/dummy/log/development.log
165
+ - spec/dummy/log/test.log
166
+ - spec/dummy/public/404.html
167
+ - spec/dummy/public/422.html
168
+ - spec/dummy/public/500.html
169
+ - spec/dummy/public/favicon.ico
170
+ - spec/dummy/tmp/local_secret.txt
171
+ - spec/models/persistent_hash/hash_spec.rb
172
+ - spec/rails_helper.rb
173
+ - spec/spec_helper.rb
130
174
  homepage: https://github.com/alexdean/persistent_hash
131
175
  licenses:
132
176
  - MIT
133
177
  metadata: {}
134
- post_install_message:
135
178
  rdoc_options: []
136
179
  require_paths:
137
180
  - lib
@@ -139,16 +182,57 @@ required_ruby_version: !ruby/object:Gem::Requirement
139
182
  requirements:
140
183
  - - ">="
141
184
  - !ruby/object:Gem::Version
142
- version: '0'
185
+ version: 3.3.0
143
186
  required_rubygems_version: !ruby/object:Gem::Requirement
144
187
  requirements:
145
188
  - - ">="
146
189
  - !ruby/object:Gem::Version
147
190
  version: '0'
148
191
  requirements: []
149
- rubyforge_project:
150
- rubygems_version: 2.7.6.2
151
- signing_key:
192
+ rubygems_version: 3.6.9
152
193
  specification_version: 4
153
194
  summary: ActiveRecord-based key/value store for Rails applications.
154
- test_files: []
195
+ test_files:
196
+ - spec/dummy/README.rdoc
197
+ - spec/dummy/Rakefile
198
+ - spec/dummy/app/assets/config/manifest.js
199
+ - spec/dummy/app/assets/javascripts/application.js
200
+ - spec/dummy/app/assets/stylesheets/application.css
201
+ - spec/dummy/app/controllers/application_controller.rb
202
+ - spec/dummy/app/helpers/application_helper.rb
203
+ - spec/dummy/app/views/layouts/application.html.erb
204
+ - spec/dummy/bin/bundle
205
+ - spec/dummy/bin/rails
206
+ - spec/dummy/bin/rake
207
+ - spec/dummy/bin/setup
208
+ - spec/dummy/config.ru
209
+ - spec/dummy/config/application.rb
210
+ - spec/dummy/config/boot.rb
211
+ - spec/dummy/config/database.yml
212
+ - spec/dummy/config/environment.rb
213
+ - spec/dummy/config/environments/development.rb
214
+ - spec/dummy/config/environments/production.rb
215
+ - spec/dummy/config/environments/test.rb
216
+ - spec/dummy/config/initializers/assets.rb
217
+ - spec/dummy/config/initializers/backtrace_silencers.rb
218
+ - spec/dummy/config/initializers/cookies_serializer.rb
219
+ - spec/dummy/config/initializers/filter_parameter_logging.rb
220
+ - spec/dummy/config/initializers/inflections.rb
221
+ - spec/dummy/config/initializers/mime_types.rb
222
+ - spec/dummy/config/initializers/persistent_hash.rb
223
+ - spec/dummy/config/initializers/session_store.rb
224
+ - spec/dummy/config/initializers/wrap_parameters.rb
225
+ - spec/dummy/config/locales/en.yml
226
+ - spec/dummy/config/routes.rb
227
+ - spec/dummy/config/secrets.yml
228
+ - spec/dummy/db/schema.rb
229
+ - spec/dummy/log/development.log
230
+ - spec/dummy/log/test.log
231
+ - spec/dummy/public/404.html
232
+ - spec/dummy/public/422.html
233
+ - spec/dummy/public/500.html
234
+ - spec/dummy/public/favicon.ico
235
+ - spec/dummy/tmp/local_secret.txt
236
+ - spec/models/persistent_hash/hash_spec.rb
237
+ - spec/rails_helper.rb
238
+ - spec/spec_helper.rb