glue 0.20.0 → 0.21.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.
- data/CHANGELOG +161 -110
- data/INSTALL +12 -12
- data/README +1 -1
- data/Rakefile +43 -45
- data/doc/AUTHORS +5 -5
- data/doc/LICENSE +3 -3
- data/doc/RELEASES +32 -24
- data/install.rb +7 -17
- data/lib/facet/object/alias_class.rb +12 -0
- data/lib/glue.rb +35 -35
- data/lib/glue/array.rb +46 -46
- data/lib/glue/aspects.rb +199 -209
- data/lib/glue/attribute.rb +15 -15
- data/lib/glue/autoreload.rb +1 -1
- data/lib/glue/builder.rb +48 -0
- data/lib/glue/builder/xml.rb +114 -0
- data/lib/glue/cache.rb +189 -0
- data/lib/glue/configuration.rb +108 -90
- data/lib/glue/flexob.rb +17 -17
- data/lib/glue/hash.rb +71 -71
- data/lib/glue/helper.rb +12 -12
- data/lib/glue/idgen.rb +9 -0
- data/lib/glue/idgen/md5.rb +24 -0
- data/lib/glue/idgen/sequential.rb +15 -0
- data/lib/glue/literal_method.rb +44 -0
- data/lib/glue/localization.rb +130 -0
- data/lib/glue/logger.rb +98 -98
- data/lib/glue/misc.rb +7 -7
- data/lib/glue/mixins.rb +19 -19
- data/lib/glue/number.rb +8 -8
- data/lib/glue/object.rb +2 -2
- data/lib/glue/pool.rb +43 -43
- data/lib/glue/property.rb +392 -392
- data/lib/glue/sanitize.rb +34 -34
- data/lib/glue/settings.rb +1 -1
- data/lib/glue/snapshot.rb +104 -0
- data/lib/glue/string.rb +129 -129
- data/lib/glue/time.rb +53 -53
- data/lib/glue/uri.rb +162 -162
- data/lib/glue/validation.rb +421 -421
- data/lib/vendor/blankslate.rb +53 -0
- data/test/glue/builder/tc_xml.rb +56 -0
- data/test/glue/tc_aspects.rb +90 -90
- data/test/glue/tc_attribute.rb +11 -11
- data/test/glue/tc_builder.rb +30 -0
- data/test/glue/tc_configuration.rb +97 -97
- data/test/glue/tc_flexob.rb +10 -10
- data/test/glue/tc_hash.rb +23 -23
- data/test/glue/tc_localization.rb +49 -0
- data/test/glue/tc_logger.rb +31 -31
- data/test/glue/tc_numbers.rb +9 -9
- data/test/glue/tc_property.rb +67 -67
- data/test/glue/tc_property_mixins.rb +17 -17
- data/test/glue/tc_property_type_checking.rb +13 -13
- data/test/glue/tc_strings.rb +94 -94
- data/test/glue/tc_uri.rb +65 -65
- data/test/glue/tc_validation.rb +196 -196
- metadata +26 -4
data/lib/glue/flexob.rb
CHANGED
@@ -5,25 +5,25 @@ require 'ostruct'
|
|
5
5
|
|
6
6
|
class Flexob < OpenStruct
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
def update(hash)
|
9
|
+
hash.each do |k, v|
|
10
|
+
send("#{k}=", v)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
alias_method :set, :update
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
def []=(key, val)
|
16
|
+
@table[key.to_sym] = val
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
@table[key.to_sym]
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
def each(&block)
|
24
|
+
@table.each(&block)
|
25
|
+
end
|
26
|
+
|
27
27
|
end
|
28
28
|
|
29
29
|
# * George Moschovitis <gm@navel.gr>
|
data/lib/glue/hash.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# * George Moschovitis <gm@navel.gr>
|
2
2
|
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
-
# $Id: hash.rb
|
3
|
+
# $Id: hash.rb 182 2005-07-22 10:07:50Z gmosx $
|
4
4
|
|
5
5
|
require 'sync'
|
6
6
|
|
@@ -13,41 +13,41 @@ module Glue
|
|
13
13
|
# implementations!
|
14
14
|
|
15
15
|
class SafeHash < Hash
|
16
|
-
|
16
|
+
attr :sync
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
# gmosx: delegator is not used.
|
19
|
+
#
|
20
|
+
def initialize(delegator = nil)
|
21
|
+
@sync = ::Sync.new
|
22
|
+
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
def [](key)
|
25
|
+
@sync.synchronize(::Sync::SH) { super }
|
26
|
+
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def []=(key, value)
|
29
|
+
@sync.synchronize(::Sync::EX) { super }
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
def delete(key)
|
33
|
+
@sync.synchronize(::Sync::EX) { super }
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
def clear
|
37
|
+
@sync.synchronize(::Sync::EX) { super }
|
38
|
+
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
def size
|
41
|
+
@sync.synchronize(::Sync::SH) { super }
|
42
|
+
end
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
def values
|
45
|
+
@sync.synchronize(::Sync::SH) { super }
|
46
|
+
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
def keys
|
49
|
+
@sync.synchronize(::Sync::SH) { super }
|
50
|
+
end
|
51
51
|
|
52
52
|
end
|
53
53
|
|
@@ -68,54 +68,54 @@ end
|
|
68
68
|
# hash = SafeHashDelegator.new(Hash.new)
|
69
69
|
|
70
70
|
class SafeHashDelegator < Hash
|
71
|
-
|
71
|
+
attr :delegate, :sync
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
def initialize(delegate)
|
74
|
+
@delegate = delegate
|
75
|
+
@sync = ::Sync.new
|
76
|
+
end
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
def [](key)
|
79
|
+
@sync.synchronize(::Sync::SH) {
|
80
|
+
@delegate[key]
|
81
|
+
}
|
82
82
|
end
|
83
83
|
|
84
84
|
def []=(key, value)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
85
|
+
@sync.synchronize(::Sync::EX) {
|
86
|
+
@delegate[key] = value
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def delete(key)
|
91
|
+
@sync.synchronize(::Sync::EX) {
|
92
|
+
@delegate.delete(key)
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def clear
|
97
|
+
@sync.synchronize(::Sync::EX) {
|
98
|
+
@delegate.clear
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def size
|
103
|
+
@sync.synchronize(::Sync::SH) {
|
104
|
+
@delegate.size()
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
def values
|
109
|
+
@sync.synchronize(::Sync::SH) {
|
110
|
+
@delegate.values()
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
def keys
|
115
|
+
@sync.synchronize(::Sync::SH) {
|
116
|
+
@delegate.keys()
|
117
|
+
}
|
118
|
+
end
|
119
119
|
|
120
120
|
end
|
121
121
|
|
data/lib/glue/helper.rb
CHANGED
@@ -12,18 +12,18 @@ module Glue
|
|
12
12
|
|
13
13
|
module Helpers
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
15
|
+
def self.append_features(base)
|
16
|
+
base.module_eval do
|
17
|
+
def self.helper(*modules)
|
18
|
+
for mod in modules
|
19
|
+
symbols = mod.instance_methods.collect { |m| m.to_sym }
|
20
|
+
self.send(:include, mod)
|
21
|
+
self.send(:private, *symbols)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
27
|
end
|
28
28
|
|
29
29
|
end
|
data/lib/glue/idgen.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Returned ids might not be unique, but it should be very hard to guess the
|
2
|
+
# next id.
|
3
|
+
|
4
|
+
require 'glue/idgen'
|
5
|
+
require 'digest/md5'
|
6
|
+
|
7
|
+
class Glue::Md5IdGenerator < Glue::IdGenerator
|
8
|
+
def initialize(salt='ruby')
|
9
|
+
@salt = salt
|
10
|
+
end
|
11
|
+
|
12
|
+
def next
|
13
|
+
now = Time.now
|
14
|
+
md5 = Digest::MD5.new
|
15
|
+
md5.update(now.to_s)
|
16
|
+
md5.update(now.usec.to_s)
|
17
|
+
md5.update(rand(0).to_s)
|
18
|
+
md5.update($$.to_s)
|
19
|
+
md5.update(@salt.to_s)
|
20
|
+
md5.hexdigest
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# * Michael Neumann <mneumann@ntecs.de>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Returned ids are guaranteed to be unique, but they are easily guessable.
|
2
|
+
|
3
|
+
require 'glue/idgen'
|
4
|
+
|
5
|
+
class Glue::SequentialIdGenerator < Glue::IdGenerator
|
6
|
+
def initialize(initial_value=0)
|
7
|
+
@value = initial_value
|
8
|
+
end
|
9
|
+
|
10
|
+
def next
|
11
|
+
@value += 1
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# * Michael Neumann <mneumann@ntecs.de>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Glue
|
2
|
+
|
3
|
+
# A serializable method.
|
4
|
+
#
|
5
|
+
# For example, you can't marshal:
|
6
|
+
#
|
7
|
+
# "ruby".method(:to_s)
|
8
|
+
#
|
9
|
+
# But you can:
|
10
|
+
#
|
11
|
+
# Glue::LiteralMethodCallback.new("ruby", :to_s)
|
12
|
+
#
|
13
|
+
# or it's equivalent:
|
14
|
+
#
|
15
|
+
# "ruby".literal_method(:to_s)
|
16
|
+
|
17
|
+
class LiteralMethod
|
18
|
+
attr_reader :obj
|
19
|
+
|
20
|
+
def initialize(obj, method_id=:call, *args)
|
21
|
+
@obj, @method_id = obj, method_id
|
22
|
+
@args = args unless args.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def call(*args, &block)
|
26
|
+
if @args
|
27
|
+
@obj.send(@method_id, *(@args+args), &block)
|
28
|
+
else
|
29
|
+
@obj.send(@method_id, *args, &block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
alias [] call
|
34
|
+
end
|
35
|
+
|
36
|
+
end # module Glue
|
37
|
+
|
38
|
+
class Object
|
39
|
+
def literal_method(method_id, *args)
|
40
|
+
Glue::LiteralMethodCallback.new(self, method_id, *args)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# * Michael Neumann <mneumann@ntecs.de>
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
require 'glue/aspects'
|
4
|
+
|
5
|
+
module Glue
|
6
|
+
|
7
|
+
# Represents a locale.
|
8
|
+
#--
|
9
|
+
# TODO: initialize translation map from a yaml file.
|
10
|
+
#++
|
11
|
+
|
12
|
+
class Locale
|
13
|
+
|
14
|
+
# The localization map.
|
15
|
+
|
16
|
+
attr_accessor :map
|
17
|
+
|
18
|
+
def initialize(map)
|
19
|
+
parse_hash(map)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Transalte the given key.
|
23
|
+
#
|
24
|
+
# [+args+]
|
25
|
+
# An array of arguments. The first argument
|
26
|
+
# is the translation key. If additional arguments
|
27
|
+
# are provided they are used for sprintf
|
28
|
+
# interpolation.
|
29
|
+
#--
|
30
|
+
# THINK: Possibly avoid the creation of the
|
31
|
+
# array by making the api less elegant.
|
32
|
+
#++
|
33
|
+
|
34
|
+
def translate(*args)
|
35
|
+
if xlated = @map[args.shift]
|
36
|
+
if xlated.is_a?(String)
|
37
|
+
args.empty? ? xlated : sprintf(xlated, *args)
|
38
|
+
else
|
39
|
+
xlated.call(*args)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
alias_method :[], :translate
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def parse_hash(map)
|
48
|
+
@map = map
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse_yaml(yaml)
|
52
|
+
raise 'Not implemented'
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# Localization support.
|
58
|
+
#
|
59
|
+
# === Example
|
60
|
+
#
|
61
|
+
# locale_en = {
|
62
|
+
# 'See you' => 'See you',
|
63
|
+
# :long_paragraph => 'The best new books, up to 30% reduced price',
|
64
|
+
# :price => 'Price: %d %s',
|
65
|
+
# :proc_price => proc { |value, cur| "Price: #{value} #{cur}" }
|
66
|
+
# }
|
67
|
+
#
|
68
|
+
# locale_de = {
|
69
|
+
# 'See you' => 'Auf wieder sehen',
|
70
|
+
# :long_paragraph => 'Die besten neuer buecher, bis zu 30% reduziert',
|
71
|
+
# ...
|
72
|
+
# }
|
73
|
+
#
|
74
|
+
# Localization.add(:en => locale_en, :de => locale_de)
|
75
|
+
#
|
76
|
+
# lc = Localization.get
|
77
|
+
# lc['See you'] -> See you
|
78
|
+
# lc[:price, 100, 'euro'] -> Price: 100 euro
|
79
|
+
# lc = Localization.get[:de]
|
80
|
+
# lc['See you'] -> Auf wiedersehen
|
81
|
+
#
|
82
|
+
# To make localization even more easier, a LocalizationAspect
|
83
|
+
# is provide provided. Additional transformation macros are
|
84
|
+
# provided if you require 'nitro/compiler/localization'
|
85
|
+
|
86
|
+
class Localization
|
87
|
+
|
88
|
+
class << self
|
89
|
+
|
90
|
+
# A hash of the available locales.
|
91
|
+
|
92
|
+
attr_accessor :locales
|
93
|
+
|
94
|
+
def add(map = {})
|
95
|
+
for key, locale in map
|
96
|
+
if locale.is_a?(String)
|
97
|
+
# this is the name of the localization file.
|
98
|
+
locale = YAML.load(File.read(locale))
|
99
|
+
end
|
100
|
+
@locales[key.to_s] = Locale.new(locale)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Return the localization hash for the given
|
105
|
+
# locale.
|
106
|
+
|
107
|
+
def get(locale = :en)
|
108
|
+
locale ||= 'en'
|
109
|
+
@locales[locale.to_s]
|
110
|
+
end
|
111
|
+
alias_method :locale, :get
|
112
|
+
alias_method :[], :get
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
@locales = {}
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
# Localization Aspect for Nitro controllers.
|
121
|
+
|
122
|
+
module LocalizationAspect
|
123
|
+
def localize
|
124
|
+
@lc = Localization[@context.session[:LOCALE]]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
# * George Moschovitis <gm@navel.gr>
|