mixture 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/Gemfile +5 -1
- data/Gemfile.lock +3 -1
- data/README.md +25 -2
- data/lib/mixture/attribute.rb +6 -3
- data/lib/mixture/coerce/array.rb +20 -5
- data/lib/mixture/coerce/base.rb +62 -26
- data/lib/mixture/coerce/class.rb +12 -0
- data/lib/mixture/coerce/date.rb +10 -10
- data/lib/mixture/coerce/datetime.rb +10 -10
- data/lib/mixture/coerce/float.rb +9 -9
- data/lib/mixture/coerce/hash.rb +10 -4
- data/lib/mixture/coerce/integer.rb +9 -9
- data/lib/mixture/coerce/nil.rb +10 -10
- data/lib/mixture/coerce/object.rb +13 -13
- data/lib/mixture/coerce/rational.rb +9 -9
- data/lib/mixture/coerce/set.rb +12 -4
- data/lib/mixture/coerce/string.rb +9 -9
- data/lib/mixture/coerce/symbol.rb +4 -4
- data/lib/mixture/coerce/time.rb +10 -9
- data/lib/mixture/coerce.rb +28 -8
- data/lib/mixture/extensions/coercable.rb +2 -10
- data/lib/mixture/extensions.rb +15 -9
- data/lib/mixture/types/access.rb +45 -0
- data/lib/mixture/types/array.rb +13 -0
- data/lib/mixture/types/boolean.rb +20 -0
- data/lib/mixture/types/class.rb +16 -0
- data/lib/mixture/types/collection.rb +14 -0
- data/lib/mixture/types/date.rb +13 -0
- data/lib/mixture/types/datetime.rb +13 -0
- data/lib/mixture/types/enumerable.rb +14 -0
- data/lib/mixture/types/float.rb +12 -0
- data/lib/mixture/types/hash.rb +15 -0
- data/lib/mixture/types/integer.rb +12 -0
- data/lib/mixture/types/nil.rb +11 -0
- data/lib/mixture/types/numeric.rb +12 -0
- data/lib/mixture/types/object.rb +24 -0
- data/lib/mixture/types/rational.rb +13 -0
- data/lib/mixture/types/set.rb +16 -0
- data/lib/mixture/types/string.rb +12 -0
- data/lib/mixture/types/symbol.rb +14 -0
- data/lib/mixture/types/time.rb +13 -0
- data/lib/mixture/types/type.rb +171 -0
- data/lib/mixture/types.rb +110 -0
- data/lib/mixture/version.rb +1 -1
- data/lib/mixture.rb +22 -2
- data/mixture.gemspec +2 -3
- metadata +31 -37
- data/lib/mixture/type.rb +0 -188
@@ -0,0 +1,110 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "thread_safe"
|
4
|
+
|
5
|
+
module Mixture
|
6
|
+
# Contains information about types.
|
7
|
+
module Types
|
8
|
+
# A list of all of the types (non-anonymous) that are known.
|
9
|
+
#
|
10
|
+
# @return [Array<Class>]
|
11
|
+
def self.types
|
12
|
+
@types ||= ThreadSafe::Array.new
|
13
|
+
end
|
14
|
+
|
15
|
+
# A list of the mappings that all types have. This is used
|
16
|
+
# primarily to map a type's symbol name to its type (e.g.
|
17
|
+
# `:string` to `String`). This is also used for boolean mapping.
|
18
|
+
#
|
19
|
+
# @return [Hash{Symbol => Mixture::Types::Type}]
|
20
|
+
def self.mappings
|
21
|
+
::Hash[types.flat_map do |type|
|
22
|
+
type.mappings.map do |name|
|
23
|
+
[name, type]
|
24
|
+
end
|
25
|
+
end]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Infers an object's type. It first checks the mappings to see if
|
29
|
+
# the object given is in the mappings; if it's not, it checks if
|
30
|
+
# it is a class. If it is a class, it passes it over to
|
31
|
+
# {.infer_class}; otherwise, it passes it over to {.infer_type}.
|
32
|
+
#
|
33
|
+
# @see .mappings
|
34
|
+
# @see .infer_class
|
35
|
+
# @see .infer_type
|
36
|
+
# @param object [Object] The object to infer the type of.
|
37
|
+
# @return [Mixture::Types::Type] The type of the object.
|
38
|
+
def self.infer(object)
|
39
|
+
mappings.fetch(object) do
|
40
|
+
if object.is_a?(::Class)
|
41
|
+
infer_class(object)
|
42
|
+
else
|
43
|
+
infer_type(object)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Infers the class of the given object. If the object is a type,
|
49
|
+
# it just returns the object. Otherwise, it searches types for a
|
50
|
+
# primitive that matches the object. If one is found, it is
|
51
|
+
# returned; otherwise, a new `Class` type is created using
|
52
|
+
# {Class.[]}. This is primarily used for user-defined classes.
|
53
|
+
#
|
54
|
+
# @example Creating a type for a user-defined class.
|
55
|
+
# class MyClass; end
|
56
|
+
# Mixture::Types.infer(MyClass) # => Mixture::Types::Class[MyClass]
|
57
|
+
# @api private
|
58
|
+
# @see Class.[]
|
59
|
+
# @param object [Class] The object to infer the type of.
|
60
|
+
# @return [Mixture::Types::Type] The type of the object.
|
61
|
+
def self.infer_class(object)
|
62
|
+
return object if object <= Type
|
63
|
+
types.find { |type| type.options[:primitive] == object } || Class[object]
|
64
|
+
end
|
65
|
+
|
66
|
+
# Infers the type of the object. If the object is an array or set,
|
67
|
+
# it returns an {Array} or {Set} type with the object's first
|
68
|
+
# element's type as the member type. Otherwise, it tries to find
|
69
|
+
# a type that matches the object using {Type.matches?}. This will
|
70
|
+
# almost always return a type, if not {Object}.
|
71
|
+
#
|
72
|
+
# @note This may not return a type if the object is a
|
73
|
+
# {BasicObject}. This is because of the constraints on the
|
74
|
+
# {Object} type.
|
75
|
+
# @example Infers the type of an array of elements.
|
76
|
+
# Mixture::Types.infer([1])
|
77
|
+
# # => Mixture::Types::Array[Mixture::Types::Integer]
|
78
|
+
# @api private
|
79
|
+
# @param object [Object] The object to infer.
|
80
|
+
# @return [Mixture::Types::Type] The inferred type.
|
81
|
+
def self.infer_type(object)
|
82
|
+
case object
|
83
|
+
when ::Array then Array[infer(object.first)]
|
84
|
+
when ::Set then Set[infer(object.first)]
|
85
|
+
else types.reverse.find { |type| type.matches?(object) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
require "mixture/types/type"
|
92
|
+
require "mixture/types/access"
|
93
|
+
require "mixture/types/object"
|
94
|
+
require "mixture/types/enumerable"
|
95
|
+
require "mixture/types/collection"
|
96
|
+
require "mixture/types/class"
|
97
|
+
require "mixture/types/boolean"
|
98
|
+
require "mixture/types/numeric"
|
99
|
+
require "mixture/types/array"
|
100
|
+
require "mixture/types/date"
|
101
|
+
require "mixture/types/datetime"
|
102
|
+
require "mixture/types/float"
|
103
|
+
require "mixture/types/hash"
|
104
|
+
require "mixture/types/integer"
|
105
|
+
require "mixture/types/nil"
|
106
|
+
require "mixture/types/rational"
|
107
|
+
require "mixture/types/set"
|
108
|
+
require "mixture/types/string"
|
109
|
+
require "mixture/types/symbol"
|
110
|
+
require "mixture/types/time"
|
data/lib/mixture/version.rb
CHANGED
data/lib/mixture.rb
CHANGED
@@ -9,6 +9,16 @@ module Mixture
|
|
9
9
|
# An undefined value. This is used in place so that we can be sure
|
10
10
|
# that an argument wasn't passed.
|
11
11
|
#
|
12
|
+
# @example As a placeholder.
|
13
|
+
# def self.constraint(value = Undefined, &block)
|
14
|
+
# if value != Undefined
|
15
|
+
# constraints << value
|
16
|
+
# elsif block_given?
|
17
|
+
# constraints << block
|
18
|
+
# else
|
19
|
+
# raise ArgumentError, "Expected an argument or block"
|
20
|
+
# end
|
21
|
+
# end
|
12
22
|
# @return [Object]
|
13
23
|
Undefined = Object.new.freeze
|
14
24
|
|
@@ -17,13 +27,23 @@ module Mixture
|
|
17
27
|
# @return [Proc{(Object) => Object}]
|
18
28
|
Itself = proc { |value| value }
|
19
29
|
|
30
|
+
# Finalizes all of the Mixture modules.
|
31
|
+
#
|
32
|
+
# @return [void]
|
33
|
+
def self.finalize
|
34
|
+
Mixture::Coerce.finalize
|
35
|
+
Mixture::Extensions.finalize
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
20
39
|
require "mixture/version"
|
21
40
|
require "mixture/errors"
|
22
|
-
require "mixture/
|
41
|
+
require "mixture/types"
|
23
42
|
require "mixture/attribute"
|
24
43
|
require "mixture/attribute_list"
|
25
44
|
require "mixture/coerce"
|
26
45
|
require "mixture/validate"
|
27
46
|
require "mixture/extensions"
|
28
|
-
|
47
|
+
|
48
|
+
finalize
|
29
49
|
end
|
data/mixture.gemspec
CHANGED
@@ -25,7 +25,6 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency "bundler"
|
26
26
|
spec.add_development_dependency "rake"
|
27
27
|
spec.add_development_dependency "rspec"
|
28
|
-
|
29
|
-
spec.
|
30
|
-
spec.add_development_dependency "rubocop"
|
28
|
+
|
29
|
+
spec.add_dependency "thread_safe", "~> 0.3"
|
31
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixture
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Rodi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -53,47 +53,19 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: thread_safe
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :
|
61
|
+
version: '0.3'
|
62
|
+
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: coveralls
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
66
|
+
- - "~>"
|
74
67
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rubocop
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
68
|
+
version: '0.3'
|
97
69
|
description: Handle validation, coercion, and attributes.
|
98
70
|
email:
|
99
71
|
- redjazz96@gmail.com
|
@@ -105,6 +77,7 @@ files:
|
|
105
77
|
- ".rspec"
|
106
78
|
- ".rubocop.yml"
|
107
79
|
- ".travis.yml"
|
80
|
+
- ".yardopts"
|
108
81
|
- CODE_OF_CONDUCT.md
|
109
82
|
- Gemfile
|
110
83
|
- Gemfile.lock
|
@@ -117,6 +90,7 @@ files:
|
|
117
90
|
- lib/mixture/coerce.rb
|
118
91
|
- lib/mixture/coerce/array.rb
|
119
92
|
- lib/mixture/coerce/base.rb
|
93
|
+
- lib/mixture/coerce/class.rb
|
120
94
|
- lib/mixture/coerce/date.rb
|
121
95
|
- lib/mixture/coerce/datetime.rb
|
122
96
|
- lib/mixture/coerce/float.rb
|
@@ -136,7 +110,27 @@ files:
|
|
136
110
|
- lib/mixture/extensions/hashable.rb
|
137
111
|
- lib/mixture/extensions/validatable.rb
|
138
112
|
- lib/mixture/model.rb
|
139
|
-
- lib/mixture/
|
113
|
+
- lib/mixture/types.rb
|
114
|
+
- lib/mixture/types/access.rb
|
115
|
+
- lib/mixture/types/array.rb
|
116
|
+
- lib/mixture/types/boolean.rb
|
117
|
+
- lib/mixture/types/class.rb
|
118
|
+
- lib/mixture/types/collection.rb
|
119
|
+
- lib/mixture/types/date.rb
|
120
|
+
- lib/mixture/types/datetime.rb
|
121
|
+
- lib/mixture/types/enumerable.rb
|
122
|
+
- lib/mixture/types/float.rb
|
123
|
+
- lib/mixture/types/hash.rb
|
124
|
+
- lib/mixture/types/integer.rb
|
125
|
+
- lib/mixture/types/nil.rb
|
126
|
+
- lib/mixture/types/numeric.rb
|
127
|
+
- lib/mixture/types/object.rb
|
128
|
+
- lib/mixture/types/rational.rb
|
129
|
+
- lib/mixture/types/set.rb
|
130
|
+
- lib/mixture/types/string.rb
|
131
|
+
- lib/mixture/types/symbol.rb
|
132
|
+
- lib/mixture/types/time.rb
|
133
|
+
- lib/mixture/types/type.rb
|
140
134
|
- lib/mixture/validate.rb
|
141
135
|
- lib/mixture/validate/base.rb
|
142
136
|
- lib/mixture/validate/exclusion.rb
|
data/lib/mixture/type.rb
DELETED
@@ -1,188 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "forwardable"
|
4
|
-
|
5
|
-
module Mixture
|
6
|
-
# A type. This can be represented as a constant. This is normally
|
7
|
-
# anything that inherits `Class`. One instance per type.
|
8
|
-
class Type
|
9
|
-
extend Forwardable
|
10
|
-
@instances = {}
|
11
|
-
# A class to represent the Boolean type (i.e. true, false), since
|
12
|
-
# ruby doesn't have a Boolean class.
|
13
|
-
#
|
14
|
-
# @return [Class]
|
15
|
-
BooleanClass = Class.new
|
16
|
-
|
17
|
-
# Ancestors that two classes might have in common with each other.
|
18
|
-
#
|
19
|
-
# @return [Array<Module, Class>]
|
20
|
-
COMMON_ANCESTORS = BooleanClass.ancestors - [BooleanClass]
|
21
|
-
|
22
|
-
# The builtin types of Ruby. These are initialized as types
|
23
|
-
# before anything else happens.
|
24
|
-
#
|
25
|
-
# @return [Array<Symbol>]
|
26
|
-
BUILTIN_TYPES = %w(
|
27
|
-
Object Array Hash Integer Rational Float Set String Symbol
|
28
|
-
Time Date DateTime
|
29
|
-
).map(&:intern).freeze
|
30
|
-
|
31
|
-
# The aliases for types. This overrides any other possible
|
32
|
-
# inferences that this class can make. For example, `true` and
|
33
|
-
# `false` are automatically mapped to `BooleanClass`.
|
34
|
-
#
|
35
|
-
# @return [Hash{Object, Symbol => Class}]
|
36
|
-
TYPE_ALIASES = {
|
37
|
-
true => BooleanClass,
|
38
|
-
false => BooleanClass,
|
39
|
-
nil => NilClass,
|
40
|
-
nil: NilClass,
|
41
|
-
bool: BooleanClass,
|
42
|
-
boolean: BooleanClass,
|
43
|
-
str: ::String,
|
44
|
-
string: ::String,
|
45
|
-
int: ::Integer,
|
46
|
-
integer: ::Integer,
|
47
|
-
rational: ::Rational,
|
48
|
-
float: ::Float,
|
49
|
-
array: ::Array,
|
50
|
-
set: ::Set,
|
51
|
-
symbol: ::Symbol,
|
52
|
-
time: ::Time,
|
53
|
-
date_time: ::DateTime,
|
54
|
-
date: ::Date
|
55
|
-
}.freeze
|
56
|
-
|
57
|
-
# Protect our class from being initialized by accident by anyone
|
58
|
-
# who doesn't know what they're doing. They would have to try
|
59
|
-
# really hard to initialize this class, and in which case, that
|
60
|
-
# is acceptable.
|
61
|
-
private_class_method :new
|
62
|
-
|
63
|
-
# Returns a {Type} from a given class. It assumes that the type
|
64
|
-
# given is a class, and passes it to `#new` - which will error if
|
65
|
-
# it isn't.
|
66
|
-
#
|
67
|
-
# @param type [Class] A type.
|
68
|
-
# @return [Mixture::Type]
|
69
|
-
def self.from(type)
|
70
|
-
@instances.fetch(type) do
|
71
|
-
@instances[type] = new(type)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# (see .from)
|
76
|
-
def self.[](type)
|
77
|
-
from(type)
|
78
|
-
end
|
79
|
-
|
80
|
-
# Determines the best type that represents the given value. If
|
81
|
-
# the given type is listed in {TYPE_ALIASES}, it uses the alias
|
82
|
-
# value for a lookup. If the given type is a {Type}, it returns
|
83
|
-
# the type. If the given type is a `Class`, it uses {.infer_class}.
|
84
|
-
# Otherwise, it uses {.infer_class} on the type's class.
|
85
|
-
#
|
86
|
-
# @example
|
87
|
-
# Mixture::Type.infer(Integer) # => Mixture::Type::Integer
|
88
|
-
#
|
89
|
-
# @example
|
90
|
-
# Mixture::Type.infer(1) # => Mixture::Type::Integer
|
91
|
-
#
|
92
|
-
# @example
|
93
|
-
# Mixture::Type.infer(MyClass) # => Mixture::Type[MyClass]
|
94
|
-
#
|
95
|
-
# @example
|
96
|
-
# Mixture::Type.infer(Object.new) # => Mixture::Type::Object
|
97
|
-
#
|
98
|
-
# @param value [Object] The value to infer.
|
99
|
-
# @return [Mixture::Type]
|
100
|
-
def self.infer(value)
|
101
|
-
case
|
102
|
-
when TYPE_ALIASES.key?(value) then from(TYPE_ALIASES[value])
|
103
|
-
when value.is_a?(Type) then value
|
104
|
-
when value.is_a?(Class) then infer_class(value)
|
105
|
-
else infer_class(value.class)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# Infer a classes' type. If the class is a type, it returns the
|
110
|
-
# type. Otherwise, it checks the most basic ancestors (most basic
|
111
|
-
# ancestors being any ancestors not shared with a new class) for
|
112
|
-
# any classes that have a {Type}; if there are none, it creates a
|
113
|
-
# new type from the class.
|
114
|
-
#
|
115
|
-
# @param klass [Class] The class to infer type from.
|
116
|
-
# @return [Mixture::Type]
|
117
|
-
def self.infer_class(klass)
|
118
|
-
if klass.is_a?(Type)
|
119
|
-
klass
|
120
|
-
else
|
121
|
-
basic_ancestors = klass.ancestors - COMMON_ANCESTORS
|
122
|
-
from(basic_ancestors.find { |a| @instances.key?(a) } || klass)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Loads the builtin types. This includes `Boolean` and `Nil`.
|
127
|
-
#
|
128
|
-
# @see BUILTIN_TYPES
|
129
|
-
# @see BooleanClass
|
130
|
-
# @return [void]
|
131
|
-
def self.load
|
132
|
-
BUILTIN_TYPES.each do |sym|
|
133
|
-
const_set(sym, from(::Object.const_get(sym)))
|
134
|
-
end
|
135
|
-
|
136
|
-
@instances[BooleanClass] = new(BooleanClass, name: "Boolean")
|
137
|
-
const_set("Boolean", @instances[BooleanClass])
|
138
|
-
@instances[NilClass] = new(NilClass, name: "Nil")
|
139
|
-
const_set("Nil", @instances[NilClass])
|
140
|
-
end
|
141
|
-
|
142
|
-
# The name of the type. If this wasn't provided upon
|
143
|
-
# initialization, it is guessed to be the class's name, which is
|
144
|
-
# normally good enough.
|
145
|
-
#
|
146
|
-
# @return [String]
|
147
|
-
attr_reader :name
|
148
|
-
|
149
|
-
# Initialize the type. The class given _must_ be a class;
|
150
|
-
# otherwise, it will error. A name can be provided as an option.
|
151
|
-
#
|
152
|
-
# @param type [Class] The type to create.
|
153
|
-
# @param options [Hash{Symbol => Object}] The options.
|
154
|
-
# @option options [String] :name The name to provide the type
|
155
|
-
# with. If this is not provided, it uses the class name.
|
156
|
-
def initialize(type, options = {})
|
157
|
-
fail ArgumentError, "Expected a Class, got #{type.class}" unless
|
158
|
-
type.is_a?(Class)
|
159
|
-
@type = type
|
160
|
-
@name = options.fetch(:name, @type.name)
|
161
|
-
end
|
162
|
-
|
163
|
-
# Creates a string representation of the type. This normally has
|
164
|
-
# the format `Mixture::Type(Class)`, where `Class` is the class.
|
165
|
-
#
|
166
|
-
# @return [String]
|
167
|
-
def to_s
|
168
|
-
"#{self.class.name}(#{@name})"
|
169
|
-
end
|
170
|
-
alias_method :inspect, :to_s
|
171
|
-
|
172
|
-
# Creates a `:to_` method name for the type.
|
173
|
-
#
|
174
|
-
# @example
|
175
|
-
# Mixture::Type[Array].method_name # => :to_array
|
176
|
-
def method_name
|
177
|
-
@_method_name ||= begin
|
178
|
-
body = name
|
179
|
-
.gsub(/^([A-Z])/) { |m| m.downcase }
|
180
|
-
.gsub(/::([A-Z])/) { |_, m| "_#{m.downcase}" }
|
181
|
-
.gsub(/([A-Z])/) { |m| "_#{m.downcase}" }
|
182
|
-
:"to_#{body}"
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
Mixture::Type.load
|