dry-struct 1.0.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,28 +1,41 @@
1
- require 'dry/types/compiler'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Dry
4
4
  class Struct
5
5
  # @private
6
- class StructBuilder < Dry::Types::Compiler
6
+ class StructBuilder < Compiler
7
7
  attr_reader :struct
8
8
 
9
9
  def initialize(struct)
10
- super(Dry::Types)
10
+ super(Types)
11
11
  @struct = struct
12
12
  end
13
13
 
14
14
  # @param [Symbol|String] attr_name the name of the nested type
15
- # @param [Dry::Struct,Dry::Types::Type::Array] type the superclass of the nested struct
15
+ # @param [Dry::Struct,Dry::Types::Type::Array,Undefined] type the superclass
16
+ # of the nested struct
16
17
  # @yield the body of the nested struct
17
18
  def call(attr_name, type, &block)
18
19
  const_name = const_name(type, attr_name)
19
20
  check_name(const_name)
20
21
 
21
- new_type = Class.new(parent(type), &block)
22
+ builder = self
23
+ parent = parent(type)
24
+
25
+ new_type = ::Class.new(Undefined.default(parent, struct.abstract_class)) do
26
+ if Undefined.equal?(parent)
27
+ schema builder.struct.schema.clear
28
+ end
29
+
30
+ class_exec(&block)
31
+ end
32
+
22
33
  struct.const_set(const_name, new_type)
23
34
 
24
35
  if array?(type)
25
36
  type.of(new_type)
37
+ elsif optional?(type)
38
+ new_type.optional
26
39
  else
27
40
  new_type
28
41
  end
@@ -30,37 +43,46 @@ module Dry
30
43
 
31
44
  private
32
45
 
46
+ def type?(type)
47
+ type.is_a?(Types::Type)
48
+ end
49
+
33
50
  def array?(type)
34
- type.is_a?(Types::Type) && type.primitive.equal?(Array)
51
+ type?(type) && !type.optional? && type.primitive.equal?(::Array)
52
+ end
53
+
54
+ def optional?(type)
55
+ type?(type) && type.optional?
35
56
  end
36
57
 
37
58
  def parent(type)
38
59
  if array?(type)
39
60
  visit(type.to_ast)
61
+ elsif optional?(type)
62
+ type.right
40
63
  else
41
- type || default_superclass
64
+ type
42
65
  end
43
66
  end
44
67
 
45
- def default_superclass
46
- struct < Value ? Value : Struct
47
- end
48
-
49
68
  def const_name(type, attr_name)
50
- snake_name = if array?(type)
51
- Dry::Core::Inflector.singularize(attr_name)
52
- else
53
- attr_name
54
- end
55
-
56
- Dry::Core::Inflector.camelize(snake_name)
69
+ snake_name =
70
+ if array?(type)
71
+ Core::Inflector.singularize(attr_name)
72
+ else
73
+ attr_name
74
+ end
75
+
76
+ Core::Inflector.camelize(snake_name)
57
77
  end
58
78
 
59
79
  def check_name(name)
60
- raise(
61
- Struct::Error,
62
- "Can't create nested attribute - `#{struct}::#{name}` already defined"
63
- ) if struct.const_defined?(name, false)
80
+ if struct.const_defined?(name, false)
81
+ raise(
82
+ Error,
83
+ "Can't create nested attribute - `#{struct}::#{name}` already defined"
84
+ )
85
+ end
64
86
  end
65
87
 
66
88
  def visit_constrained(node)
@@ -70,11 +92,11 @@ module Dry
70
92
 
71
93
  def visit_array(node)
72
94
  member, * = node
73
- member
95
+ visit(member)
74
96
  end
75
97
 
76
98
  def visit_nominal(*)
77
- default_superclass
99
+ Undefined
78
100
  end
79
101
 
80
102
  def visit_constructor(node)
