safety 1.0.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 +7 -0
- data/lib/safety/safety_attribute_helper.rb +13 -0
- data/lib/safety/safety_module.rb +91 -0
- data/lib/safety.rb +6 -0
- metadata +47 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 82ccd013a24f2ad81da78340b9ceceae95240f52
|
4
|
+
data.tar.gz: 9d5429001690a7a33dabcce0002103560bfcff2a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e1c567f91aa9079323da52b092dfa5dfff36e3c656f758c95fc6844cbce4dc6b66d78d1e3c3c8c86885bacc47d2c3518c26def7a23bcc78802f726d393b928d6
|
7
|
+
data.tar.gz: 0fa062d38e2f969ea32b374723c4ace3a96dd803b1905b5e0f072b3a7a8683a282caeb1880aa33e5c3c5a78f0e602d8e363ff1e9367344d1a52cba3fd852d3c7
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SafetyAttributeHelper
|
2
|
+
def self.parse_attribute_type method
|
3
|
+
if method.to_s =~ /attr_accessor_[a-zA-Z_]*/
|
4
|
+
:accessor
|
5
|
+
elsif method.to_s =~ /attr_reader_[a-zA-Z_]*/
|
6
|
+
:reader
|
7
|
+
elsif method.to_s =~ /attr_writer_[a-zA-Z_]*/
|
8
|
+
:writer
|
9
|
+
else
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'safety/safety_attribute_helper'
|
2
|
+
module SafetyModule
|
3
|
+
def respond_to?(method)
|
4
|
+
if SafetyAttributeHelper.parse_attribute_type method
|
5
|
+
true
|
6
|
+
else
|
7
|
+
super
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method, *args, &block)
|
12
|
+
type = SafetyAttributeHelper.parse_attribute_type method
|
13
|
+
if type
|
14
|
+
# Extract the type name from the attribute declaration
|
15
|
+
type_name = method.to_s.slice("attr_#{type.to_s}_".length...method.to_s.length)
|
16
|
+
|
17
|
+
# If the type name is var, type safety will be disabled for this attribute
|
18
|
+
should_enforce_type_safety = type_name != 'var'
|
19
|
+
|
20
|
+
# The class to enforce type safety on
|
21
|
+
type_safe_class = nil
|
22
|
+
|
23
|
+
# Get the type, which could be deep in modules
|
24
|
+
if should_enforce_type_safety == true
|
25
|
+
type_safe_class = type_name.split('::').inject(Object.class) do |current_module, class_name|
|
26
|
+
current_module.const_get(class_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Define enforce safety for this property
|
31
|
+
define_method "__enforce_safety_#{args[0]}".to_sym do |value|
|
32
|
+
# If enforcing type and value is not of type safe class, raise TypeError
|
33
|
+
if should_enforce_type_safety == true and value.is_a?(type_safe_class) == false
|
34
|
+
raise TypeError, "Type Safe Attribute \"#{args[0]}\", of type \"#{type_safe_class}\", set to value \"#{value}\" of class \"#{value.class}\"."
|
35
|
+
end
|
36
|
+
return value
|
37
|
+
end
|
38
|
+
|
39
|
+
# A way to get the default value
|
40
|
+
define_method "__default_value_#{args[0]}".to_sym do
|
41
|
+
if args[1] != nil
|
42
|
+
return args[1]
|
43
|
+
else
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Set default, if one was provided
|
49
|
+
#set_value.call(args[1]) if args[1] != nil
|
50
|
+
define_method "__lazy_instantiator_#{args[0]}".to_sym do
|
51
|
+
return block
|
52
|
+
end
|
53
|
+
|
54
|
+
lazy_instantiation = <<EVAL
|
55
|
+
def __lazy_instantiation_#{args[0]}
|
56
|
+
return nil if __lazy_instantiator_#{args[0]}().nil?
|
57
|
+
instance_exec &__lazy_instantiator_#{args[0]}
|
58
|
+
end
|
59
|
+
EVAL
|
60
|
+
|
61
|
+
getter = <<EVAL
|
62
|
+
def #{args[0]}
|
63
|
+
@#{args[0]} = __lazy_instantiation_#{args[0]} if @#{args[0]}.nil? && __lazy_instantiator_#{args[0]} != nil
|
64
|
+
@#{args[0]} = __enforce_safety_#{args[0]}(__default_value_#{args[0]}) if @#{args[0]}.nil? && __default_value_#{args[0]} != nil
|
65
|
+
__enforce_safety_#{args[0]}(@#{args[0]})
|
66
|
+
end
|
67
|
+
EVAL
|
68
|
+
|
69
|
+
setter = <<EVAL
|
70
|
+
def #{args[0]}= value
|
71
|
+
@#{args[0]} = __enforce_safety_#{args[0]}(value)
|
72
|
+
end
|
73
|
+
EVAL
|
74
|
+
|
75
|
+
to_evaluate = lazy_instantiation
|
76
|
+
case type
|
77
|
+
when :accessor
|
78
|
+
to_evaluate << getter
|
79
|
+
to_evaluate << setter
|
80
|
+
when :reader
|
81
|
+
to_evaluate << getter
|
82
|
+
when :writer
|
83
|
+
to_evaluate << setter
|
84
|
+
end
|
85
|
+
|
86
|
+
self.class_eval to_evaluate
|
87
|
+
else
|
88
|
+
super
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/safety.rb
ADDED
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: safety
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Lawrence Turner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-06 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Allows you to create type safe attributes in Ruby. Attributes may also
|
14
|
+
have default values or lazy instantiators
|
15
|
+
email: james@jameslawrenceturner.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/safety.rb
|
21
|
+
- lib/safety/safety_module.rb
|
22
|
+
- lib/safety/safety_attribute_helper.rb
|
23
|
+
homepage: http://github.com/jlturner/safety
|
24
|
+
licenses:
|
25
|
+
- MIT
|
26
|
+
metadata: {}
|
27
|
+
post_install_message:
|
28
|
+
rdoc_options: []
|
29
|
+
require_paths:
|
30
|
+
- lib
|
31
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - '>='
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
requirements: []
|
42
|
+
rubyforge_project:
|
43
|
+
rubygems_version: 2.1.11
|
44
|
+
signing_key:
|
45
|
+
specification_version: 4
|
46
|
+
summary: Type Safety in Ruby
|
47
|
+
test_files: []
|