nitro 0.1.2
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/AUTHORS +8 -0
- data/ChangeLog +1546 -0
- data/LICENCE +32 -0
- data/README +278 -0
- data/RELEASES +7 -0
- data/Rakefile +79 -0
- data/bin/cluster.rb +219 -0
- data/doc/architecture.txt +28 -0
- data/doc/bugs.txt +7 -0
- data/doc/css.txt +20 -0
- data/doc/ideas.txt +120 -0
- data/doc/pg.txt +47 -0
- data/doc/svn.txt +82 -0
- data/doc/todo.txt +30 -0
- data/etc/new-project.rb +18 -0
- data/examples/simple/README +15 -0
- data/examples/simple/app.rb +31 -0
- data/examples/simple/conf/apache.conf +100 -0
- data/examples/simple/conf/config.rb +89 -0
- data/examples/simple/conf/debug-config.rb +53 -0
- data/examples/simple/conf/live-config.rb +48 -0
- data/examples/simple/conf/overrides.rb +9 -0
- data/examples/simple/conf/requires.rb +51 -0
- data/examples/simple/ctl +32 -0
- data/examples/simple/env.rb +33 -0
- data/examples/simple/install.rb +12 -0
- data/examples/simple/lib/articles/entities.rb +35 -0
- data/examples/simple/lib/articles/lc-en.rb +36 -0
- data/examples/simple/lib/articles/methods.rb +55 -0
- data/examples/simple/lib/articles/part.rb +58 -0
- data/examples/simple/logs/access_log +2 -0
- data/examples/simple/logs/apache.log +3 -0
- data/examples/simple/logs/app.log +1 -0
- data/examples/simple/logs/events.log +1 -0
- data/examples/simple/root/add-article.sx +15 -0
- data/examples/simple/root/article-form.ss +20 -0
- data/examples/simple/root/comments-form.ss +16 -0
- data/examples/simple/root/comments.si +30 -0
- data/examples/simple/root/index.sx +44 -0
- data/examples/simple/root/shader/shader.xsl +100 -0
- data/examples/simple/root/shader/style.css +9 -0
- data/examples/simple/root/view-article.sx +30 -0
- data/examples/tiny/app.rb +30 -0
- data/examples/tiny/conf/apache.conf +100 -0
- data/examples/tiny/conf/config.rb +67 -0
- data/examples/tiny/conf/requires.rb +40 -0
- data/examples/tiny/ctl +31 -0
- data/examples/tiny/logs/access_log +9 -0
- data/examples/tiny/logs/apache.log +9 -0
- data/examples/tiny/root/index.sx +35 -0
- data/lib/n/app/cluster.rb +219 -0
- data/lib/n/app/cookie.rb +86 -0
- data/lib/n/app/filters/autologin.rb +50 -0
- data/lib/n/app/fragment.rb +67 -0
- data/lib/n/app/handlers.rb +120 -0
- data/lib/n/app/handlers/code-handler.rb +184 -0
- data/lib/n/app/handlers/page-handler.rb +612 -0
- data/lib/n/app/request-part.rb +59 -0
- data/lib/n/app/request.rb +653 -0
- data/lib/n/app/script.rb +398 -0
- data/lib/n/app/server.rb +53 -0
- data/lib/n/app/session.rb +224 -0
- data/lib/n/app/user.rb +47 -0
- data/lib/n/app/webrick-servlet.rb +213 -0
- data/lib/n/app/webrick.rb +70 -0
- data/lib/n/application.rb +187 -0
- data/lib/n/config.rb +31 -0
- data/lib/n/db.rb +217 -0
- data/lib/n/db/README +232 -0
- data/lib/n/db/connection.rb +369 -0
- data/lib/n/db/make-release.sh +26 -0
- data/lib/n/db/managed.rb +235 -0
- data/lib/n/db/mixins.rb +282 -0
- data/lib/n/db/mysql.rb +342 -0
- data/lib/n/db/psql.rb +378 -0
- data/lib/n/db/tools.rb +110 -0
- data/lib/n/db/utils.rb +99 -0
- data/lib/n/events.rb +118 -0
- data/lib/n/l10n.rb +22 -0
- data/lib/n/logger.rb +33 -0
- data/lib/n/macros.rb +53 -0
- data/lib/n/mixins.rb +46 -0
- data/lib/n/parts.rb +154 -0
- data/lib/n/properties.rb +194 -0
- data/lib/n/server.rb +61 -0
- data/lib/n/server/PLAYBACK.txt +8 -0
- data/lib/n/server/RESEARCH.txt +13 -0
- data/lib/n/server/filter.rb +77 -0
- data/lib/n/shaders.rb +167 -0
- data/lib/n/sitemap.rb +188 -0
- data/lib/n/std.rb +69 -0
- data/lib/n/sync/clc.rb +108 -0
- data/lib/n/sync/handler.rb +221 -0
- data/lib/n/sync/server.rb +170 -0
- data/lib/n/tools/README +11 -0
- data/lib/n/ui/date-select.rb +74 -0
- data/lib/n/ui/pager.rb +187 -0
- data/lib/n/ui/popup.rb +45 -0
- data/lib/n/ui/select.rb +41 -0
- data/lib/n/ui/tabs.rb +34 -0
- data/lib/n/utils/array.rb +92 -0
- data/lib/n/utils/cache.rb +144 -0
- data/lib/n/utils/gfx.rb +108 -0
- data/lib/n/utils/hash.rb +148 -0
- data/lib/n/utils/html.rb +147 -0
- data/lib/n/utils/http.rb +98 -0
- data/lib/n/utils/mail.rb +28 -0
- data/lib/n/utils/number.rb +31 -0
- data/lib/n/utils/pool.rb +66 -0
- data/lib/n/utils/string.rb +297 -0
- data/lib/n/utils/template.rb +38 -0
- data/lib/n/utils/time.rb +91 -0
- data/lib/n/utils/uri.rb +193 -0
- data/lib/xsl/base.xsl +205 -0
- data/lib/xsl/ce.xsl +30 -0
- data/lib/xsl/localization.xsl +23 -0
- data/lib/xsl/xforms.xsl +26 -0
- data/test/run.rb +95 -0
- metadata +187 -0
data/lib/n/db/tools.rb
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# = Database Tools
|
|
2
|
+
#
|
|
3
|
+
# Useful methods wor working with the Db BAckend
|
|
4
|
+
#
|
|
5
|
+
# code:
|
|
6
|
+
# George Moschovitis <gm@navel.gr>
|
|
7
|
+
# Elias Athanasopoulos <elathan@navel.gr>
|
|
8
|
+
#
|
|
9
|
+
# (c) 2004 Navel, all rights reserved.
|
|
10
|
+
# $Id: tools.rb 71 2004-10-18 10:50:22Z gmosx $
|
|
11
|
+
|
|
12
|
+
module N;
|
|
13
|
+
|
|
14
|
+
require "n/db"
|
|
15
|
+
|
|
16
|
+
# = DbConnection
|
|
17
|
+
#
|
|
18
|
+
# A Connection to the Database.
|
|
19
|
+
#
|
|
20
|
+
module DbTools
|
|
21
|
+
|
|
22
|
+
# Lets say you have changed the definition of a managed object
|
|
23
|
+
# (for example you have added a new prop_accessor, and want to
|
|
24
|
+
# automatically update the database schema.
|
|
25
|
+
# Compares the given class to the actual db schema and
|
|
26
|
+
# automatically alters the backend table if needed.
|
|
27
|
+
# No need to optimize this method.
|
|
28
|
+
#
|
|
29
|
+
def self.alter_table(klass)
|
|
30
|
+
#
|
|
31
|
+
# Use the following query to see the fields in system level:
|
|
32
|
+
#
|
|
33
|
+
# sql = "SELECT attname, attnum FROM pg_attribute, pg_class "
|
|
34
|
+
# sql << "WHERE attrelid = pg_class.oid "
|
|
35
|
+
# sql << "AND relname = '#{klass::DBTABLE}' AND attnum > 0;"
|
|
36
|
+
#
|
|
37
|
+
# In orer to test alter_table() use the following tests:
|
|
38
|
+
#
|
|
39
|
+
# klass.__props << N::Property.new("new_field", String)
|
|
40
|
+
# klass.__props.delete_if{ |member| member.name == "new_field" }
|
|
41
|
+
#
|
|
42
|
+
# Remember you must not uncomment both of the above statements.
|
|
43
|
+
# Uncomment the first one, use alter_table(), the uncomment the
|
|
44
|
+
# seconde one and re-use alter_table().
|
|
45
|
+
#
|
|
46
|
+
$db.open { |db|
|
|
47
|
+
|
|
48
|
+
sql = "SELECT * FROM #{klass::DBTABLE} LIMIT 1;"
|
|
49
|
+
table_fields = db.exec(sql).fields
|
|
50
|
+
|
|
51
|
+
# find fields to be added.
|
|
52
|
+
properties_to_add = []
|
|
53
|
+
klass.__props.each { |klass_member|
|
|
54
|
+
properties_to_add << klass_member unless table_fields.include? klass_member.name
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# find fields to be removed.
|
|
58
|
+
properties_to_remove = []
|
|
59
|
+
table_fields.each { |field|
|
|
60
|
+
properties_to_remove << field unless klass.__props.map{ |member| member.name }.include? field
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
# Add new fields
|
|
64
|
+
fields = []
|
|
65
|
+
properties_to_add.each { |p|
|
|
66
|
+
field = "#{p.symbol}"
|
|
67
|
+
if p.sql
|
|
68
|
+
field << " #{p.sql}"
|
|
69
|
+
else
|
|
70
|
+
field << " #{db.class::TYPEMAP[p.klass]}"
|
|
71
|
+
end
|
|
72
|
+
field << " #{p.sql}" if p.sql
|
|
73
|
+
|
|
74
|
+
fields << field
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
for field in fields
|
|
78
|
+
sql = "ALTER TABLE #{klass::DBTABLE} ADD COLUMN #{field}"
|
|
79
|
+
db.exec_clear(sql)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
removed = nil
|
|
83
|
+
properties_to_remove.each { |p|
|
|
84
|
+
sql = "ALTER TABLE #{klass::DBTABLE} DROP COLUMN #{p} RESTRICT"
|
|
85
|
+
db.exec_clear(sql)
|
|
86
|
+
removed = true
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if removed
|
|
90
|
+
sql = "UPDATE #{klass::DBTABLE}; VACUUM FULL #{klass::DBTABLE};"
|
|
91
|
+
db.exec_clear(sql)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# NOT IMPLEMENTED
|
|
98
|
+
#
|
|
99
|
+
def self.alter_column(klass, old_field, new_field)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# NOT IMPLEMENTED
|
|
103
|
+
#
|
|
104
|
+
def self.rename_table(old_klass, new_klass)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end # module
|
|
110
|
+
|
data/lib/n/db/utils.rb
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# = Database Utilities
|
|
2
|
+
#
|
|
3
|
+
# A collection of database utilities.
|
|
4
|
+
#
|
|
5
|
+
# code:
|
|
6
|
+
# George Moschovitis <gm@navel.gr>
|
|
7
|
+
#
|
|
8
|
+
# (c) 2004 Navel, all rights reserved.
|
|
9
|
+
# $Id$
|
|
10
|
+
|
|
11
|
+
module N;
|
|
12
|
+
|
|
13
|
+
require "n/properties"
|
|
14
|
+
require "n/utils/array"
|
|
15
|
+
require "n/utils/time"
|
|
16
|
+
|
|
17
|
+
# = DbUtils
|
|
18
|
+
#
|
|
19
|
+
# A collection of Database utilities.
|
|
20
|
+
# Additional backend specific utilities are defined in
|
|
21
|
+
# the backend implementations.
|
|
22
|
+
#
|
|
23
|
+
module DbUtils
|
|
24
|
+
|
|
25
|
+
# Escape an sql string
|
|
26
|
+
#
|
|
27
|
+
def self.escape(str)
|
|
28
|
+
# defined in the backend
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Escape bytes
|
|
32
|
+
#
|
|
33
|
+
def self.escape_bytes(bytes)
|
|
34
|
+
# defined in the backend
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# The name of the SQL table where entities of this class are stored.
|
|
38
|
+
# The Module separators are replaced with _ and NOT stripped out so
|
|
39
|
+
# that we can convert back to the original notation if needed.
|
|
40
|
+
#
|
|
41
|
+
def self.sql_table(klass)
|
|
42
|
+
return "#{klass}".gsub(/::/, "_").downcase
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Convert a ruby time to an sql timestamp.
|
|
46
|
+
#
|
|
47
|
+
def self.sql_timestamp(time = Time.now)
|
|
48
|
+
# defined in the backend
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Output YYY-mm-dd
|
|
52
|
+
#
|
|
53
|
+
def self.sql_date(date)
|
|
54
|
+
# defined in the backend
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Parse sql datetime
|
|
58
|
+
#
|
|
59
|
+
def self.parse_sql_timestamp(str)
|
|
60
|
+
# defined in the backend
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Input YYYY-mm-dd
|
|
64
|
+
#
|
|
65
|
+
def self.parse_sql_date(str)
|
|
66
|
+
# defined in the backend
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Return an sql string evaluator for the property.
|
|
70
|
+
# No need to optimize this, used only to precalculate code.
|
|
71
|
+
#
|
|
72
|
+
# FIXME: add extra handling for float.
|
|
73
|
+
#
|
|
74
|
+
def self.write_prop(p)
|
|
75
|
+
if String == p.klass
|
|
76
|
+
return "'#\{DbUtils.escape(@#{p.symbol})\}'"
|
|
77
|
+
elsif Time == p.klass
|
|
78
|
+
return %|#\{@#{p.symbol} ? "'#\{DbUtils.sql_timestamp(@#{p.symbol})\}'" : 'NULL'\}|
|
|
79
|
+
elsif Date == p.klass
|
|
80
|
+
return %|#\{@#{p.symbol} ? "'#\{DbUtils.sql_date(@#{p.symbol})\}'" : 'NULL'\}|
|
|
81
|
+
elsif Object == p.klass or Array == p.klass or Hash == p.klass
|
|
82
|
+
#return "'#\{DbUtils.escape_bytes(Marshal.dump(@#{p.symbol}))\}'"
|
|
83
|
+
return "'#\{DbUtils.escape_bytes(Marshal.dump(@#{p.symbol}))\}'"
|
|
84
|
+
else
|
|
85
|
+
# Fixnum, TrueClass
|
|
86
|
+
return "#\{@#{p.symbol} || 'NULL'\}"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Return an evaluator for reading the property
|
|
91
|
+
# No need to optimize this, used only to precalculate code.
|
|
92
|
+
#
|
|
93
|
+
def self.read_prop(p)
|
|
94
|
+
# defined in the backend
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end # namespace
|
|
99
|
+
|
data/lib/n/events.rb
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# = Events
|
|
2
|
+
#
|
|
3
|
+
# A simple events mechanism.
|
|
4
|
+
#
|
|
5
|
+
# === Design:
|
|
6
|
+
#
|
|
7
|
+
# As always we try to keep the design simple:
|
|
8
|
+
# Events = strings (hiearchical notation)
|
|
9
|
+
# Handlers = named Procs
|
|
10
|
+
# The handlers are named so that we can remove them
|
|
11
|
+
# by name. Also usefull for documentation purposes.
|
|
12
|
+
#
|
|
13
|
+
# === TODO:
|
|
14
|
+
#
|
|
15
|
+
# Add a class of events to allow filtering of certain
|
|
16
|
+
# events. Perhaps name can be used for this!
|
|
17
|
+
#
|
|
18
|
+
# code: tml
|
|
19
|
+
#
|
|
20
|
+
# (c) 2002-2003 Navel, all rights reserved.
|
|
21
|
+
# $Id: events.rb 71 2004-10-18 10:50:22Z gmosx $
|
|
22
|
+
|
|
23
|
+
module N;
|
|
24
|
+
|
|
25
|
+
# = EventManager
|
|
26
|
+
#
|
|
27
|
+
# === Example:
|
|
28
|
+
#
|
|
29
|
+
# $ev.event("id/user/login", user)
|
|
30
|
+
# $ev.add_handler("id/user/login", "login-score", proc { |user|
|
|
31
|
+
# user["score"] += 1
|
|
32
|
+
# })
|
|
33
|
+
#
|
|
34
|
+
class EventManager
|
|
35
|
+
attr :events
|
|
36
|
+
attr_accessor :logger
|
|
37
|
+
|
|
38
|
+
def initialize(logger = nil)
|
|
39
|
+
@events = Hash.new
|
|
40
|
+
@logger = logger
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Register an event handler.
|
|
44
|
+
#
|
|
45
|
+
# === Input:
|
|
46
|
+
# event = the event
|
|
47
|
+
# name = the name of the handler
|
|
48
|
+
# proc = the proc of the hadler
|
|
49
|
+
#
|
|
50
|
+
def add_handler(event, name, proc)
|
|
51
|
+
unless event_handlers = @events[event]
|
|
52
|
+
@events[event] = event_handlers = Hash.new
|
|
53
|
+
end
|
|
54
|
+
event_handlers[name] = proc
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Remove the named handler from the event.
|
|
58
|
+
#
|
|
59
|
+
def remove_handler(event, name)
|
|
60
|
+
if event_handlers = @events[event]
|
|
61
|
+
event_handlers.delete(name)
|
|
62
|
+
else
|
|
63
|
+
$log.debug "ev: cannot remove, handler #{name} not found for event #{event}" if $DBG
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Remove all handlers for the event.
|
|
68
|
+
#
|
|
69
|
+
# === Input:
|
|
70
|
+
# event = the event
|
|
71
|
+
# name = the name of the handler
|
|
72
|
+
#
|
|
73
|
+
def remove_all_handlers(event)
|
|
74
|
+
@events[event] = Hash.new
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Fire an event
|
|
78
|
+
#
|
|
79
|
+
# === Input:
|
|
80
|
+
# event = the event to fire
|
|
81
|
+
# param = parameters for the handler, use an array
|
|
82
|
+
# for multiple parameters.
|
|
83
|
+
#
|
|
84
|
+
def event(event, params)
|
|
85
|
+
if event_handlers = @events[event]
|
|
86
|
+
# call all event handler procs
|
|
87
|
+
for handler in event_handlers.values
|
|
88
|
+
# call the handler with the params.
|
|
89
|
+
handler.call(params)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
if @logger
|
|
93
|
+
if params.is_a?(Array)
|
|
94
|
+
pstr = params.collect{|i| i.to_s()}.join(", ")
|
|
95
|
+
else
|
|
96
|
+
pstr = params.to_s()
|
|
97
|
+
end
|
|
98
|
+
@logger.info("#{event}: #{pstr}")
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
alias_method :fire, :event
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
#
|
|
105
|
+
#
|
|
106
|
+
#
|
|
107
|
+
class Event
|
|
108
|
+
@@manager = EventManager.new()
|
|
109
|
+
|
|
110
|
+
def self.add_handler(event, name, proc)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def self.fire(event, params)
|
|
114
|
+
@@manager.fire(event, params)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
end # module
|
data/lib/n/l10n.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# = L10N, Localization support
|
|
2
|
+
#
|
|
3
|
+
# code: tml
|
|
4
|
+
#
|
|
5
|
+
# (c) 2002-2003 Navel, all rights reserved.
|
|
6
|
+
# $Id: l10n.rb 71 2004-10-18 10:50:22Z gmosx $
|
|
7
|
+
|
|
8
|
+
$lc_en = {}
|
|
9
|
+
$lc_el = {}
|
|
10
|
+
|
|
11
|
+
# = Configuration
|
|
12
|
+
#
|
|
13
|
+
# Override as needed in your application.
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
$lc_map = {
|
|
17
|
+
"en" => $lc_en,
|
|
18
|
+
"el" => $lc_el
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# The locales to use for this application.
|
|
22
|
+
$lc_use = %w{lc-en lc-el}
|
data/lib/n/logger.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# = Logger
|
|
2
|
+
#
|
|
3
|
+
# A simple wrapper arround the Ruby logger. Mainly for compatibility
|
|
4
|
+
# purposes.
|
|
5
|
+
#
|
|
6
|
+
# code: tml
|
|
7
|
+
#
|
|
8
|
+
# (c) 2004 Navel, all rights reserved.
|
|
9
|
+
# $Id: logger.rb 71 2004-10-18 10:50:22Z gmosx $
|
|
10
|
+
|
|
11
|
+
require "logger"
|
|
12
|
+
|
|
13
|
+
class Logger
|
|
14
|
+
alias_method :devel, :debug
|
|
15
|
+
alias_method :fine, :debug
|
|
16
|
+
|
|
17
|
+
def detach
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Used for debuging, remove this in release code.
|
|
21
|
+
#
|
|
22
|
+
def d(str)
|
|
23
|
+
self << "#{str}\n"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Inspect an object. Used for debugging, remove this in release
|
|
27
|
+
# code.
|
|
28
|
+
#
|
|
29
|
+
def i(obj)
|
|
30
|
+
self << "Inspect #{obj.inspect()}\n"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
data/lib/n/macros.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# = Macros
|
|
2
|
+
#
|
|
3
|
+
# A powerfull macro implementation for Ruby. Allows definition
|
|
4
|
+
# of new macro.
|
|
5
|
+
#
|
|
6
|
+
# code: gmosx
|
|
7
|
+
#
|
|
8
|
+
# (c) 2004 Navel, all rights reserved.
|
|
9
|
+
# $Id: macros.rb 71 2004-10-18 10:50:22Z gmosx $
|
|
10
|
+
|
|
11
|
+
$__macros__ = {}
|
|
12
|
+
$__required__ = {}
|
|
13
|
+
|
|
14
|
+
module Kernel
|
|
15
|
+
|
|
16
|
+
alias_method :old_require, :require
|
|
17
|
+
def require(path)
|
|
18
|
+
return if $__required__[path]
|
|
19
|
+
|
|
20
|
+
source = File.read(path)
|
|
21
|
+
|
|
22
|
+
# parse macro
|
|
23
|
+
source.gsub!(/defmacro\s*\/(.*?)\/\s(.*?)endmacro/m) {
|
|
24
|
+
$__macros__[Regexp.new($1)] = $2 ; ""
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
# expand macros
|
|
28
|
+
$__macros__.each { |match, replace|
|
|
29
|
+
source.gsub!(match, replace)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
$__required__[path] = true
|
|
33
|
+
|
|
34
|
+
eval(source)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
require "n/test1.rb"
|
|
40
|
+
require "n/test2.rb"
|
|
41
|
+
|
|
42
|
+
__END__
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
|
|
46
|
+
defmacro /my_macro\((.*)\)/
|
|
47
|
+
begin
|
|
48
|
+
my_function(\1)
|
|
49
|
+
rescue => ex
|
|
50
|
+
puts ex
|
|
51
|
+
end
|
|
52
|
+
endmacro
|
|
53
|
+
|
data/lib/n/mixins.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# = Mixins
|
|
2
|
+
#
|
|
3
|
+
# A collection of useful mixins. Use these to synthesize your
|
|
4
|
+
# entities.
|
|
5
|
+
#
|
|
6
|
+
# code:
|
|
7
|
+
# George Moschovitis <gm@navel.gr>
|
|
8
|
+
#
|
|
9
|
+
# (c) 2004 Navel, all rights reserved.
|
|
10
|
+
# $Id$
|
|
11
|
+
|
|
12
|
+
module N;
|
|
13
|
+
|
|
14
|
+
# = Expirable
|
|
15
|
+
#
|
|
16
|
+
# Generic expiring functionality mixin. This is not exclusive
|
|
17
|
+
# for entities.
|
|
18
|
+
#
|
|
19
|
+
module Expirable
|
|
20
|
+
attr_accessor :expires
|
|
21
|
+
|
|
22
|
+
# Set the expires timeout for this entry.
|
|
23
|
+
|
|
24
|
+
def expires_after(timeout = (60*60*24))
|
|
25
|
+
@expires = Time.now + timeout
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Set the expire timeout for this entry. The timeout happens
|
|
29
|
+
# after (base + rand(spread)) seconds.
|
|
30
|
+
|
|
31
|
+
def expires_spread(base, spread)
|
|
32
|
+
@expires = Time.now + base + rand(spread)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Is this entry expired?
|
|
36
|
+
|
|
37
|
+
def expired?
|
|
38
|
+
if @expires.nil? or (Time.now > @expires)
|
|
39
|
+
return true
|
|
40
|
+
else
|
|
41
|
+
return false
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end # module
|