@@ -1,5 +1,4 @@
1
- require 'dry/types/sum'
2
- require 'dry/types/printer'
1
+ # frozen_string_literal: true
3
2
 
4
3
  module Dry
5
4
  class Struct
@@ -12,9 +11,10 @@ module Dry
12
11
  right.try_struct(input) { super }
13
12
  end
14
13
  end
14
+
15
15
  # @param [Hash{Symbol => Object},Dry::Struct] input
16
16
  # @yieldparam [Dry::Types::Result::Failure] failure
17
- # @yieldreturn [Dry::Types::ResultResult]
17
+ # @yieldreturn [Dry::Types::Result]
18
18
  # @return [Dry::Types::Result]
19
19
  def try(input)
20
20
  if input.is_a?(Struct)
@@ -43,9 +43,9 @@ module Dry
43
43
  protected
44
44
 
45
45
  # @private
46
- def try_struct(input)
46
+ def try_struct(input, &block)
47
47
  left.try_struct(input) do
48
- right.try_struct(input) { yield }
48
+ right.try_struct(input, &block)
49
49
  end
50
50
  end
51
51
  end
@@ -1,14 +1,18 @@
1
- require 'ice_nine'
1
+ # frozen_string_literal: true
2
+
3
+ require "ice_nine"
2
4
 
3
5
  module Dry
4
6
  class Struct
7
+ extend Core::Deprecations[:"dry-struct"]
8
+
5
9
  # {Value} objects behave like {Struct}s but *deeply frozen*
6
10
  # using [`ice_nine`](https://github.com/dkubb/ice_nine)
7
11
  #
8
12
  # @example
9
13
  # class Location < Dry::Struct::Value
10
- # attribute :lat, Types::Strict::Float
11
- # attribute :lng, Types::Strict::Float
14
+ # attribute :lat, Types::Float
15
+ # attribute :lng, Types::Float
12
16
  # end
13
17
  #
14
18
  # loc1 = Location.new(lat: 1.23, lng: 4.56)
@@ -20,12 +24,16 @@ module Dry
20
24
  #
21
25
  # @see https://github.com/dkubb/ice_nine
22
26
  class Value < self
27
+ abstract
28
+
23
29
  # @param (see ClassInterface#new)
24
30
  # @return [Value]
25
31
  # @see https://github.com/dkubb/ice_nine
26
32
  def self.new(*)
27
- IceNine.deep_freeze(super)
33
+ ::IceNine.deep_freeze(super)
28
34
  end
29
35
  end
36
+
37
+ deprecate_constant :Value
30
38
  end
31
39
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  class Struct
3
5
  # @private
4
- VERSION = '1.0.0'.freeze
6
+ VERSION = "1.6.0"
5
7
  end
6
8
  end
data/lib/dry/struct.rb CHANGED
@@ -1,13 +1,13 @@
1
- require 'dry-types'
2
- require 'dry-equalizer'
3
- require 'dry/core/extensions'
4
- require 'dry/core/constants'
1
+ # frozen_string_literal: true
5
2
 
6
- require 'dry/struct/version'
7
- require 'dry/struct/errors'
8
- require 'dry/struct/class_interface'
9
- require 'dry/struct/hashify'
10
- require 'dry/struct/struct_builder'
3
+ require "weakref"
4
+
5
+ require "dry/core"
6
+ require "dry/types"
7
+
8
+ require "dry/struct/class_interface"
9
+ require "dry/struct/errors"
10
+ require "dry/struct/version"
11
11
 
12
12
  module Dry
13
13
  # Constructor method for easily creating a {Dry::Struct}.
@@ -16,21 +16,21 @@ module Dry
16
16
  # require 'dry-struct'
17
17
  #
18
18
  # module Types
19
- # include Dry.Types
19
+ # include Dry.Types()
20
20
  # end
21
21
  #
22
- # Person = Dry.Struct(name: Types::Strict::String, age: Types::Strict::Int)
22
+ # Person = Dry.Struct(name: Types::String, age: Types::Integer)
23
23
  # matz = Person.new(name: "Matz", age: 52)
