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.
@@ -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
@@ -0,0 +1,3 @@
1
+ module Coercible
2
+ VERSION = "0.2.0"
3
+ end
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: