named_value_class 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
data/lib/named_value_class.rb
CHANGED
@@ -1,13 +1,45 @@
|
|
1
1
|
require 'delegate'
|
2
|
+
require 'named_value_class/core_ext'
|
3
|
+
|
4
|
+
module NamedValueClass
|
5
|
+
OPERATIONS = {}
|
6
|
+
# OPERATORS = %w{+ - / * ** % | & ^ << >>}
|
7
|
+
OPERATORS = %w{+ - / *} # **}
|
8
|
+
|
9
|
+
def self.operators(klass, op, rhs_class, policy)
|
10
|
+
rhs_class = rhs_class.sub(/^Kernel::/,'')
|
11
|
+
OPERATIONS[klass] ||= {}
|
12
|
+
OPERATIONS[klass][rhs_class] ||= {}
|
13
|
+
OPERATIONS[klass][rhs_class][op] = policy
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.operate(klass, op, rhs_class, lhs, default_policy, rhs)
|
17
|
+
rhs_class = rhs_class.sub(/^Kernel::/,'')
|
18
|
+
result = (OPERATIONS[klass] && OPERATIONS[klass][rhs_class] &&
|
19
|
+
OPERATIONS[klass][rhs_class][op]) ?
|
20
|
+
OPERATIONS[klass][rhs_class][op].call(lhs,default_policy,rhs) :
|
21
|
+
default_policy.call(rhs)
|
22
|
+
result = (result.constrain(lhs.lhs_constrain) rescue result)
|
23
|
+
lhs.class[result] || result
|
24
|
+
end
|
25
|
+
end
|
2
26
|
|
3
27
|
# see README for documention
|
4
28
|
def NamedValueClass(attrs={},&block)
|
5
29
|
klass_name, superclass = attrs.first
|
6
30
|
attrs.delete(klass_name)
|
31
|
+
lhs_constrain = attrs.delete(:constrain)
|
7
32
|
target = (self.class == Object ? Kernel : self)
|
8
|
-
|
9
33
|
target.module_eval "class #{klass_name} < DelegateClass(superclass); end"
|
10
34
|
klass = target.const_get(klass_name)
|
35
|
+
|
36
|
+
if superclass.ancestors.include?(Numeric) && lhs_constrain
|
37
|
+
klass.module_eval <<-EVAL
|
38
|
+
def lhs_constrain
|
39
|
+
#{lhs_constrain}
|
40
|
+
end
|
41
|
+
EVAL
|
42
|
+
end
|
11
43
|
|
12
44
|
klass.module_eval do
|
13
45
|
def self.inherited(child)
|
@@ -34,16 +66,102 @@ def NamedValueClass(attrs={},&block)
|
|
34
66
|
end
|
35
67
|
end
|
36
68
|
end
|
69
|
+
|
70
|
+
def self.all_operators_with_a *attrs
|
71
|
+
rhs_class = attrs.shift
|
72
|
+
operators *(NamedValueClass::OPERATORS + [rhs_class] + attrs)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.all_remaining_operators_with_a *attrs
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.operators *attrs, &block
|
79
|
+
policy = attrs.pop if attrs.last.is_a?(Hash)
|
80
|
+
with_a = attrs.pop
|
81
|
+
attrs.each do |op|
|
82
|
+
operator op, *([with_a, policy].compact), &block
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.operator op, rhs_class, attrs={}, &policy
|
87
|
+
if value_to_return = (attrs[:return] || attrs[:returns])
|
88
|
+
policy = proc do |_,_,_|
|
89
|
+
value_to_return
|
90
|
+
end
|
91
|
+
end
|
92
|
+
if klass_to_raise = (attrs[:raise] || attrs[:raises])
|
93
|
+
policy = proc do |_,_,_|
|
94
|
+
raise klass_to_raise
|
95
|
+
end
|
96
|
+
end
|
97
|
+
NamedValueClass.operators(self, op, rhs_class.to_s, policy)
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.plus_a (*attrs,&policy) operator '+', *attrs, &policy end
|
101
|
+
def self.minus_a (*attrs,&policy) operator '-', *attrs, &policy end
|
102
|
+
def self.divided_by_a (*attrs,&policy) operator '/', *attrs, &policy end
|
103
|
+
def self.multiplied_by_a(*attrs,&policy) operator '*', *attrs, &policy end
|
104
|
+
def self.modulus_a (*attrs,&policy) operator '%', *attrs, &policy end
|
105
|
+
def self.raised_by_a (*attrs,&policy) operator '**',*attrs, &policy end
|
106
|
+
|
107
|
+
{
|
108
|
+
_plus: '+',
|
109
|
+
_minus: '-',
|
110
|
+
_multi: '*',
|
111
|
+
_divide:'/',
|
112
|
+
_mod: '%',
|
113
|
+
_raise: '**'
|
114
|
+
}.each do |(name,orig)|
|
115
|
+
eval "alias #{name} #{orig}" rescue nil
|
116
|
+
define_method orig do |rhs|
|
117
|
+
NamedValueClass.operate(self.class,orig,rhs.class.to_s,
|
118
|
+
self,method(name.to_sym),rhs)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# TODO: think about coerce more
|
123
|
+
# def coerce(lhs)
|
124
|
+
# [lhs,self.value]
|
125
|
+
# end
|
126
|
+
|
127
|
+
# def coerce(rhs)
|
128
|
+
# class_eval do
|
129
|
+
# if @operators && @operators[rhs.class]
|
130
|
+
# @operators[rhs.class].call(self,rhs)
|
131
|
+
# end
|
132
|
+
# end
|
133
|
+
# end
|
37
134
|
|
135
|
+
attr_reader :value
|
136
|
+
|
38
137
|
def initialize(attrs = {})
|
39
138
|
@name, value = attrs.first
|
40
139
|
attrs.delete(@name)
|
41
140
|
@name = @name.to_s
|
42
|
-
super(value)
|
43
|
-
|
141
|
+
super(@value = value)
|
142
|
+
|
143
|
+
this = self
|
44
144
|
attrs.each do |(attr,val)|
|
45
145
|
self.class.instance_eval do
|
46
146
|
attr_accessor attr
|
147
|
+
if [FalseClass,TrueClass].include?(val.class)
|
148
|
+
booleans = begin
|
149
|
+
const_get((attr.to_s+'s').upcase)
|
150
|
+
rescue NameError
|
151
|
+
const_set((attr.to_s+'s').upcase, {})
|
152
|
+
end
|
153
|
+
|
154
|
+
booleans[value] = this if val
|
155
|
+
|
156
|
+
self.class.instance_eval do
|
157
|
+
define_method(attr.to_s + 's') do
|
158
|
+
const_get((attr.to_s+'s').upcase)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
define_method "is_#{attr}?" do
|
162
|
+
self.send(attr)
|
163
|
+
end
|
164
|
+
end
|
47
165
|
end
|
48
166
|
instance_variable_set "@#{attr}", val
|
49
167
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#
|
2
|
+
# core_ext.rb: useful additions to basic Ruby objects
|
3
|
+
#
|
4
|
+
# Copyright October 2010, Adam Florin. All rights reserved.
|
5
|
+
#
|
6
|
+
|
7
|
+
|
8
|
+
# Monkeypatch Array so we can cleanly get SUM
|
9
|
+
#
|
10
|
+
class Array
|
11
|
+
def sum
|
12
|
+
inject( nil ) { |sum,x| sum ? sum+x : x }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# So that we can do the neat Railsy syntax like array.map(&:method) in Ruby 1.8.6
|
17
|
+
# See http://jlaine.net/2008/5/8/amp-lified
|
18
|
+
#
|
19
|
+
class Symbol
|
20
|
+
def to_proc
|
21
|
+
lambda {|i| i.send(self)}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Numeric extensions
|
26
|
+
#
|
27
|
+
class Numeric
|
28
|
+
|
29
|
+
# constrain number within a given range
|
30
|
+
#
|
31
|
+
def constrain(range)
|
32
|
+
if self > range.end
|
33
|
+
return range.end
|
34
|
+
elsif self < range.begin
|
35
|
+
return range.begin
|
36
|
+
else
|
37
|
+
return self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# to manage things like timescale shifts which for now
|
42
|
+
# must be divisible by 2
|
43
|
+
#
|
44
|
+
def round_to_power(power = 2)
|
45
|
+
power ** (Math.log(self) / Math.log(power)).round
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# To convert :symbol_names to ClassNames and back.
|
50
|
+
#
|
51
|
+
class String
|
52
|
+
def camelize
|
53
|
+
self.gsub(/[^_]+/){|c| c.capitalize}.gsub('_', '')
|
54
|
+
end
|
55
|
+
|
56
|
+
def underscorize
|
57
|
+
self.gsub(/[A-Z]/, "_\\0").gsub(/^_/, '').downcase
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# for Rails-like method chaining
|
62
|
+
#
|
63
|
+
class Module
|
64
|
+
def alias_method_chain(target, feature)
|
65
|
+
alias_method "#{target}_without_#{feature}", target
|
66
|
+
alias_method target, "#{target}_with_#{feature}"
|
67
|
+
end
|
68
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: named_value_class
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-12-20 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: Quickly add customizable class delegate constants which output their
|
15
15
|
names, not their values. This may be desirable for some DSLs.
|
@@ -19,6 +19,9 @@ extensions: []
|
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
21
|
- lib/named_value_class.rb
|
22
|
+
- lib/named_value_class/core_ext.rb
|
23
|
+
- lib/named_value_class/immutable.rb
|
24
|
+
- lib/named_value_class/version.rb
|
22
25
|
homepage: http://github.com/mgarriss/named_value_class
|
23
26
|
licenses: []
|
24
27
|
post_install_message:
|