24
24
  # matz.name #=> "Matz"
25
25
  # matz.age #=> 52
26
26
  #
27
- # Test = Dry.Struct(expected: Types::Strict::String) { input(input.strict) }
27
+ # Test = Dry.Struct(expected: Types::String) { schema(schema.strict) }
28
28
  # Test[expected: "foo", unexpected: "bar"]
29
29
  # #=> Dry::Struct::Error: [Test.new] unexpected keys [:unexpected] in Hash input
30
30
  def self.Struct(attributes = Dry::Core::Constants::EMPTY_HASH, &block)
31
31
  Class.new(Dry::Struct) do
32
32
  attributes.each { |a, type| attribute a, type }
33
- instance_eval(&block) if block
33
+ module_eval(&block) if block
34
34
  end
35
35
  end
36
36
 
@@ -60,7 +60,7 @@ module Dry
60
60
  # require 'dry-struct'
61
61
  #
62
62
  # module Types
63
- # include Dry.Types
63
+ # include Dry.Types()
64
64
  # end
65
65
  #
66
66
  # class Book < Dry::Struct
@@ -82,18 +82,41 @@ module Dry
82
82
  # refactoring.title #=> 'Refactoring'
83
83
  # refactoring.subtitle #=> 'Improving the Design of Existing Code'
84
84
  class Struct
85
- extend Dry::Core::Extensions
86
- include Dry::Core::Constants
85
+ extend Core::Extensions
86
+ include Core::Constants
87
87
  extend ClassInterface
88
+ extend Core::Deprecations[:"dry-struct"]
89
+
90
+ class << self
91
+ # override `Dry::Types::Builder#prepend`
92
+ define_method(:prepend, ::Module.method(:prepend))
93
+
94
+ def loader
95
+ @loader ||= ::Zeitwerk::Loader.new.tap do |loader|
96
+ root = ::File.expand_path("..", __dir__)
97
+ loader.tag = "dry-struct"
98
+ loader.inflector = ::Zeitwerk::GemInflector.new("#{root}/dry-struct.rb")
99
+ loader.push_dir(root)
100
+ loader.ignore(
101
+ "#{root}/dry-struct.rb",
102
+ "#{root}/dry/struct/{class_interface,errors,extensions,printer,value,version}.rb",
103
+ "#{root}/dry/struct/extensions"
104
+ )
105
+ end
106
+ end
107
+ end
108
+
109
+ loader.setup
88
110
 
89
- include Dry::Equalizer(:__attributes__)
111
+ include ::Dry::Equalizer(:__attributes__, inspect: false, immutable: true)
90
112
 
91
113
  # {Dry::Types::Hash::Schema} subclass with specific behaviour defined for
92
114
  # @return [Dry::Types::Hash::Schema]
93
115
  defines :schema
94
- schema Types['coercible.hash'].schema(EMPTY_HASH)
116
+ schema Types["coercible.hash"].schema(EMPTY_HASH)
95
117
 
96
- @meta = EMPTY_HASH
118
+ defines :abstract_class
119
+ abstract
97
120
 
98
121
  # @!attribute [Hash{Symbol => Object}] attributes
99
122
  attr_reader :attributes
@@ -111,8 +134,8 @@ module Dry
111
134
  #
112
135
  # @example
113
136
  # class Book < Dry::Struct
114
- # attribute :title, Types::Strict::String
115
- # attribute :subtitle, Types::Strict::String.optional
137
+ # attribute :title, Types::String
138
+ # attribute :subtitle, Types::String.optional
116
139
  # end
117
140
  #
118
141
  # rom_n_roda = Book.new(
@@ -122,7 +145,7 @@ module Dry
122
145
  # rom_n_roda[:title] #=> 'Web Development with ROM and Roda'
123
146
  # rom_n_roda[:subtitle] #=> nil
