mixture 0.2.0 → 0.3.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 +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
|