Class: N::App::Script

Inherits:
Object
  • Object
show all
Defined in:
lib/n/app/script.rb

Overview

Script

Base class for scripts. Typically a handler evaluates a script. The base class describing a script is defined here. A generalized fragment caching system is also defined.

see handlers/page-handler::PageScript for more information. – no need to prepend __ to the attributes! (@ is prepended) ++

Direct Known Subclasses

CodeScript, PageScript

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Script

Returns a new instance of Script.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/n/app/script.rb', line 64

def initialize(path)
	@path = "#$root_dir/#{path}"

	# gmosx, INVESTIGATE: createtime == filemtime ?
	
	# the creation time for this script-class
	@create_time = Time.now
	
	# when the filename was last modified
	@file_mtime = File.mtime(@path).to_i

	# sub-scripts set: a set of files this script depends on.
	# We use a hash to implement a set.
	@sub_scripts = N::SafeArray.new

	# a cache for the script outputs (fragments). Keeps multiple revisions
	# of the script output according to user, access rights etc.
	# must be thread safe because it is shared accross threads.
	# 
	# gmosx: DONT DEPRECATE THIS! if we switch to FastCGI, perhaps
	# this will be needed!
	#
	# DISK CACHING IS SLOW!
	#
	@fragment_cache = N::LRUCache.new(1000)
	
	__init()
end

Instance Attribute Details

#cacheabilityObject

is this script cacheable? NONE, SERVER, DOWNSTREAM, CLIENT



62
63
64
# File 'lib/n/app/script.rb', line 62

def cacheability
  @cacheability
end

#keyObject

Returns the value of attribute key.



59
60
61
# File 'lib/n/app/script.rb', line 59

def key
  @key
end

#pathObject

the full path to the actual script file



54
55
56
# File 'lib/n/app/script.rb', line 54

def path
  @path
end

#sub_scriptsObject

the sub scripts.



57
58
59
# File 'lib/n/app/script.rb', line 57

def sub_scripts
  @sub_scripts
end

Class Method Details

.admin_role(role) ⇒ Object

Evals a standard admin?() method.



388
389
390
391
392
393
394
# File 'lib/n/app/script.rb', line 388

def self.admin_role(role)
	class_eval %{
		def admin?(request)
			return request.user.role?("#{role}") 
		end
	}
end

.enable_cache!Object

Sets cache?() to return true



378
379
380
381
382
383
384
# File 'lib/n/app/script.rb', line 378

def self.enable_cache!
	class_eval %{	
		def __cache?(request)
			return true
		end
	}
end

Instance Method Details

#__action(request, params = nil) ⇒ Object Also known as: _a

Encodes an action url to the same page. Params is almost always != nil, no need to optimize the case.



261
262
263
264
265
266
267
# File 'lib/n/app/script.rb', line 261

def __action(request, params = nil)		
	if request.parameters.empty?
		return "#{request.translated_uri}?#{params}"
	else
		return "#{request.translated_uri}?#{request.query_string};#{params}"
	end
end

#__authorize?(request) ⇒ Boolean

authorize access to this script ?

Returns:

  • (Boolean)


350
351
352
# File 'lib/n/app/script.rb', line 350

def __authorize?(request)
	return true
end

#__cache?(request) ⇒ Boolean

Is this script cacheable for this request?

Returns:

  • (Boolean)


173
174
175
176
# File 'lib/n/app/script.rb', line 173

def __cache?(request)
	# By default if lm is overriden the page is cacheable
	return __lm(request) 
end

#__cache_clearObject

clear the fragment_cache



187
188
189
# File 'lib/n/app/script.rb', line 187

def __cache_clear
	@fragment_cache.clear
end

#__cache_get(key) ⇒ Object

get a fragment from the fragment cache in a thread safe manner.

Output: the fragment object encapsulating the output of this script.



196
197
198
# File 'lib/n/app/script.rb', line 196

def __cache_get(key)
	return @fragment_cache[key]
end

#__cache_put(key, fragment) ⇒ Object

add a new fragment in the fragment cache in a thread safe manner. encapsulate the fragment text (== body) in a fragment object.



203
204
205
# File 'lib/n/app/script.rb', line 203

def __cache_put(key, fragment)
	@fragment_cache[key] = fragment
end

#__calc_lm(request) ⇒ Object

Calculate LastModified for HTTP1.1 caching takes into account all subscripts! also takes into account the script file modification



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/n/app/script.rb', line 138

def __calc_lm(request)
	unless lm = __lm(request)
		lm = @file_mtime
	else
		lm = @file_mtime if @file_mtime > lm
	end
	
	if @sub_scripts
		for script in @sub_scripts
			if slm = script.__calc_lm(request)
				unless lm
					lm = slm
				else
					lm = slm if slm > lm
				end
			end
		end
	end
	
	return lm
end

#__calc_tag(request) ⇒ Object

Recursively calculate tag.



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/n/app/script.rb', line 115

def __calc_tag(request)
	tag = __tag(request)

	if @sub_scripts
		for script in @sub_scripts
			tag << script.__calc_tag(request)
		end
	end
	
	return tag
end

#__create_timeObject



239
240
241
# File 'lib/n/app/script.rb', line 239

def __create_time
	return @create_time
end

#__etag(request) ⇒ Object

Calculates the ETag fof HTTP1.1 caching. This etag is typically used in the downstream, so we can be VERY granular :-) ie we can even encode a user id!