124
147
  def [](name)
125
- @attributes.fetch(name) { raise MissingAttributeError.new(name) }
148
+ @attributes.fetch(name) { raise MissingAttributeError, name }
126
149
  end
127
150
 
128
151
  # Converts the {Dry::Struct} to a hash with keys representing
@@ -132,8 +155,8 @@ module Dry
132
155
  #
133
156
  # @example
134
157
  # class Book < Dry::Struct
135
- # attribute :title, Types::Strict::String
136
- # attribute :subtitle, Types::Strict::String.optional
158
+ # attribute :title, Types::String
159
+ # attribute :subtitle, Types::String.optional
137
160
  # end
138
161
  #
139
162
  # rom_n_roda = Book.new(
@@ -142,12 +165,13 @@ module Dry
142
165
  # )
143
166
  # rom_n_roda.to_hash
144
167
  # #=> {title: 'Web Development with ROM and Roda', subtitle: nil}
145
- def to_hash
168
+ def to_h
146
169
  self.class.schema.each_with_object({}) do |key, result|
147
170
  result[key.name] = Hashify[self[key.name]] if attributes.key?(key.name)
148
171
  end
149
172
  end
150
- alias_method :to_h, :to_hash
173
+ # TODO: remove in 2.0
174
+ alias_method :to_hash, :to_h
151
175
 
152
176
  # Create a copy of {Dry::Struct} with overriden attributes
153
177
  #
@@ -157,8 +181,8 @@ module Dry
157
181
  #
158
182
  # @example
159
183
  # class Book < Dry::Struct
160
- # attribute :title, Types::Strict::String
161
- # attribute :subtitle, Types::Strict::String.optional
184
+ # attribute :title, Types::String
185
+ # attribute :subtitle, Types::String.optional
162
186
  # end
163
187
  #
164
188
  # rom_n_roda = Book.new(
@@ -170,10 +194,14 @@ module Dry
170
194
  # rom_n_roda.new(subtitle: '3rd edition')
171
195
  # #=> #<Book title="Web Development with ROM and Roda" subtitle="3rd edition">
172
196
  def new(changeset)
173
- new_attributes = self.class.schema.apply(changeset, skip_missing: true, resolve_defaults: false)
197
+ new_attributes = self.class.schema.apply(
198
+ changeset,
199
+ skip_missing: true,
200
+ resolve_defaults: false
201
+ )
174
202
  self.class.load(__attributes__.merge(new_attributes))
175
- rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError => error
176
- raise Struct::Error, "[#{self}.new] #{error}"
203
+ rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError => e
204
+ raise Error, "[#{self}.new] #{e}"
177
205
  end
178
206
  alias_method :__new__, :new
179
207
 
@@ -181,11 +209,18 @@ module Dry
181
209
  def inspect
182
210
  klass = self.class
183
211
  attrs = klass.attribute_names.map { |key| " #{key}=#{@attributes[key].inspect}" }.join
184
- "#<#{ klass.name || klass.inspect }#{ attrs }>"
212
+ "#<#{klass.name || klass.inspect}#{attrs}>"
213
+ end
214
+
215
+ # Pattern matching support
216
+ #
217
+ # @api private
218
+ def deconstruct_keys(_keys)
219
+ attributes
185
220
  end
186
221
  end
187
222
  end
188
223
 
189
- require 'dry/struct/value'
190
- require 'dry/struct/extensions'
191
- require 'dry/struct/printer'
224
+ require "dry/struct/extensions"
225
+ require "dry/struct/printer"
226
+ require "dry/struct/value"
data/lib/dry-struct.rb CHANGED
@@ -1 +1,3 @@
1
- require 'dry/struct'
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/struct"
metadata CHANGED
@@ -1,77 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-23 00:00:00.000000000 Z
11
+ date: 2022-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: dry-equalizer
14
+ name: dry-core
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.2'
19
+ version: '1.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '0.2'
29
+ version: '1.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: dry-types
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
- - - "~>"
37
+ - - ">="
32
38
  - !ruby/object:Gem::Version
