kiss 1.0.4 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 debug(object)
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.
@@ -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
@@ -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
@@ -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('localhost') do |smtp|
76
- smtp.sendmail(@options[:message], options[:from], options[:to])
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
@@ -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
- @controller
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.pluralize
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(controller = nil)
73
- @controller = controller
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
- @cache[source] ||= begin
79
- dataset = @controller.db[source]
80
- (@@model_dir && source.is_a?(Symbol)) ? begin
81
- # use file_cache
82
- model_path = "#{@@model_dir}/#{source}.rb"
83
- src = Kiss.file_cache(model_path)
84
- klass = Class.new(Kiss::Model)
85
- klass.set_dataset(dataset)
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 db
103
- @controller.db
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)
@@ -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
@@ -19,6 +19,7 @@ module Rack
19
19
  contents.gsub!(/txmt:\/\//, 'http://textmate.local/')
20
20
  contents.gsub!('<body>','<div class="body">')
21
21
  contents.gsub!('</body>','</div>')
22
+ contents.gsub!('<wbr/>','')
22
23
 
23
24
  headers['Content-Length'] = contents.length.to_s
24
25
 
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Rack
2
- # Deprecated; now does nothing.
2
+ # Deprecated. To be removed in Kiss 1.1.
3
3
  # Functionality moved to Kiss#initialize (lib/kiss.rb).
4
4
 
5
5
  class ShowDebug
@@ -1,5 +1,5 @@
1
1
  module Rack
2
- # Deprecated; now does nothing.
2
+ # Deprecated. To be removed in Kiss 1.1.
3
3
  # Functionality moved to Kiss#initialize (lib/kiss.rb).
4
4
 
5
5
  class ShowExceptions
@@ -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.to_s] = value
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(options = {})
55
- path = get_template_path(options)
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(options = {})
70
+ def process(*args)
71
+ options = get_template_options(*args)
61
72
  path = get_template_path(options)
62
- content = erubis(path,binding)
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
- if options.is_a?(String)
70
- path = options
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
- eruby_src = file_cache(path,'template') do |template|
93
- # macros
94
- template.gsub!(/\<\%\s*macro\s+(\w+.*?)\s*\%\>/,'<% def \1; _buf = \'\' %>')
95
- template.gsub!(/\<\%\s*end\s+macro\s*\%\>/,'<% _buf; end %>')
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
- # generic loop iterator, using 'iterate'
98
- template.gsub!(/\<\%\s*iterate\s+(\w+)\s+(.*?)\s*\%\>/,"<% \\1 = Kiss::Iterator.new; \\2; \\1.increment %>")
99
- # for loop iterator
100
- 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 %>")
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
- Erubis::Eruby.new(template).src
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 url_encode(string)
114
- # don't encode to hex: letters, numbers, periods, spaces
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, :url_encode
119
- alias_method :h, :url_encode
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 escape_html(str)
123
- Rack::Utils.escape_html(str)
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