Coded by top level scripts only! Typically combines __tag and __last_modified



167
168
169
# File 'lib/n/app/script.rb', line 167

def __etag(request)
	return "#{__calc_lm(request)}#{__calc_tag(request)}#{request.tag}" # .hash.to_s
end

#__file_mtimeObject



243
244
245
# File 'lib/n/app/script.rb', line 243

def __file_mtime
	return @file_mtime
end

#__force_login(request) ⇒ Object

force a logged-in user for this page. implemented like the n1-version to avoid checking everytime for login, use the if __force method.



364
365
366
367
368
369
370
# File 'lib/n/app/script.rb', line 364

def (request)
	if request.session["USER"].anonymous?
		request.redirect("/id/login.sx?_go=#{request.uri}")
		return false
	end
	return true
end

#__include(url, request) ⇒ Object

Dynamically include (“inject”) a subpage (fragment) in this page. Dynamic means at run-time.



235
236
237
# File 'lib/n/app/script.rb', line 235

def __include(url, request)
	return ""
end

#__initObject

This method is called at compile time to perform additional initialization.



96
97
# File 'lib/n/app/script.rb', line 96

def __init
end

#__init_render(request) ⇒ Object

This method is called before rendering to perform additional initialization.



102
103
104
# File 'lib/n/app/script.rb', line 102

def __init_render(request)
	# nop
end

#__inject(url, request) ⇒ Object

Dynamically include (“inject”) a subpage (fragment) in this page. Dynamic means at run-time.



228
229
230
# File 'lib/n/app/script.rb', line 228

def __inject(url, request)
	return ""
end

#__lm(request) ⇒ Object

Calculate LastModified for HTTP1.1 caching Return the last modified time for this script.



130
131
132
# File 'lib/n/app/script.rb', line 130

def __lm(request)
	return nil
end

#__pathObject



247
248
249
# File 'lib/n/app/script.rb', line 247

def __path
	return @path
end

#__post_evaluate(request) ⇒ Object

executed after script evaluation, even for cached fragments! not used yet.



282
283
# File 'lib/n/app/script.rb', line 282

def __post_evaluate(request)
end

#__post_render(request) ⇒ Object

Post-render hook. NOT executed for cached fragments. not used yet.

Returns: text that is appended to the request, by default the EMPTY_STRING



301
302
303
# File 'lib/n/app/script.rb', line 301

def __post_render(request)
	return EMPTY_STRING
end

#__pre_evaluate(request) ⇒ Object

executed prior to script evaluation, even for cached fragments! not used yet.



276
277
# File 'lib/n/app/script.rb', line 276

def __pre_evaluate(request)
end

#__pre_render(request) ⇒ Object

Pre-render hook. NOT executed for cached fragments not used yet.

Returns: text that is prepended to the request, by default the EMPTY_STRING



291
292
293
# File 'lib/n/app/script.rb', line 291

def __pre_render(request)
	return EMPTY_STRING
end

#__render(request) ⇒ Object

renders the script as html output to be send to the borwser. the output of this script is the script fragment. this method is constructed dynamically by the handler.

Design:

the parameters to this method are visible to page scripts. in order to avoid namespace pollution and dangerous bugs in the scripts we prepend an underscore to differentiate them. n1 used



222
223
# File 'lib/n/app/script.rb', line 222

def __render(request)
end

#__shader(request) ⇒ Object

get the shader to use for this script



356
357
358
# File 'lib/n/app/script.rb', line 356

def __shader(request)
	return nil
end

#__tag(request) ⇒ Object

Tag for this request



108
109
110
111
# File 'lib/n/app/script.rb', line 108

def __tag(request)
	# gmosx: dont return nil!
	return ""
end

#admin?(request) ⇒ Boolean


Actions:

Returns:

  • (Boolean)


254
255
256
# File 'lib/n/app/script.rb', line 254

def admin?(request)
	return false;
end

#cache?(request) ⇒ Boolean

enable fragment caching for this script? to avoid storing in the cache uncacheable fragments

Returns:

  • (Boolean)


321
322
323
324
325
# File 'lib/n/app/script.rb', line 321

def cache?(request)
	# gmosx: AAAAAAAAARGHHH!!! NASTY keep this false!
	# to save memory!
	return false
end

#cache_flag(request) ⇒ Object

Calculate a hash modifier (flag) to differentiate caching according to user roles or other dynamic conditions. The calculated flag is appended to the fragmant hash.

Design: use this separate method to allow the top level page to collect the flags for all sub-pages and build a super-flag.



314
315
316
# File 'lib/n/app/script.rb', line 314

def cache_flag(request)
	return Fragment::ADMIN_FLAG if admin?(request)
end

#cache_valid?(fragment, request) ⇒ Boolean

is the output of the script (the fragment) valid for this request? used for cache invalidation calculations. By default returns false.

Input: __fragment_key: the server automatically generates a fragment_key (typically the request.real_path) and passes this to this methods for further customization. The key passed is the base key, the method is responsible to build the final key (taking user roles, etc into account). request: used to customize the fragment_key for this request. customized fragment_keys denote request classes.

Output: is the fragment valid for this request?

Side-effects: WARNING: the method potentially modifies __fragment_key!

Returns:

  • (Boolean)


344
345
346
# File 'lib/n/app/script.rb', line 344

def cache_valid?(fragment, request)
	return false
end