33
- version: '1.0'
39
+ version: '1.7'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '2'
34
43
  type: :runtime
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
- - - "~>"
47
+ - - ">="
39
48
  - !ruby/object:Gem::Version
40
- version: '1.0'
49
+ version: '1.7'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '2'
41
53
  - !ruby/object:Gem::Dependency
42
- name: dry-core
54
+ name: ice_nine
43
55
  requirement: !ruby/object:Gem::Requirement
44
56
  requirements:
45
57
  - - "~>"
46
58
  - !ruby/object:Gem::Version
47
- version: '0.4'
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: 0.4.3
59
+ version: '0.11'
51
60
  type: :runtime
52
61
  prerelease: false
53
62
  version_requirements: !ruby/object:Gem::Requirement
54
63
  requirements:
55
64
  - - "~>"
56
65
  - !ruby/object:Gem::Version
57
- version: '0.4'
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 0.4.3
66
+ version: '0.11'
61
67
  - !ruby/object:Gem::Dependency
62
- name: ice_nine
68
+ name: zeitwerk
63
69
  requirement: !ruby/object:Gem::Requirement
64
70
  requirements:
65
71
  - - "~>"
66
72
  - !ruby/object:Gem::Version
67
- version: '0.11'
73
+ version: '2.6'
68
74
  type: :runtime
69
75
  prerelease: false
70
76
  version_requirements: !ruby/object:Gem::Requirement
71
77
  requirements:
72
78
  - - "~>"
73
79
  - !ruby/object:Gem::Version
74
- version: '0.11'
80
+ version: '2.6'
75
81
  - !ruby/object:Gem::Dependency
76
82
  name: bundler
77
83
  requirement: !ruby/object:Gem::Requirement
@@ -90,71 +96,59 @@ dependencies:
90
96
  name: rake
91
97
  requirement: !ruby/object:Gem::Requirement
92
98
  requirements:
93
- - - "~>"
99
+ - - ">="
94
100
  - !ruby/object:Gem::Version
95
- version: '11.0'
101
+ version: '0'
96
102
  type: :development
97
103
  prerelease: false
98
104
  version_requirements: !ruby/object:Gem::Requirement
99
105
  requirements:
100
- - - "~>"
106
+ - - ">="
101
107
  - !ruby/object:Gem::Version
102
- version: '11.0'
108
+ version: '0'
103
109
  - !ruby/object:Gem::Dependency
104
110
  name: rspec
105
111
  requirement: !ruby/object:Gem::Requirement
106
112
  requirements:
107
- - - "~>"
113
+ - - ">="
108
114
  - !ruby/object:Gem::Version
109
- version: '3.3'
115
+ version: '0'
110
116
  type: :development
111
117
  prerelease: false
112
118
  version_requirements: !ruby/object:Gem::Requirement
113
119
  requirements:
114
- - - "~>"
120
+ - - ">="
115
121
  - !ruby/object:Gem::Version
116
- version: '3.3'
122
+ version: '0'
117
123
  - !ruby/object:Gem::Dependency
118
124
  name: yard
119
125
  requirement: !ruby/object:Gem::Requirement
120
126
  requirements:
121
- - - "~>"
127
+ - - ">="
122
128
  - !ruby/object:Gem::Version
123
- version: 0.9.5
129
+ version: '0'
124
130
  type: :development
125
131
  prerelease: false
126
132
  version_requirements: !ruby/object:Gem::Requirement
127
133
  requirements:
128
- - - "~>"
134
+ - - ">="
129
135
  - !ruby/object:Gem::Version
130
- version: 0.9.5
131
- description: Typed structs and value objects.
136
+ version: '0'
137
+ description: Typed structs and value objects
132
138
  email:
133
139
  - piotr.solnica@gmail.com
