glue 0.31.0 → 0.40.0
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/AUTHORS +1 -1
- data/doc/LICENSE +2 -3
- data/doc/RELEASES +0 -4
- data/lib/glue.rb +3 -3
- data/lib/glue/attribute.rb +114 -0
- data/lib/glue/attributeutils.rb +117 -0
- data/lib/glue/autoreload.rb +0 -4
- data/lib/glue/builder.rb +0 -2
- data/lib/glue/builder/xml.rb +0 -2
- data/lib/glue/cache.rb +3 -5
- data/lib/glue/cache/drb.rb +0 -2
- data/lib/glue/cache/memory.rb +0 -2
- data/lib/glue/cache/og.rb +11 -6
- data/lib/glue/configuration.rb +60 -15
- data/lib/glue/fixture.rb +3 -5
- data/lib/glue/localization.rb +0 -2
- data/lib/glue/logger.rb +1 -2
- data/lib/glue/mail.rb +0 -2
- data/lib/glue/mailer.rb +4 -2
- data/lib/glue/mailer/incoming.rb +0 -2
- data/lib/glue/mailer/outgoing.rb +3 -5
- data/lib/glue/settings.rb +0 -2
- data/lib/glue/uri.rb +0 -2
- data/lib/glue/validation.rb +6 -8
- data/test/glue/builder/tc_xml.rb +3 -2
- data/test/glue/tc_attribute.rb +112 -0
- data/test/glue/{tc_property_mixins.rb → tc_attribute_mixins.rb} +9 -11
- data/test/glue/tc_configuration.rb +1 -1
- data/test/glue/tc_fixture.rb +4 -3
- data/test/glue/tc_logger.rb +2 -2
- data/test/glue/tc_mail.rb +22 -21
- data/test/glue/tc_stores.rb +0 -2
- data/test/glue/tc_uri.rb +12 -12
- data/test/glue/tc_validation.rb +13 -13
- metadata +52 -64
- data/INSTALL +0 -56
- data/ProjectInfo +0 -49
- data/README +0 -21
- data/lib/glue/markup.rb +0 -123
- data/lib/glue/property.rb +0 -290
- data/lib/glue/sanitize.rb +0 -48
- data/lib/glue/template.rb +0 -219
- data/setup.rb +0 -1585
- data/test/glue/tc_property.rb +0 -112
- data/test/glue/tc_property_type_checking.rb +0 -41
- data/test/glue/tc_template.rb +0 -35
data/doc/AUTHORS
CHANGED
data/doc/LICENSE
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
The BSD License
|
2
2
|
|
3
|
-
Copyright (c) 2004-
|
4
|
-
Copyright (c) 2004-2005, Navel Ltd. (http://www.navel.gr)
|
3
|
+
Copyright (c) 2004-2006, George K. Moschovitis. (http://www.gmosx.com)
|
5
4
|
All rights reserved.
|
6
5
|
|
7
6
|
Redistribution and use in source and binary forms, with or without
|
@@ -15,7 +14,7 @@ notice, this list of conditions and the following disclaimer.
|
|
15
14
|
notice, this list of conditions and the following disclaimer in the
|
16
15
|
documentation and/or other materials provided with the distribution.
|
17
16
|
|
18
|
-
* Neither the name of
|
17
|
+
* Neither the name of Glue nor the names of its contributors may be
|
19
18
|
used to endorse or promote products derived from this software
|
20
19
|
without specific prior written permission.
|
21
20
|
|
data/doc/RELEASES
CHANGED
data/lib/glue.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
# = Glue
|
2
2
|
#
|
3
3
|
# Copyright (c) 2004-2006, George Moschovitis (http://www.gmosx.com)
|
4
|
-
# Copyright (c) 2004-2006, Navel Ltd (http://www.navel.gr)
|
5
4
|
#
|
6
5
|
# Glue (http://www.nitroproject.org) is copyrighted free software
|
7
|
-
# created and maintained by George Moschovitis (mailto:
|
6
|
+
# created and maintained by George Moschovitis (mailto:george.moschovitis@gmail.com)
|
8
7
|
# and released under the standard BSD Licence. For details
|
9
8
|
# consult the file doc/LICENCE.
|
10
9
|
|
@@ -16,7 +15,8 @@ require 'facets/more/paramix' # keep this before module/is
|
|
16
15
|
require 'facets/core/module/is'
|
17
16
|
require 'facets/core/class/cattr'
|
18
17
|
|
19
|
-
require 'glue/
|
18
|
+
require 'glue/attribute'
|
19
|
+
require 'glue/attributeutils'
|
20
20
|
|
21
21
|
# Glue is a collection of reusable utilities and methods to
|
22
22
|
# especially suited to Nitro and Og coding. We try to extract
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# This file extends the functionality in facets/more/annotation.
|
2
|
+
|
3
|
+
require 'facets/more/annotation'
|
4
|
+
require 'facets/more/annattr'
|
5
|
+
require 'facets/more/aspects'
|
6
|
+
|
7
|
+
require 'glue/validation'
|
8
|
+
require 'og/entity'
|
9
|
+
|
10
|
+
class Module
|
11
|
+
|
12
|
+
# If the class has serializable attributes, automatically
|
13
|
+
# add some useful mixins.
|
14
|
+
#
|
15
|
+
# Extends the default facets implementation.
|
16
|
+
|
17
|
+
[:attr_reader, :attr_writer, :attr_accessor].each do |m|
|
18
|
+
module_eval %{
|
19
|
+
alias_method :#{m}_previous, :#{m}
|
20
|
+
|
21
|
+
def #{m} *args
|
22
|
+
# gmosx: this is a hack, rethink!
|
23
|
+
|
24
|
+
unless klass = args.last.is_a?(Hash) ? args.last[:class] : nil
|
25
|
+
for a in args
|
26
|
+
if a.is_a? Class
|
27
|
+
klass = a
|
28
|
+
break
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# If the class defines the included_as_property callback
|
34
|
+
# call to modify the base with custom code.
|
35
|
+
|
36
|
+
if klass.respond_to? :included_as_property
|
37
|
+
klass.included_as_property(self, args)
|
38
|
+
else
|
39
|
+
#{m}_previous *args
|
40
|
+
end
|
41
|
+
|
42
|
+
unless serializable_attributes.empty?
|
43
|
+
include Og::EntityMixin unless ancestors.include?(Og::EntityMixin)
|
44
|
+
include Glue::Validation unless ancestors.include?(Glue::Validation)
|
45
|
+
include Aspects unless ancestors.include?(Aspects)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
alias_method :property, :attr_accessor
|
52
|
+
|
53
|
+
# Return the serializable attributes of this class.
|
54
|
+
# Serializable are attributes with the class annotation that
|
55
|
+
# are not marked as :serializable => false.
|
56
|
+
#
|
57
|
+
# === Examples
|
58
|
+
#
|
59
|
+
# class MyClass
|
60
|
+
# attr_accessor :test
|
61
|
+
# attr_accessor :name, String, :doc => 'Hello'
|
62
|
+
# attr_accessor :age, Fixnum
|
63
|
+
# attr_accessor :body, String, :serialize => false
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# MyClass.attributes # => [:test, :name, :age, :body]
|
67
|
+
# MyClass.serializable_attributes # => [:name, :age]
|
68
|
+
|
69
|
+
def serializable_attributes
|
70
|
+
attributes.find_all do |a|
|
71
|
+
anno = self.ann(a)
|
72
|
+
anno.class? and (anno.serialize != false)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#--
|
77
|
+
# Define force methods for the given attribute.
|
78
|
+
#++
|
79
|
+
|
80
|
+
def define_force_method_for(sym)
|
81
|
+
if klass = self.ann(sym).class
|
82
|
+
code = %{
|
83
|
+
def __force_#{sym}(val)
|
84
|
+
if respond_to?(:force_#{sym})
|
85
|
+
self.#{sym} = force_#{sym}(val)
|
86
|
+
else
|
87
|
+
self.#{sym}=(} << case klass.name
|
88
|
+
when Fixnum.name: 'val.to_s.empty? ? nil : val.to_i'
|
89
|
+
when String.name: 'val.to_s'
|
90
|
+
when Float.name: 'val.to_f'
|
91
|
+
when Time.name: 'val.is_a?(Hash) ? Time.local(val["year"],val["month"],val["day"],val["hour"],val["min"]) : Time.parse(val.to_s)'
|
92
|
+
when Date.name: 'val.is_a?(Hash) ? Time.local(val["year"],val["month"],val["day"]).to_date : Time.parse(val.to_s).to_date'
|
93
|
+
when TrueClass.name, FalseClass.name: 'val == "on" or val == "true" ? true: val.to_i > 0'
|
94
|
+
else 'val'
|
95
|
+
end + %{)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
}
|
99
|
+
|
100
|
+
module_eval code
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
#--
|
105
|
+
# Define all force methods.
|
106
|
+
#++
|
107
|
+
|
108
|
+
def define_force_methods
|
109
|
+
for a in serializable_attributes
|
110
|
+
define_force_method_for(a)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'og/relation/all'
|
3
|
+
|
4
|
+
#--
|
5
|
+
# TODO: find a better name!
|
6
|
+
# TODO: this is nitro request specific, should probably get moved
|
7
|
+
# into the Nitro directory.
|
8
|
+
#++
|
9
|
+
|
10
|
+
class AttributeUtils
|
11
|
+
class << self
|
12
|
+
|
13
|
+
#--
|
14
|
+
# TODO: Add preprocessing.
|
15
|
+
#++
|
16
|
+
|
17
|
+
def set_attr(obj, name, value)
|
18
|
+
obj.send("__force_#{name}", value)
|
19
|
+
rescue Object => ex
|
20
|
+
obj.instance_variable_set("@#{name}", value)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Populate an object from a hash of values.
|
24
|
+
# This is a truly dangerous method.
|
25
|
+
#
|
26
|
+
# === Options
|
27
|
+
#
|
28
|
+
# * name
|
29
|
+
# * force_boolean
|
30
|
+
|
31
|
+
def populate_object(obj, values, options = {})
|
32
|
+
# If a class is passed create an instance.
|
33
|
+
|
34
|
+
obj = obj.new if obj.is_a?(Class)
|
35
|
+
|
36
|
+
for sym in obj.class.serializable_attributes
|
37
|
+
anno = obj.class.ann(sym)
|
38
|
+
|
39
|
+
unless options[:all]
|
40
|
+
# THINK: should skip control none attributes?
|
41
|
+
next if sym == obj.class.primary_key or anno.control == :none or anno.disable_control?
|
42
|
+
end
|
43
|
+
|
44
|
+
prop_name = sym.to_s
|
45
|
+
|
46
|
+
# See if there is an incoming request param for this prop.
|
47
|
+
|
48
|
+
if values.has_key? prop_name
|
49
|
+
|
50
|
+
prop_value = values[prop_name]
|
51
|
+
|
52
|
+
# to_s must be called on the prop_value incase the
|
53
|
+
# request is IOString.
|
54
|
+
|
55
|
+
prop_value = prop_value.to_s unless prop_value.is_a?(Hash) or prop_value.is_a?(Array)
|
56
|
+
|
57
|
+
# If property is a Blob dont overwrite current
|
58
|
+
# property's data if "".
|
59
|
+
|
60
|
+
break if anno.class == Og::Blob and prop_value.empty?
|
61
|
+
|
62
|
+
set_attr(obj, prop_name, CGI.unescape(prop_value))
|
63
|
+
|
64
|
+
elsif options[:force_boolean] and (anno.class == TrueClass or anno.class == FalseClass)
|
65
|
+
# Set a boolean property to false if it is not in the
|
66
|
+
# request. Requires force_boolean == true.
|
67
|
+
|
68
|
+
set_attr(obj, prop_name, 0)
|
69
|
+
obj.send("__force_#{prop_name}", 0)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
if options[:assign_relations]
|
74
|
+
for rel in obj.class.relations
|
75
|
+
unless options[:all]
|
76
|
+
next if rel.options[:control] == :none or rel.options[:disable_control]
|
77
|
+
end
|
78
|
+
|
79
|
+
rel_name = rel.name.to_s
|
80
|
+
|
81
|
+
# Renew the relations from values
|
82
|
+
|
83
|
+
if rel.kind_of?(Og::RefersTo)
|
84
|
+
if foreign_oid = values[rel_name]
|
85
|
+
foreign_oid = foreign_oid.to_s unless foreign_oid.is_a?(Hash) or foreign_oid.is_a?(Array)
|
86
|
+
foreign_oid = nil if foreign_oid == 'nil' or foreign_oid == 'none'
|
87
|
+
end
|
88
|
+
set_attr(obj, rel.foreign_key, foreign_oid)
|
89
|
+
elsif rel.kind_of?(Og::JoinsMany) || rel.kind_of?(Og::HasMany)
|
90
|
+
collection = obj.send(rel_name)
|
91
|
+
collection.remove_all
|
92
|
+
if values.has_key?(rel_name)
|
93
|
+
primary_keys = values[rel_name]
|
94
|
+
primary_keys.each do |v|
|
95
|
+
v = v.to_s
|
96
|
+
next if v == "nil" or v == "none"
|
97
|
+
collection << rel.target_class[v.to_i]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
#--
|
105
|
+
# gmosx, FIXME: this is a hack, will be replaced with proper
|
106
|
+
# code soon.
|
107
|
+
#++
|
108
|
+
|
109
|
+
for callback in obj.class.assign_callbacks
|
110
|
+
callback.call(obj, values, options)
|
111
|
+
end if obj.class.respond_to?(:assign_callbacks)
|
112
|
+
|
113
|
+
return obj
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
data/lib/glue/autoreload.rb
CHANGED
data/lib/glue/builder.rb
CHANGED
data/lib/glue/builder/xml.rb
CHANGED
data/lib/glue/cache.rb
CHANGED
@@ -7,9 +7,9 @@ end
|
|
7
7
|
|
8
8
|
# A general cache mechanism.
|
9
9
|
#
|
10
|
-
# This cache system was originaly developed for Nitro. It is
|
11
|
-
# to cache fragments, og objects (entities), sessions,
|
12
|
-
# scoped variables and more.
|
10
|
+
# This cache system was originaly developed for Nitro. It is
|
11
|
+
# used to cache fragments, og objects (entities), sessions,
|
12
|
+
# application scoped variables and more.
|
13
13
|
|
14
14
|
class Cache
|
15
15
|
|
@@ -20,5 +20,3 @@ class Cache
|
|
20
20
|
end
|
21
21
|
|
22
22
|
end
|
23
|
-
|
24
|
-
# * George Moschovitis <gm@navel.gr>
|
data/lib/glue/cache/drb.rb
CHANGED
data/lib/glue/cache/memory.rb
CHANGED
data/lib/glue/cache/og.rb
CHANGED
@@ -4,10 +4,14 @@ require 'base64'
|
|
4
4
|
module Glue
|
5
5
|
|
6
6
|
class OgCached
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
include Og::EntityMixin
|
8
|
+
|
9
|
+
property :unique_id, String, :sql => 'PRIMARY KEY'
|
10
|
+
property :expires, Time
|
11
|
+
property :cache_name, String
|
12
|
+
property :content, String
|
13
|
+
|
14
|
+
set_primary_key :unique_id, String
|
11
15
|
end
|
12
16
|
|
13
17
|
class OgCache
|
@@ -26,11 +30,12 @@ module Glue
|
|
26
30
|
end
|
27
31
|
#s.content = v.to_yaml
|
28
32
|
s.content = encode(v)
|
29
|
-
s.
|
33
|
+
s.insert
|
30
34
|
end
|
31
35
|
|
32
36
|
def [](k)
|
33
|
-
s = OgCached.find_by_unique_id_and_cache_name(k.to_s, @cache_name)
|
37
|
+
s = OgCached.find_by_unique_id_and_cache_name(k.to_s, @cache_name)
|
38
|
+
decode(s.content) if s
|
34
39
|
end
|
35
40
|
|
36
41
|
def gc!
|
data/lib/glue/configuration.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
require '
|
3
|
+
require 'facets/core/kernel/constant'
|
4
|
+
require 'facets/more/synchash'
|
5
|
+
require 'facets/more/dictionary'
|
6
|
+
require 'facets/core/string/capitalized'
|
7
|
+
require 'facets/core/class/cattr'
|
7
8
|
|
8
9
|
module Glue
|
9
10
|
|
@@ -98,6 +99,51 @@ class Configuration
|
|
98
99
|
end
|
99
100
|
|
100
101
|
class << self
|
102
|
+
|
103
|
+
# The configuration mode, typical modes include :debug,
|
104
|
+
# :stage, :live.
|
105
|
+
#
|
106
|
+
# [:debug]
|
107
|
+
# useful when debugging, extra debug information
|
108
|
+
# is emmited, actions, templates and shaders are
|
109
|
+
# reloaded, etc. The execution speed of the application
|
110
|
+
# is impaired.
|
111
|
+
#
|
112
|
+
# [:stage]
|
113
|
+
# test the application with live parameters
|
114
|
+
# (typically on a staging server).
|
115
|
+
#
|
116
|
+
# [:live]
|
117
|
+
# use the parameters for the live (production)
|
118
|
+
# server. Optimized for speed.
|
119
|
+
#
|
120
|
+
# Tries to set the default value from the CONFIGURATION_MODE
|
121
|
+
# environment variable.
|
122
|
+
|
123
|
+
attr_accessor :mode
|
124
|
+
|
125
|
+
def mode
|
126
|
+
@mode || ENV.fetch('CONFIGURATION_MODE', :debug).to_sym
|
127
|
+
end
|
128
|
+
|
129
|
+
alias kernel_load load
|
130
|
+
|
131
|
+
# Attempt to load external configuration in Ruby or
|
132
|
+
# YAML format. The files:
|
133
|
+
#
|
134
|
+
# * conf/mode.rb
|
135
|
+
# * conf/mode.yaml
|
136
|
+
#
|
137
|
+
# are considered.
|
138
|
+
|
139
|
+
def load(m = mode)
|
140
|
+
ruby_conf = "conf/#{m}.rb"
|
141
|
+
kernel_load(ruby_conf) if File.exist?(ruby_conf)
|
142
|
+
|
143
|
+
# Try to configure from a yaml file.
|
144
|
+
yml_conf = "conf/#{m}.yml"
|
145
|
+
Configuration.load_yaml(yml_conf) if File.exist?(yml_conf)
|
146
|
+
end
|
101
147
|
|
102
148
|
# Inject the configuration parameters provided as a hash
|
103
149
|
# (dictionary, ordered) to classes to be configured.
|
@@ -115,24 +161,26 @@ class Configuration
|
|
115
161
|
|
116
162
|
# Parse configuration parameters in yaml format.
|
117
163
|
|
118
|
-
def
|
164
|
+
def parse_yaml(options)
|
119
165
|
temp = YAML::load(options)
|
120
166
|
options = Dictionary.new
|
121
167
|
temp.each do |k, v|
|
122
|
-
|
123
|
-
options[k.gsub(/\./, '::').to_sym] = v
|
124
|
-
rescue Object
|
125
|
-
options[k] = v
|
126
|
-
end
|
168
|
+
options[k.gsub(/\./, '::').to_sym] = v
|
127
169
|
end
|
128
170
|
|
129
171
|
setup(options)
|
130
172
|
end
|
131
173
|
|
174
|
+
# Load an external ruby configuration file. Constant missing
|
175
|
+
# errors are not reported for extra flexibility.
|
176
|
+
|
177
|
+
def load_ruby(filename)
|
178
|
+
end
|
179
|
+
|
132
180
|
# Load and parse an external yaml configuration file.
|
133
181
|
|
134
|
-
def
|
135
|
-
|
182
|
+
def load_yaml(filename)
|
183
|
+
parse_yaml(File.read(filename))
|
136
184
|
end
|
137
185
|
|
138
186
|
# Manually add a configuration setting. The class key can
|
@@ -174,7 +222,6 @@ class Configuration
|
|
174
222
|
alias_method :all, :settings
|
175
223
|
alias_method :[], :settings
|
176
224
|
|
177
|
-
|
178
225
|
#--
|
179
226
|
# FIXME: this does not work as expected.
|
180
227
|
#++
|
@@ -224,5 +271,3 @@ class Module
|
|
224
271
|
end
|
225
272
|
|
226
273
|
end
|
227
|
-
|
228
|
-
# * George Moschovitis <gm@navel.gr>
|