enum_kit 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +46 -0
- data/.rspec +2 -0
- data/.rubocop.yml +21 -0
- data/.travis.yml +13 -0
- data/Gemfile +5 -0
- data/Guardfile +17 -0
- data/LICENSE +21 -0
- data/README.md +82 -0
- data/Rakefile +8 -0
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/config.ru +9 -0
- data/enum_kit.gemspec +35 -0
- data/lib/enum_kit/active_record_extensions/connection_adapters/postgresql/column_dumper.rb +29 -0
- data/lib/enum_kit/active_record_extensions/connection_adapters/postgresql/schema_dumper.rb +29 -0
- data/lib/enum_kit/active_record_extensions/connection_adapters/postgresql_adapter.rb +74 -0
- data/lib/enum_kit/active_record_extensions/migration/command_recorder.rb +45 -0
- data/lib/enum_kit/active_record_extensions/schema_dumper.rb +31 -0
- data/lib/enum_kit/active_record_patches/connection_adapters/postgresql/column_methods.rb +32 -0
- data/lib/enum_kit/active_record_patches/connection_adapters/postgresql/oid/enum.rb +32 -0
- data/lib/enum_kit/active_record_patches/connection_adapters/postgresql/oid/type_map_initializer.rb +27 -0
- data/lib/enum_kit/active_record_patches/enum/enum_type.rb +25 -0
- data/lib/enum_kit/active_record_patches/enum.rb +39 -0
- data/lib/enum_kit/active_record_patches/validations/pg_enum_validator.rb +31 -0
- data/lib/enum_kit/constants.rb +7 -0
- data/lib/enum_kit/helpers.rb +84 -0
- data/lib/enum_kit.rb +62 -0
- data/spec/active_record/base_spec.rb +15 -0
- data/spec/active_record/connection_adapters/postgresql_adapter_spec.rb +62 -0
- data/spec/active_record/validations/pg_enum_validator_spec.rb +19 -0
- data/spec/enum_kit/constants_spec.rb +11 -0
- data/spec/enum_kit/helpers_spec.rb +106 -0
- data/spec/internal/app/models/shirt.rb +7 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/db/schema.rb +10 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/spec_helper.rb +96 -0
- metadata +231 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :nodoc:
|
4
|
+
#
|
5
|
+
module ActiveRecord
|
6
|
+
# :nodoc:
|
7
|
+
#
|
8
|
+
module Validations
|
9
|
+
# Validates whether an enum's value is acceptable by comparing with the acceptable values defined in the PostgreSQL
|
10
|
+
# database.
|
11
|
+
#
|
12
|
+
class PgEnumValidator < ActiveModel::EachValidator
|
13
|
+
# Validate the given value is acceptable for the enum.
|
14
|
+
#
|
15
|
+
# @param record [ActiveRecord::Base] The record being validated.
|
16
|
+
# @param attribute [Symbol] The enum attribute being validated.
|
17
|
+
# @param value [String, Symbol, nil] The current value of the enum.
|
18
|
+
#
|
19
|
+
def validate_each(record, attribute, value)
|
20
|
+
values = record.class.pg_enum_values(attribute)
|
21
|
+
|
22
|
+
return if values.include?(value)
|
23
|
+
|
24
|
+
record.errors.add(attribute, options[:message] || :invalid, **options.except(:message).merge!(
|
25
|
+
attribute: record.class.human_attribute_name(attribute),
|
26
|
+
values: values.join(', ')
|
27
|
+
))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EnumKit
|
4
|
+
# Makes an underscored, lowercase form from the expression in the string.
|
5
|
+
#
|
6
|
+
# Changes '::' to '/' to convert namespaces to paths.
|
7
|
+
# This method is based on the `ActiveSupport::Inflector.underscore` method.
|
8
|
+
#
|
9
|
+
# @param value [String] A value to transform.
|
10
|
+
# @return [String] The underscored, lowercase form of the expression.
|
11
|
+
#
|
12
|
+
def self.underscore(value)
|
13
|
+
return value unless /[A-Z-]|::/.match?(value)
|
14
|
+
|
15
|
+
value = value.to_s.gsub('::', '/')
|
16
|
+
value.gsub!('PostgreSQL', 'Postgresql')
|
17
|
+
value.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
18
|
+
value.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
19
|
+
value.tr!('-', '_')
|
20
|
+
value.downcase!
|
21
|
+
value
|
22
|
+
end
|
23
|
+
|
24
|
+
# Convert a value into a String that can be used in SQL.
|
25
|
+
#
|
26
|
+
# @param value [Array|String|Symbol] A value to convert into SQL format.
|
27
|
+
# @return [String] The SQL representation of the value.
|
28
|
+
#
|
29
|
+
def self.sqlize(value)
|
30
|
+
case value
|
31
|
+
when Array
|
32
|
+
'(' + value.map { |v| sqlize(v) }.join(', ') + ')'
|
33
|
+
when String
|
34
|
+
ActiveRecord::Base.connection.quote(value)
|
35
|
+
when Symbol
|
36
|
+
sqlize(value.to_s)
|
37
|
+
else
|
38
|
+
raise ArgumentError, "Unable to convert value of type #{value.class} into SQL format."
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Sanitize the name of the enum.
|
43
|
+
#
|
44
|
+
# @param name [String|Symbol] An enum name.
|
45
|
+
# @return [String] The sanitized name.
|
46
|
+
#
|
47
|
+
def self.sanitize_name!(name)
|
48
|
+
raise ArgumentError, 'Enum names must be a String or a Symbol.' unless name.is_a?(String) || name.is_a?(Symbol)
|
49
|
+
|
50
|
+
name = name.to_s
|
51
|
+
|
52
|
+
return name if name =~ /^[a-z0-9_]+$/
|
53
|
+
|
54
|
+
raise ArgumentError, 'Enum names may contain only lowercase letters, numbers and underscores.'
|
55
|
+
end
|
56
|
+
|
57
|
+
# Sanitize a single value of an enum.
|
58
|
+
#
|
59
|
+
# @param value [String|Symbol] An enum value.
|
60
|
+
# @return [Array] The sanitized value.
|
61
|
+
#
|
62
|
+
def self.sanitize_value!(value)
|
63
|
+
raise ArgumentError, 'Enum values must be a String or a Symbol.' unless value.is_a?(String) || value.is_a?(Symbol)
|
64
|
+
|
65
|
+
value = value.to_s
|
66
|
+
|
67
|
+
return value if value =~ /^[a-z0-9_ ]+$/
|
68
|
+
|
69
|
+
raise ArgumentError, 'Enum values may contain only lowercase letters, numbers, underscores and spaces.'
|
70
|
+
end
|
71
|
+
|
72
|
+
# Sanitize the values of an enum.
|
73
|
+
#
|
74
|
+
# @param values [Array] An Array of String or Symbol values.
|
75
|
+
# @return [Array] A sanitized Array of String values.
|
76
|
+
#
|
77
|
+
def self.sanitize_values!(values)
|
78
|
+
return nil if values.nil?
|
79
|
+
|
80
|
+
raise ArgumentError, 'Enum values must be an Array of String and/or Symbol objects.' unless values.is_a?(Array)
|
81
|
+
|
82
|
+
values.map { |value| sanitize_value!(value) }
|
83
|
+
end
|
84
|
+
end
|
data/lib/enum_kit.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'enum_kit/constants'
|
4
|
+
require 'enum_kit/helpers'
|
5
|
+
|
6
|
+
# Used as a namespace to encapsulate the logic for the EnumKit gem.
|
7
|
+
#
|
8
|
+
module EnumKit
|
9
|
+
# Queue loading of the patches/extensions and database type registration for when `ActiveRecord` has loaded.
|
10
|
+
#
|
11
|
+
def self.load!
|
12
|
+
require 'active_record'
|
13
|
+
require 'active_record/connection_adapters/postgresql_adapter'
|
14
|
+
require 'active_support/lazy_load_hooks'
|
15
|
+
|
16
|
+
ActiveSupport.on_load(:active_record) do
|
17
|
+
EnumKit.load_patches!
|
18
|
+
EnumKit.load_extensions!
|
19
|
+
EnumKit.register_database_type!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Load the `ActiveRecord` monkey patches.
|
24
|
+
#
|
25
|
+
def self.load_patches!
|
26
|
+
require 'enum_kit/active_record_patches/connection_adapters/postgresql/column_methods'
|
27
|
+
require 'enum_kit/active_record_patches/connection_adapters/postgresql/oid/enum'
|
28
|
+
require 'enum_kit/active_record_patches/connection_adapters/postgresql/oid/type_map_initializer'
|
29
|
+
require 'enum_kit/active_record_patches/enum'
|
30
|
+
require 'enum_kit/active_record_patches/enum/enum_type'
|
31
|
+
require 'enum_kit/active_record_patches/validations/pg_enum_validator'
|
32
|
+
end
|
33
|
+
|
34
|
+
# Load the `ActiveRecord` extensions.
|
35
|
+
#
|
36
|
+
def self.load_extensions!
|
37
|
+
%w[
|
38
|
+
ConnectionAdapters::PostgreSQL::ColumnDumper
|
39
|
+
ConnectionAdapters::PostgreSQL::SchemaDumper
|
40
|
+
ConnectionAdapters::PostgreSQLAdapter
|
41
|
+
Migration::CommandRecorder
|
42
|
+
SchemaDumper
|
43
|
+
].each do |extension|
|
44
|
+
next unless Object.const_defined?("ActiveRecord::#{extension}")
|
45
|
+
|
46
|
+
require File.join('enum_kit', 'active_record_extensions', EnumKit.underscore(extension))
|
47
|
+
|
48
|
+
target_constant = Object.const_get("ActiveRecord::#{extension}")
|
49
|
+
extension_constant = Object.const_get("EnumKit::ActiveRecordExtensions::#{extension}")
|
50
|
+
|
51
|
+
target_constant.prepend(extension_constant)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Register `:enum` as a native database type.
|
56
|
+
#
|
57
|
+
def self.register_database_type!
|
58
|
+
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:enum] = { name: 'enum' }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
EnumKit.load!
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe ActiveRecord::Base do
|
4
|
+
describe '.pg_enum' do
|
5
|
+
it 'is defined' do
|
6
|
+
expect(described_class).to respond_to(:pg_enum)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.pg_enum_values' do
|
11
|
+
it 'is defined' do
|
12
|
+
expect(described_class).to respond_to(:pg_enum_values)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe ActiveRecord::ConnectionAdapters::PostgreSQLAdapter do
|
4
|
+
subject(:connection) { ActiveRecord::Base.connection }
|
5
|
+
|
6
|
+
describe '#create_enum' do
|
7
|
+
after { connection.execute 'DROP TYPE IF EXISTS an_enum' }
|
8
|
+
|
9
|
+
it 'is defined' do
|
10
|
+
expect(connection).to respond_to(:create_enum)
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when called with valid arguments' do
|
14
|
+
subject { connection.create_enum(:an_enum, [:first_value, 'second value']) }
|
15
|
+
|
16
|
+
it 'creates an enum' do
|
17
|
+
expect(subject.result_status).to eq(PG::PGRES_COMMAND_OK)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when called with a malformed name' do
|
22
|
+
subject { connection.create_enum('an enum', [:first_value, 'second value']) }
|
23
|
+
|
24
|
+
it 'raises an ArgumentError' do
|
25
|
+
expect { subject }.to raise_exception(ArgumentError)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when called with malformed values' do
|
30
|
+
subject { connection.create_enum(:an_enum, [:good_value, 'bad$value']) }
|
31
|
+
|
32
|
+
it 'raises an ArgumentError' do
|
33
|
+
expect { subject }.to raise_exception(ArgumentError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#drop_enum' do
|
39
|
+
before { connection.execute "CREATE TYPE an_enum AS ENUM ('first', 'second')" }
|
40
|
+
after { connection.execute 'DROP TYPE IF EXISTS an_enum' }
|
41
|
+
|
42
|
+
it 'is defined' do
|
43
|
+
expect(connection).to respond_to(:drop_enum)
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when called with an existing enum' do
|
47
|
+
subject { connection.drop_enum(:an_enum) }
|
48
|
+
|
49
|
+
it 'drops the enum' do
|
50
|
+
expect(subject.result_status).to eq(PG::PGRES_COMMAND_OK)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when called with a non-existent enum' do
|
55
|
+
subject { connection.drop_enum(:non_existent_enum) }
|
56
|
+
|
57
|
+
it 'raises ActiveRecord::StatementInvalid' do
|
58
|
+
expect { subject }.to raise_exception(ActiveRecord::StatementInvalid)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe ActiveRecord::Validations::PgEnumValidator do
|
4
|
+
subject { Shirt.create(name: 'Plain Shirt', size: :small) }
|
5
|
+
|
6
|
+
it 'permits known values' do
|
7
|
+
expect { subject.update!(size: :large) }.not_to raise_exception
|
8
|
+
expect { subject.update!(size: :medium) }.not_to raise_exception
|
9
|
+
expect { subject.update!(size: :small) }.not_to raise_exception
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'rejects unknown values' do
|
13
|
+
expect { subject.update!(size: :other) }.to raise_exception(ActiveRecord::RecordInvalid)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'rejects nil values' do
|
17
|
+
expect { subject.update!(size: nil) }.to raise_exception(ActiveRecord::RecordInvalid)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe EnumKit do
|
4
|
+
describe '.underscore' do
|
5
|
+
it 'converts camel case into snake case' do
|
6
|
+
expect(described_class.underscore('EnumKit')).to eq('enum_kit')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'converts namespaces into paths' do
|
10
|
+
expect(described_class.underscore('EnumKit::Example')).to eq('enum_kit/example')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'treats PostgreSQL as an acronym' do
|
14
|
+
expect(described_class.underscore('PostgreSQL')).to eq('postgresql')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.sqlize' do
|
19
|
+
context 'with a String' do
|
20
|
+
subject { described_class.sqlize('value') }
|
21
|
+
|
22
|
+
it 'returns a quoted String' do
|
23
|
+
expect(subject).to eq("'value'")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with a Symbol' do
|
28
|
+
subject { described_class.sqlize(:value) }
|
29
|
+
|
30
|
+
it 'returns a quoted String' do
|
31
|
+
expect(subject).to eq("'value'")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'with an Array' do
|
36
|
+
subject { described_class.sqlize(%i[one two three]) }
|
37
|
+
|
38
|
+
it 'returns a SQL array representation' do
|
39
|
+
expect(subject).to eq("('one', 'two', 'three')")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.sanitize_name!' do
|
45
|
+
it 'permits lowercase letters' do
|
46
|
+
expect(described_class.sanitize_name!('abc')).to eq('abc')
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'permits numbers' do
|
50
|
+
expect(described_class.sanitize_name!('123')).to eq('123')
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'permits underscores' do
|
54
|
+
expect(described_class.sanitize_name!('_')).to eq('_')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'rejects hyphens' do
|
58
|
+
expect { described_class.sanitize_name!('-') }.to raise_exception(ArgumentError)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'rejects spaces' do
|
62
|
+
expect { described_class.sanitize_name!(' ') }.to raise_exception(ArgumentError)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'rejects uppercase letters' do
|
66
|
+
expect { described_class.sanitize_name!('ABC') }.to raise_exception(ArgumentError)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '.sanitize_value!' do
|
71
|
+
it 'permits lowercase letters' do
|
72
|
+
expect(described_class.sanitize_value!('abc')).to eq('abc')
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'permits numbers' do
|
76
|
+
expect(described_class.sanitize_value!('123')).to eq('123')
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'permits spaces' do
|
80
|
+
expect(described_class.sanitize_value!(' ')).to eq(' ')
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'permits underscores' do
|
84
|
+
expect(described_class.sanitize_value!('_')).to eq('_')
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'rejects hyphens' do
|
88
|
+
expect { described_class.sanitize_value!('-') }.to raise_exception(ArgumentError)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'rejects uppercase letters' do
|
92
|
+
expect { described_class.sanitize_value!('ABC') }.to raise_exception(ArgumentError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '.sanitize_values!' do
|
97
|
+
subject { described_class.sanitize_values!(%i[one two three]) }
|
98
|
+
|
99
|
+
it 'calls .sanitize_value! for each of the inputs' do
|
100
|
+
expect(described_class).to receive(:sanitize_value!).with(:one).once
|
101
|
+
expect(described_class).to receive(:sanitize_value!).with(:two).once
|
102
|
+
expect(described_class).to receive(:sanitize_value!).with(:three).once
|
103
|
+
subject
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
*.log
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Conventionally, all specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
4
|
+
# The `.rspec` file contains `--require spec_helper` which will cause this file to always be loaded,
|
5
|
+
# without a need to explicitly require it in any files.
|
6
|
+
#
|
7
|
+
# Given that it is always loaded, you are encouraged to keep this file as light-weight as possible.
|
8
|
+
# Requiring heavyweight dependencies from this file will add to the boot time of your test suite on EVERY test run,
|
9
|
+
# even for an individual file that may not need all of that loaded. Instead, consider making a separate helper file
|
10
|
+
# that requires the additional dependencies and performs the additional setup, and require it from the spec files
|
11
|
+
# that actually need it.
|
12
|
+
#
|
13
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
14
|
+
|
15
|
+
# Bundler
|
16
|
+
require 'bundler'
|
17
|
+
|
18
|
+
Bundler.require :default, :test
|
19
|
+
|
20
|
+
# Combustion
|
21
|
+
require 'combustion'
|
22
|
+
|
23
|
+
Combustion.initialize! :active_record
|
24
|
+
|
25
|
+
# Rails
|
26
|
+
require 'rspec/rails'
|
27
|
+
|
28
|
+
# RSpec
|
29
|
+
RSpec.configure do |config|
|
30
|
+
# rspec-expectations config goes here. You can use an alternate assertion/expectation library such as wrong or the
|
31
|
+
# stdlib/minitest assertions if you prefer.
|
32
|
+
config.expect_with :rspec do |expectations|
|
33
|
+
# This option will default to `true` in RSpec 4.
|
34
|
+
# It makes the `description` and `failure_message` of custom matchers include text for helper methods defined using
|
35
|
+
# `chain`, e.g.:
|
36
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
37
|
+
# # => "be bigger than 2 and smaller than 4"
|
38
|
+
# ...rather than:
|
39
|
+
# # => "be bigger than 2"
|
40
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
41
|
+
end
|
42
|
+
|
43
|
+
# rspec-mocks config goes here. You can use an alternate test double library (such as bogus or mocha) by changing the
|
44
|
+
# `mock_with` option here.
|
45
|
+
config.mock_with :rspec do |mocks|
|
46
|
+
# Prevents you from mocking or stubbing a method that does not exist on a real object.
|
47
|
+
# This is generally recommended, and will default to `true` in RSpec 4.
|
48
|
+
mocks.verify_partial_doubles = true
|
49
|
+
end
|
50
|
+
|
51
|
+
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will have no way to turn it off -- the option
|
52
|
+
# exists only for backwards compatibility in RSpec 3).
|
53
|
+
# It causes shared context metadata to be inherited by the metadata hash of host groups and examples, rather than
|
54
|
+
# triggering implicit auto-inclusion in groups with matching metadata.
|
55
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
56
|
+
|
57
|
+
# This allows you to limit a spec run to individual examples or groups you care about by tagging them with `:focus`
|
58
|
+
# metadata. When nothing is tagged with `:focus`, all examples get run.
|
59
|
+
# RSpec also provides aliases for `it`, `describe`, and `context` that include `:focus` metadata: `fit`, `fdescribe`
|
60
|
+
# and `fcontext`, respectively.
|
61
|
+
config.filter_run_when_matching :focus
|
62
|
+
|
63
|
+
# Allows RSpec to persist some state between runs in order to support the `--only-failures` and `--next-failure` CLI
|
64
|
+
# options. We recommend you configure your source control system to ignore this file.
|
65
|
+
config.example_status_persistence_file_path = 'spec/examples.txt'
|
66
|
+
|
67
|
+
# Limits the available syntax to the non-monkey patched syntax that is recommended. For more details, see:
|
68
|
+
# - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
|
69
|
+
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
70
|
+
# - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
|
71
|
+
config.disable_monkey_patching!
|
72
|
+
|
73
|
+
# Many RSpec users commonly either run the entire suite or an individual file, and it's useful to allow more verbose
|
74
|
+
# output when running an individual spec file.
|
75
|
+
if config.files_to_run.one?
|
76
|
+
# Use the documentation formatter for detailed output, unless a formatter has already been configured (e.g. via a
|
77
|
+
# command-line flag).
|
78
|
+
config.default_formatter = 'doc'
|
79
|
+
end
|
80
|
+
|
81
|
+
# Print the 10 slowest examples and example groups at the end of the spec run, to help surface which specs are
|
82
|
+
# running particularly slow.
|
83
|
+
# config.profile_examples = 10
|
84
|
+
|
85
|
+
# Run specs in random order to surface order dependencies. If you find an order dependency and want to debug it, you
|
86
|
+
# can fix the order by providing the seed, which is printed after each run.
|
87
|
+
# --seed 1234
|
88
|
+
config.order = :random
|
89
|
+
|
90
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
91
|
+
# Setting this allows you to use `--seed` to deterministically reproduce test failures related to randomization by
|
92
|
+
# passing the same `--seed` value as the one that triggered the failure.
|
93
|
+
Kernel.srand config.seed
|
94
|
+
end
|
95
|
+
|
96
|
+
Dir[File.expand_path('support/**/*.rb', __dir__)].each { |path| require(path) }
|