134
140
  executables: []
135
141
  extensions: []
136
142
  extra_rdoc_files: []
137
143
  files:
138
- - ".gitignore"
139
- - ".rspec"
140
- - ".travis.yml"
141
- - ".yardopts"
142
144
  - CHANGELOG.md
143
- - CONTRIBUTING.md
144
- - Gemfile
145
145
  - LICENSE
146
146
  - README.md
147
- - Rakefile
148
- - benchmarks/basic.rb
149
- - benchmarks/constrained.rb
150
- - benchmarks/profile_instantiation.rb
151
- - benchmarks/setup.rb
152
- - bin/console
153
- - bin/setup
154
147
  - dry-struct.gemspec
155
148
  - lib/dry-struct.rb
156
149
  - lib/dry/struct.rb
157
150
  - lib/dry/struct/class_interface.rb
151
+ - lib/dry/struct/compiler.rb
158
152
  - lib/dry/struct/constructor.rb
159
153
  - lib/dry/struct/errors.rb
160
154
  - lib/dry/struct/extensions.rb
@@ -165,14 +159,14 @@ files:
165
159
  - lib/dry/struct/sum.rb
166
160
  - lib/dry/struct/value.rb
167
161
  - lib/dry/struct/version.rb
168
- - log/.gitkeep
169
- homepage: https://github.com/dry-rb/dry-struct
162
+ homepage: https://dry-rb.org/gems/dry-struct
170
163
  licenses:
171
164
  - MIT
172
165
  metadata:
173
166
  allowed_push_host: https://rubygems.org
174
- changelog_uri: https://github.com/dry-rb/dry-struct/blob/master/CHANGELOG.md
167
+ changelog_uri: https://github.com/dry-rb/dry-struct/blob/main/CHANGELOG.md
175
168
  source_code_uri: https://github.com/dry-rb/dry-struct
169
+ bug_tracker_uri: https://github.com/dry-rb/dry-struct/issues
176
170
  post_install_message:
177
171
  rdoc_options: []
178
172
  require_paths:
@@ -181,15 +175,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
181
175
  requirements:
182
176
  - - ">="
183
177
  - !ruby/object:Gem::Version
184
- version: 2.4.0
178
+ version: 2.7.0
185
179
  required_rubygems_version: !ruby/object:Gem::Requirement
186
180
  requirements:
187
181
  - - ">="
188
182
  - !ruby/object:Gem::Version
189
183
  version: '0'
190
184
  requirements: []
191
- rubygems_version: 3.0.3
185
+ rubygems_version: 3.1.6
192
186
  signing_key:
193
187
  specification_version: 4
194
- summary: Typed structs and value objects.
188
+ summary: Typed structs and value objects
195
189
  test_files: []
data/.gitignore DELETED
@@ -1,12 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- *.log
11
-
12
- .DS_Store
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --require ./spec/spec_helper
data/.travis.yml DELETED
@@ -1,29 +0,0 @@
1
- language: ruby
2
- dist: trusty
3
- sudo: required
4
- bundler_args: --without benchmarks tools
5
- script:
6
- - bundle exec rake spec
7
- after_success:
8
- - '[ -d coverage ] && bundle exec codeclimate-test-reporter'
9
- rvm:
10
- - 2.4.5
11
- - 2.5.5
12
- - 2.6.3
13
- - jruby-9.2.7.0
14
- - truffleruby
15
- env:
16
- global:
17
- - COVERAGE=true
18
- - JRUBY_OPTS='--dev -J-Xmx1024M'
19
- matrix:
20
- allow_failures:
21
- - rvm: truffleruby
22
- notifications:
23
- email: false
24
- webhooks:
25
- urls:
26
- - https://webhooks.gitter.im/e/19098b4253a72c9796db
27
- on_success: change # options: [always|never|change] default: always
28
- on_failure: always # options: [always|never|change] default: always
29
- on_start: false # default: false