motion_coercible 0.2.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 +15 -0
- data/README.md +62 -0
- data/lib/motion_coercible.rb +12 -0
- data/lib/project/coercer/array.rb +24 -0
- data/lib/project/coercer/configurable.rb +63 -0
- data/lib/project/coercer/false_class.rb +25 -0
- data/lib/project/coercer/float.rb +25 -0
- data/lib/project/coercer/hash.rb +46 -0
- data/lib/project/coercer/integer.rb +92 -0
- data/lib/project/coercer/numeric.rb +53 -0
- data/lib/project/coercer/object.rb +187 -0
- data/lib/project/coercer/string.rb +228 -0
- data/lib/project/coercer/symbol.rb +25 -0
- data/lib/project/coercer/time.rb +41 -0
- data/lib/project/coercer/time_coercions.rb +58 -0
- data/lib/project/coercer/true_class.rb +25 -0
- data/lib/project/coercer.rb +136 -0
- data/lib/project/coercible.rb +18 -0
- data/lib/project/configuration.rb +28 -0
- data/lib/project/support/options.rb +125 -0
- data/lib/project/support/type_lookup.rb +113 -0
- data/lib/project/version.rb +3 -0
- metadata +108 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
module Coercible
|
2
|
+
EXTRA_CONST_ARGS = (RUBY_VERSION < '1.9' ? [] : [ false ]).freeze
|
3
|
+
|
4
|
+
UnsupportedCoercion = Class.new(StandardError)
|
5
|
+
|
6
|
+
# Test for rubinius platform
|
7
|
+
#
|
8
|
+
# @return [true]
|
9
|
+
# if running under rubinius
|
10
|
+
#
|
11
|
+
# @return [false]
|
12
|
+
# otherwise
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
def self.rbx?
|
16
|
+
@is_rbx ||= defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Coercible
|
2
|
+
|
3
|
+
# Configuration object for global and per coercer type settings
|
4
|
+
#
|
5
|
+
class Configuration
|
6
|
+
|
7
|
+
# Build a configuration instance
|
8
|
+
#
|
9
|
+
# @param [Array] list of accessor keys
|
10
|
+
#
|
11
|
+
# @return [Configuration]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
def self.build(keys, &block)
|
15
|
+
config = new
|
16
|
+
keys.each do |key|
|
17
|
+
config.instance_eval do
|
18
|
+
define_singleton_method("#{key}") { instance_variable_get("@#{key}") }
|
19
|
+
define_singleton_method("#{key}=") {|value| instance_variable_set("@#{key}", value) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
yield(config) if block_given?
|
23
|
+
config
|
24
|
+
end
|
25
|
+
|
26
|
+
end # class Configuration
|
27
|
+
|
28
|
+
end # module Coercible
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Coercible
|
2
|
+
|
3
|
+
# A module that adds class and instance level options
|
4
|
+
module Options
|
5
|
+
Undefined = Class.new.freeze
|
6
|
+
|
7
|
+
# Hook called when descendant was extended
|
8
|
+
#
|
9
|
+
# @param [Class,Module] descendant
|
10
|
+
#
|
11
|
+
# @return [undefined]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
def self.extended(descendant)
|
15
|
+
descendant.extend(DescendantsTracker)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns default options hash for a given attribute class
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# Virtus::Attribute::String.options
|
22
|
+
# # => {:primitive => String}
|
23
|
+
#
|
24
|
+
# @return [Hash]
|
25
|
+
# a hash of default option values
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
def options
|
29
|
+
accepted_options.each_with_object({}) do |option_name, options|
|
30
|
+
option_value = send(option_name)
|
31
|
+
options[option_name] = option_value unless option_value.nil?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns an array of valid options
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# Virtus::Attribute::String.accepted_options
|
39
|
+
# # => [:primitive, :accessor, :reader, :writer]
|
40
|
+
#
|
41
|
+
# @return [Array]
|
42
|
+
# the array of valid option names
|
43
|
+
#
|
44
|
+
# @api public
|
45
|
+
def accepted_options
|
46
|
+
@accepted_options ||= []
|
47
|
+
end
|
48
|
+
|
49
|
+
# Defines which options are valid for a given attribute class
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
# class MyAttribute < Virtus::Attribute::Object
|
53
|
+
# accept_options :foo, :bar
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# @return [self]
|
57
|
+
#
|
58
|
+
# @api public
|
59
|
+
def accept_options(*new_options)
|
60
|
+
add_accepted_options(new_options)
|
61
|
+
new_options.each { |option| define_option_method(option) }
|
62
|
+
descendants.each { |descendant| descendant.add_accepted_options(new_options) }
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
# Adds a reader/writer method for the give option name
|
69
|
+
#
|
70
|
+
# @return [undefined]
|
71
|
+
#
|
72
|
+
# @api private
|
73
|
+
def define_option_method(option)
|
74
|
+
metaclass = class << self; self; end
|
75
|
+
metaclass.instance_eval do
|
76
|
+
define_method("#{option}") do |value=Undefined|
|
77
|
+
return instance_variable_get("@#{option}") if value.equal?(Undefined)
|
78
|
+
instance_variable_set("@#{option}", value)
|
79
|
+
metaclass
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Sets default options
|
85
|
+
#
|
86
|
+
# @param [#each] new_options
|
87
|
+
# options to be set
|
88
|
+
#
|
89
|
+
# @return [self]
|
90
|
+
#
|
91
|
+
# @api private
|
92
|
+
def set_options(new_options)
|
93
|
+
new_options.each { |pair| send(*pair) }
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
# Adds new options that an attribute class can accept
|
98
|
+
#
|
99
|
+
# @param [#to_ary] new_options
|
100
|
+
# new options to be added
|
101
|
+
#
|
102
|
+
# @return [self]
|
103
|
+
#
|
104
|
+
# @api private
|
105
|
+
def add_accepted_options(new_options)
|
106
|
+
accepted_options.concat(new_options)
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
# Adds descendant to descendants array and inherits default options
|
113
|
+
#
|
114
|
+
# @param [Class] descendant
|
115
|
+
#
|
116
|
+
# @return [undefined]
|
117
|
+
#
|
118
|
+
# @api private
|
119
|
+
def inherited(descendant)
|
120
|
+
super
|
121
|
+
descendant.add_accepted_options(accepted_options).set_options(options)
|
122
|
+
end
|
123
|
+
|
124
|
+
end # module Options
|
125
|
+
end # module Virtus
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Coercible
|
2
|
+
|
3
|
+
# A module that adds type lookup to a class
|
4
|
+
module TypeLookup
|
5
|
+
|
6
|
+
TYPE_FORMAT = /\A[A-Z]\w*\z/.freeze
|
7
|
+
|
8
|
+
# Set cache ivar on the model
|
9
|
+
#
|
10
|
+
# @param [Class] model
|
11
|
+
#
|
12
|
+
# @return [undefined]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
def self.extended(model)
|
16
|
+
model.instance_variable_set('@type_lookup_cache', {})
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns a descendant based on a name or class
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# MyClass.determine_type('String') # => MyClass::String
|
23
|
+
#
|
24
|
+
# @param [Class, #to_s] class_or_name
|
25
|
+
# name of a class or a class itself
|
26
|
+
#
|
27
|
+
# @return [Class]
|
28
|
+
# a descendant
|
29
|
+
#
|
30
|
+
# @return [nil]
|
31
|
+
# nil if the type cannot be determined by the class_or_name
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
def determine_type(class_or_name)
|
35
|
+
@type_lookup_cache[class_or_name] ||= determine_type_and_cache(class_or_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return the default primitive supported
|
39
|
+
#
|
40
|
+
# @return [Class]
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
def primitive
|
44
|
+
raise NotImplementedError, "#{self}.primitive must be implemented"
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Determine type and cache the class
|
50
|
+
#
|
51
|
+
# @return [Class]
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
def determine_type_and_cache(class_or_name)
|
55
|
+
case class_or_name
|
56
|
+
when singleton_class
|
57
|
+
determine_type_from_descendant(class_or_name)
|
58
|
+
when Class
|
59
|
+
determine_type_from_primitive(class_or_name)
|
60
|
+
else
|
61
|
+
determine_type_from_string(class_or_name.to_s)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Return the class given a descendant
|
66
|
+
#
|
67
|
+
# @param [Class] descendant
|
68
|
+
#
|
69
|
+
# @return [Class]
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
def determine_type_from_descendant(descendant)
|
73
|
+
descendant if descendant < self
|
74
|
+
end
|
75
|
+
|
76
|
+
# Return the class given a primitive
|
77
|
+
#
|
78
|
+
# @param [Class] primitive
|
79
|
+
#
|
80
|
+
# @return [Class]
|
81
|
+
#
|
82
|
+
# @return [nil]
|
83
|
+
# nil if the type cannot be determined by the primitive
|
84
|
+
#
|
85
|
+
# @api private
|
86
|
+
def determine_type_from_primitive(primitive)
|
87
|
+
type = nil
|
88
|
+
descendants.reverse_each do |descendant|
|
89
|
+
descendant_primitive = descendant.primitive
|
90
|
+
next unless primitive <= descendant_primitive
|
91
|
+
type = descendant if type.nil? or type.primitive > descendant_primitive
|
92
|
+
end
|
93
|
+
type
|
94
|
+
end
|
95
|
+
|
96
|
+
# Return the class given a string
|
97
|
+
#
|
98
|
+
# @param [String] string
|
99
|
+
#
|
100
|
+
# @return [Class]
|
101
|
+
#
|
102
|
+
# @return [nil]
|
103
|
+
# nil if the type cannot be determined by the string
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
def determine_type_from_string(string)
|
107
|
+
if string =~ TYPE_FORMAT and const_defined?(string, *EXTRA_CONST_ARGS)
|
108
|
+
const_get(string, *EXTRA_CONST_ARGS)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end # module TypeLookup
|
113
|
+
end # module Virtus
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: motion_coercible
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Closner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: motion-require
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: motion_descendants_tracker
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: RubyMotion port of coercible
|
56
|
+
email:
|
57
|
+
- ryan@ryanclosner.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- README.md
|
63
|
+
- lib/motion_coercible.rb
|
64
|
+
- lib/project/coercer/array.rb
|
65
|
+
- lib/project/coercer/configurable.rb
|
66
|
+
- lib/project/coercer/false_class.rb
|
67
|
+
- lib/project/coercer/float.rb
|
68
|
+
- lib/project/coercer/hash.rb
|
69
|
+
- lib/project/coercer/integer.rb
|
70
|
+
- lib/project/coercer/numeric.rb
|
71
|
+
- lib/project/coercer/object.rb
|
72
|
+
- lib/project/coercer/string.rb
|
73
|
+
- lib/project/coercer/symbol.rb
|
74
|
+
- lib/project/coercer/time.rb
|
75
|
+
- lib/project/coercer/time_coercions.rb
|
76
|
+
- lib/project/coercer/true_class.rb
|
77
|
+
- lib/project/coercer.rb
|
78
|
+
- lib/project/coercible.rb
|
79
|
+
- lib/project/configuration.rb
|
80
|
+
- lib/project/support/options.rb
|
81
|
+
- lib/project/support/type_lookup.rb
|
82
|
+
- lib/project/version.rb
|
83
|
+
homepage: http://github.com/rclosner/motion_coercible
|
84
|
+
licenses:
|
85
|
+
- ''
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.0.6
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: RubyMotion port of coercible
|
107
|
+
test_files: []
|
108
|
+
has_rdoc:
|