kiss 1.0.4 → 1.1
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/Rakefile +9 -6
- data/VERSION +1 -1
- data/bin/kiss +75 -0
- data/data/scaffold.tgz +0 -0
- data/lib/kiss.rb +328 -337
- data/lib/kiss/action.rb +133 -47
- data/lib/kiss/bench.rb +2 -3
- data/lib/kiss/controller_accessors.rb +24 -68
- data/lib/kiss/debug.rb +4 -5
- data/lib/kiss/exception_report.rb +10 -6
- data/lib/kiss/hacks.rb +7 -3
- data/lib/kiss/iterator.rb +6 -6
- data/lib/kiss/login.rb +45 -0
- data/lib/kiss/mailer.rb +20 -2
- data/lib/kiss/model.rb +27 -31
- data/lib/kiss/rack/bench.rb +5 -0
- data/lib/kiss/rack/errors_ok.rb +19 -0
- data/lib/kiss/rack/facebook.rb +1 -0
- data/lib/kiss/rack/recorder.rb +22 -0
- data/lib/kiss/rack/show_debug.rb +1 -1
- data/lib/kiss/rack/show_exceptions.rb +1 -1
- data/lib/kiss/template_methods.rb +71 -30
- metadata +16 -8
data/lib/kiss/hacks.rb
CHANGED
@@ -7,14 +7,18 @@
|
|
7
7
|
|
8
8
|
# This gets called outside of controller contexts; used mainly for debugging
|
9
9
|
# during Kiss framework development.
|
10
|
-
def
|
10
|
+
def force_debug(object)
|
11
11
|
print "Content-type: text/html\n\n" unless $debug
|
12
12
|
$debug = true
|
13
13
|
|
14
|
-
puts object.inspect + '<br/>'
|
15
|
-
puts '<small>at ' + Kernel.caller[0] + '</small><br/>'
|
14
|
+
puts object.inspect + '<br/>' + '<small>at ' + Kernel.caller[0] + '</small><br/>'
|
16
15
|
object
|
17
16
|
end
|
17
|
+
alias :debug :force_debug
|
18
|
+
|
19
|
+
def trace(object)
|
20
|
+
debug(object)
|
21
|
+
end
|
18
22
|
|
19
23
|
class Kiss
|
20
24
|
# Used when Kiss#file_cache called from Kiss::Action#file_cache.
|
data/lib/kiss/iterator.rb
CHANGED
@@ -10,12 +10,6 @@ class Kiss
|
|
10
10
|
@index = -1
|
11
11
|
end
|
12
12
|
|
13
|
-
# Used by template erubis pre-processing voodoo to advance
|
14
|
-
# the iterator index. Not intended for any other use.
|
15
|
-
def increment
|
16
|
-
@index = @index + 1
|
17
|
-
end
|
18
|
-
|
19
13
|
# Return current iteration number, indexed from one instead of zero.
|
20
14
|
def count
|
21
15
|
@index + 1
|
@@ -52,5 +46,11 @@ class Kiss
|
|
52
46
|
def size
|
53
47
|
@collection ? @collection.size : nil
|
54
48
|
end
|
49
|
+
|
50
|
+
# Used by template erubis pre-processing voodoo to advance
|
51
|
+
# the iterator index. Not intended for any other use.
|
52
|
+
def increment
|
53
|
+
@index = @index + 1
|
54
|
+
end
|
55
55
|
end
|
56
56
|
end
|
data/lib/kiss/login.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
class Kiss
|
2
|
+
class Login < Hash
|
3
|
+
def initialize(session)
|
4
|
+
@session = session
|
5
|
+
@session['login'] ||= {}
|
6
|
+
|
7
|
+
# check if login expired
|
8
|
+
if expired?
|
9
|
+
# login expired
|
10
|
+
@session['login'] = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
@persist_data = @session['login']
|
14
|
+
self.merge!(@persist_data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def expired?
|
18
|
+
@session['login']['expires_at'] && session['login']['expires_at'] < Time.now
|
19
|
+
end
|
20
|
+
|
21
|
+
def persist(data = {})
|
22
|
+
@persist_data.merge!(data)
|
23
|
+
self.merge!(data)
|
24
|
+
end
|
25
|
+
|
26
|
+
def expires_at(time)
|
27
|
+
persist(:expires_at => time)
|
28
|
+
end
|
29
|
+
def expires_at=(seconds)
|
30
|
+
expires_at(seconds)
|
31
|
+
end
|
32
|
+
|
33
|
+
def expires_in(seconds)
|
34
|
+
persist(:expires_at => Time.now + seconds)
|
35
|
+
end
|
36
|
+
def expires_in=(seconds)
|
37
|
+
expires_in(seconds)
|
38
|
+
end
|
39
|
+
|
40
|
+
def clear
|
41
|
+
@session['login'] = {}
|
42
|
+
super()
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/kiss/mailer.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
class Kiss
|
2
2
|
# This class creates, renders, and sends email messages.
|
3
|
+
|
4
|
+
# @options
|
5
|
+
# :server, :port, :domain, :account, :password, :auth - for SMTP login
|
6
|
+
# :from/to - used by SMTP to send message (ignored by sendmail)
|
7
|
+
# :message - message headers/body text
|
8
|
+
# :template - name of email template to use to create message
|
9
|
+
# :data/vars - values to inject into email template
|
10
|
+
# :sendmail_path - filesystem path to sendmail executable
|
11
|
+
|
3
12
|
class Mailer
|
4
13
|
include Kiss::TemplateMethods
|
5
14
|
|
@@ -54,6 +63,8 @@ class Kiss
|
|
54
63
|
end
|
55
64
|
|
56
65
|
# Attempts to send message using /usr/sbin/sendmail.
|
66
|
+
# NOTE: sendmail ignores :from and :to options, using
|
67
|
+
# From and To headers from the message
|
57
68
|
def sendmail(options = nil)
|
58
69
|
merge_options(options) if options
|
59
70
|
|
@@ -72,8 +83,15 @@ class Kiss
|
|
72
83
|
|
73
84
|
require 'net/smtp' unless defined?(Net::SMTP)
|
74
85
|
# begin
|
75
|
-
Net::SMTP.start(
|
76
|
-
|
86
|
+
Net::SMTP.start(
|
87
|
+
@options[:server] || 'localhost',
|
88
|
+
@options[:port] || 25,
|
89
|
+
@options[:domain] || nil,
|
90
|
+
@options[:account] || @options[:username] || nil,
|
91
|
+
@options[:password] || nil,
|
92
|
+
@options[:auth] || :plain
|
93
|
+
) do |smtp|
|
94
|
+
smtp.sendmail(@options[:message], @options[:from], @options[:to])
|
77
95
|
end
|
78
96
|
# rescue
|
79
97
|
# end
|
data/lib/kiss/model.rb
CHANGED
@@ -8,16 +8,14 @@ class Kiss
|
|
8
8
|
super(source)
|
9
9
|
end
|
10
10
|
|
11
|
+
# This method is called by Sequel::Model's association def methods.
|
12
|
+
# Must return singularized table name for correct association key names.
|
11
13
|
def name
|
12
|
-
@table.to_s
|
14
|
+
@table.to_s.singularize
|
13
15
|
end
|
14
16
|
|
15
17
|
def controller
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
def controller=(controller)
|
20
|
-
@controller = controller
|
18
|
+
db.kiss_controller
|
21
19
|
end
|
22
20
|
|
23
21
|
def table
|
@@ -40,9 +38,9 @@ class Kiss
|
|
40
38
|
# TODO: Fix has_many and many_to_many associations
|
41
39
|
def associate(type, name, opts = {}, &block)
|
42
40
|
opts = opts.clone
|
43
|
-
|
41
|
+
|
44
42
|
unless opts[:class] || opts[:class_name]
|
45
|
-
opts[:class_name] = name.to_s.
|
43
|
+
opts[:class_name] = name.to_s.singularize
|
46
44
|
end
|
47
45
|
|
48
46
|
super(type, name, opts, &block)
|
@@ -69,39 +67,37 @@ class Kiss
|
|
69
67
|
@@model_dir = model_dir && ::File.directory?(model_dir) ? model_dir : nil
|
70
68
|
end
|
71
69
|
|
72
|
-
def initialize(
|
73
|
-
@
|
70
|
+
def initialize(database = nil)
|
71
|
+
@db = database
|
74
72
|
@cache = {}
|
75
73
|
end
|
74
|
+
|
75
|
+
def new_model_class(database,source)
|
76
|
+
klass = Class.new(Kiss::Model)
|
77
|
+
klass.set_dataset(database[source])
|
78
|
+
klass.table = source
|
79
|
+
klass
|
80
|
+
end
|
76
81
|
|
77
82
|
def [](source)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
klass
|
86
|
-
klass.controller = @controller
|
87
|
-
klass.table = source
|
83
|
+
raise 'argument to model cache must be symbol of database table name' unless source.is_a?(Symbol)
|
84
|
+
|
85
|
+
database = @db
|
86
|
+
@@model_dir ? begin
|
87
|
+
# use file_cache
|
88
|
+
model_path = "#{@@model_dir}/#{source}.rb"
|
89
|
+
Kiss.file_cache(model_path) do |src|
|
90
|
+
klass = new_model_class(database,source)
|
88
91
|
klass.class_eval(src,model_path) if src
|
89
92
|
klass
|
90
|
-
end : begin
|
91
|
-
# no model_dir, or source is not a symbol
|
92
|
-
# no mapping from source to filesystem path
|
93
|
-
klass = Class.new(Kiss::Model)
|
94
|
-
klass.set_dataset(dataset)
|
95
|
-
klass.table = source if source.is_a?(Symbol)
|
96
|
-
klass.controller = @controller
|
97
|
-
klass
|
98
93
|
end
|
99
|
-
end
|
94
|
+
end : @cache[source] ||= new_model_class(database,source)
|
100
95
|
end
|
101
96
|
|
102
|
-
def
|
103
|
-
@
|
97
|
+
def database
|
98
|
+
@db
|
104
99
|
end
|
100
|
+
alias_method :db, :database
|
105
101
|
|
106
102
|
def literal(*args)
|
107
103
|
Sequel::Model.dataset.literal(*args)
|
data/lib/kiss/rack/bench.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
1
|
module Rack
|
2
|
+
# Deprecated. Benchmarks output now prepended at end of Kiss#call.
|
3
|
+
# This module is kept for benchmarking full request operation time;
|
4
|
+
# this should be moved to Kiss#call as well. Then remove this module
|
5
|
+
# for Kiss 1.1.
|
6
|
+
|
2
7
|
# Rack::Bench shows total request duration for any request.
|
3
8
|
class Bench
|
4
9
|
def initialize(app)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rack
|
2
|
+
# Rack::Facebook formats HTTP responses to remove certain status codes
|
3
|
+
# and HTML entities that are invalid as FBML responses.
|
4
|
+
class ErrorsOK
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
code, headers, body = @app.call(env)
|
11
|
+
|
12
|
+
if code >= 500 && code < 600
|
13
|
+
code = 200
|
14
|
+
end
|
15
|
+
|
16
|
+
[ code, headers, body ]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/kiss/rack/facebook.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rack
|
2
|
+
class Recorder
|
3
|
+
def initialize(app)
|
4
|
+
@app = app
|
5
|
+
|
6
|
+
@@filepath ||= begin
|
7
|
+
puts "Yo. Starting app..."
|
8
|
+
puts "Would ask you for a test name or recording path here."
|
9
|
+
'something'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
code, headers, body = @app.call(env)
|
15
|
+
|
16
|
+
puts "OK, that was fun."
|
17
|
+
puts "Would save some request and response data here."
|
18
|
+
|
19
|
+
[ code, headers, body ]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/kiss/rack/show_debug.rb
CHANGED
@@ -2,17 +2,27 @@ class Kiss
|
|
2
2
|
module TemplateMethods
|
3
3
|
include Kiss::ControllerAccessors
|
4
4
|
|
5
|
+
def db
|
6
|
+
controller.database
|
7
|
+
end
|
8
|
+
alias_method :database, :db
|
9
|
+
|
5
10
|
# Contains data set by action/mailer logic to be displayed in templates.
|
6
11
|
def data
|
7
12
|
@data
|
8
13
|
end
|
9
14
|
alias_method :vars, :data
|
10
15
|
|
16
|
+
def data=(hash)
|
17
|
+
@data = hash
|
18
|
+
end
|
19
|
+
alias_method :'vars=', :'data='
|
20
|
+
|
11
21
|
# Merges specified data (key-value pairs) into template data hash.
|
12
22
|
def set(vars)
|
13
23
|
vars.each_pair do |key,value|
|
14
24
|
# convert symbols to strings
|
15
|
-
@data[key
|
25
|
+
@data[key] = value
|
16
26
|
end
|
17
27
|
end
|
18
28
|
|
@@ -51,28 +61,51 @@ class Kiss
|
|
51
61
|
|
52
62
|
# Reads file specified by options and return contents (without template
|
53
63
|
# processing).
|
54
|
-
def insert(
|
55
|
-
path = get_template_path(
|
64
|
+
def insert(*args)
|
65
|
+
path = get_template_path(get_template_options(*args))
|
56
66
|
content = ::File.read(path)
|
57
67
|
end
|
58
68
|
|
59
69
|
# Processes template specified by options and return results.
|
60
|
-
def process(
|
70
|
+
def process(*args)
|
71
|
+
options = get_template_options(*args)
|
61
72
|
path = get_template_path(options)
|
62
|
-
|
73
|
+
|
74
|
+
if (options[:data] || options[:vars])
|
75
|
+
new_data = (options[:data] || {}).merge(options[:vars] || {})
|
76
|
+
old_data = self.data
|
77
|
+
self.data = self.data.merge(new_data)
|
78
|
+
else
|
79
|
+
old_data = nil
|
80
|
+
end
|
81
|
+
|
82
|
+
content = erubis(path)
|
83
|
+
self.data = old_data if old_data
|
84
|
+
|
85
|
+
content
|
86
|
+
end
|
87
|
+
alias_method :process_template, :process
|
88
|
+
|
89
|
+
# Convert arguments into options hash for use get_template_path.
|
90
|
+
def get_template_options(*args)
|
91
|
+
case args.length
|
92
|
+
when 0
|
93
|
+
{}
|
94
|
+
when 1
|
95
|
+
args[0].is_a?(Hash) ? args[0] : { :template => args[0] }
|
96
|
+
when 2
|
97
|
+
args[1].merge( :template => args[0] )
|
98
|
+
else
|
99
|
+
raise 'too many arguments'
|
100
|
+
end
|
63
101
|
end
|
64
102
|
|
65
103
|
# Gets path to insert/template file from specified options.
|
66
|
-
def get_template_path(options)
|
104
|
+
def get_template_path(options = {})
|
67
105
|
@current_template_dir ||= @template_dir + action_subdir
|
68
106
|
|
69
|
-
|
70
|
-
|
71
|
-
extension = nil
|
72
|
-
else
|
73
|
-
path = options[:template]
|
74
|
-
extension = options[:extension]
|
75
|
-
end
|
107
|
+
path = options[:template]
|
108
|
+
extension = options[:extension]
|
76
109
|
|
77
110
|
path += ".#{extension || 'rhtml'}" unless path =~ /\./
|
78
111
|
(path =~ /\A\//) ? "#{@template_dir}#{path}" : "#{@current_template_dir}/#{path}"
|
@@ -89,18 +122,25 @@ class Kiss
|
|
89
122
|
old_template_dir = @current_template_dir
|
90
123
|
@current_template_dir = path.sub(/\/?[^\/]*\Z/,'')
|
91
124
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
template
|
125
|
+
# read the file, parse into eruby source,
|
126
|
+
# and pre-process source for Kiss additions
|
127
|
+
eruby_src = file_cache(path) do |template|
|
128
|
+
template ? begin
|
129
|
+
# macros
|
130
|
+
template.gsub!(/\<\%\s*macro\s+(\w+.*?)\s*\%\>/,'<% def \1; _buf = \'\' %>')
|
131
|
+
template.gsub!(/\<\%\s*end\s+macro\s*\%\>/,'<% _buf; end %>')
|
96
132
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
133
|
+
# generic loop iterator, using 'iterate'
|
134
|
+
template.gsub!(/\<\%\s*iterate\s+(\w+)\s+(.*?)\s*\%\>/,"<% \\1 = Kiss::Iterator.new; \\2; \\1.increment %>")
|
135
|
+
# for loop iterator
|
136
|
+
template.gsub!(/\<\%\s*for\s+(\w+)\s+in\s+(.*?)\s*\%\>/,"<% \\1_loop = Kiss::Iterator.new(\\2); for \\1 in \\1_loop.collection; \\1_loop.increment %>")
|
101
137
|
|
102
|
-
|
138
|
+
Erubis::Eruby.new(template).src
|
139
|
+
end : nil
|
103
140
|
end
|
141
|
+
raise Kiss::FileNotFound, "template '#{path}' not found" unless eruby_src
|
142
|
+
|
143
|
+
# evaluate source in context of template_binding
|
104
144
|
result = eval eruby_src, template_binding, path
|
105
145
|
|
106
146
|
# restore previous template dir
|
@@ -110,17 +150,18 @@ class Kiss
|
|
110
150
|
end
|
111
151
|
|
112
152
|
# Escapes string for use in URLs.
|
113
|
-
def
|
114
|
-
|
115
|
-
# encode space to +
|
116
|
-
string.gsub(/([^A-Za-z0-9\.])/) { sprintf("%%%02X", $&.unpack("C")[0]) }
|
153
|
+
def url_escape(string)
|
154
|
+
Kiss.url_escape(str)
|
117
155
|
end
|
118
|
-
alias_method :escape, :
|
119
|
-
alias_method :
|
156
|
+
alias_method :escape, :url_escape
|
157
|
+
alias_method :url_encode, :url_escape
|
158
|
+
alias_method :escape_url, :url_escape
|
120
159
|
|
121
160
|
# Encodes string for output to HTML.
|
122
|
-
def
|
123
|
-
|
161
|
+
def html_escape(str)
|
162
|
+
Kiss.html_escape(str)
|
124
163
|
end
|
164
|
+
alias_method :h, :html_escape
|
165
|
+
alias_method :escape_html, :html_escape
|
125
166
|
end
|
126
167
|
end
|