kiss 0.9.4 → 1.0

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.
@@ -4,33 +4,37 @@ class Kiss
4
4
  # to cache database model classes, unless no model_dir is specified.
5
5
  class Model < Sequel::Model
6
6
  class << self
7
+ def set_dataset(source)
8
+ super(source)
9
+ end
10
+
7
11
  def name
8
12
  @table.to_s
9
13
  end
10
-
11
- # Name symbol for default foreign key
12
- def default_remote_key
13
- :"#{name.singularize.demodulize.underscore}_id"
14
+
15
+ def controller
16
+ @controller
14
17
  end
15
18
 
16
- def set_controller(controller)
17
- @@controller = controller
19
+ def controller=(controller)
20
+ @controller = controller
18
21
  end
19
22
 
20
- def set_dataset(source)
21
- super(source)
23
+ def table
24
+ @table.to_sym
22
25
  end
23
26
 
24
27
  def table=(table)
25
28
  @table = table
26
29
  end
27
30
 
28
- def controller
29
- @@controller
31
+ # Name symbol for default foreign key
32
+ def default_foreign_key
33
+ :"#{name.singularize.demodulize.underscore}_id"
30
34
  end
31
35
 
32
- def dbm
33
- @@controller.dbm
36
+ def find_or_new(cond)
37
+ find(cond) || new(cond)
34
38
  end
35
39
 
36
40
  # TODO: Fix has_many and many_to_many associations
@@ -45,6 +49,8 @@ class Kiss
45
49
 
46
50
  association_reflections[name]
47
51
  end
52
+
53
+ include Kiss::KissAccessors
48
54
  end
49
55
 
50
56
  def method_missing(meth)
@@ -52,38 +58,43 @@ class Kiss
52
58
  end
53
59
 
54
60
  def controller
55
- @@controller
61
+ self.class.controller
56
62
  end
57
63
 
58
64
  include Kiss::ControllerAccessors
59
65
  end
60
66
 
61
67
  class ModelCache
62
- def initialize(controller,model_dir = nil)
68
+ def self.model_dir=(model_dir = nil)
69
+ @@model_dir = model_dir && ::File.directory?(model_dir) ? model_dir : nil
70
+ end
71
+
72
+ def initialize(controller = nil)
63
73
  @controller = controller
64
- @model_dir = model_dir && File.directory?(model_dir) ? model_dir : nil
65
74
  @cache = {}
66
75
  end
67
76
 
68
77
  def [](source)
69
- (@model_dir && source.is_a?(Symbol)) ? begin
70
- # use controller's file_cache
71
- model_path = "#{@model_dir}/#{source}.rb"
72
- @controller.file_cache(model_path) do |src|
78
+ @cache[source] ||= begin
79
+ dataset = Model.db[source]
80
+ dataset.controller = @controller
81
+ (@@model_dir && source.is_a?(Symbol)) ? begin
82
+ # use file_cache
83
+ model_path = "#{@@model_dir}/#{source}.rb"
84
+ src = Kiss.file_cache(model_path)
73
85
  klass = Class.new(Kiss::Model)
74
- klass.set_dataset(Model.db[source])
86
+ klass.set_dataset(dataset)
87
+ klass.controller = @controller
75
88
  klass.table = source
76
89
  klass.class_eval(src,model_path) if src
77
90
  klass
78
- end
79
- end : begin
80
- # no model_dir, or source is not a symbol
81
- # no mapping from source to filesystem path
82
- # use ModelCache's own cache
83
- @cache[source] ||= begin
91
+ end : begin
92
+ # no model_dir, or source is not a symbol
93
+ # no mapping from source to filesystem path
84
94
  klass = Class.new(Kiss::Model)
85
- klass.set_dataset(Model.db[source])
95
+ klass.set_dataset(dataset)
86
96
  klass.table = source if source.is_a?(Symbol)
97
+ klass.controller = @controller
87
98
  klass
88
99
  end
89
100
  end
@@ -106,9 +117,30 @@ end
106
117
 
107
118
  Sequel::Model::Associations::AssociationReflection.class_eval do
108
119
  def associated_class
109
- self[:class] ||= Kiss::Model.controller.dbm[self[:class_name].to_s.pluralize.to_sym]
120
+ self[:class] ||= self[:model].controller.dbm[self[:class_name].to_s.pluralize.to_sym]
110
121
  end
111
122
  def default_left_key
112
123
  :"#{self[:model].name.singularize.underscore}_id"
113
124
  end
125
+ end
126
+
127
+ class Sequel::Model
128
+ def inherited(subclass)
129
+ self.instance_variables.each do |var|
130
+ subclass.instance_variable_set(var, instance_variable_get(var))
131
+ end
132
+ end
133
+ end
134
+
135
+ class Sequel::Dataset
136
+ def controller=(controller)
137
+ @controller = controller
138
+ end
139
+
140
+ def execute(sql, opts={}, &block)
141
+ if @controller
142
+ @controller.last_sql = sql
143
+ end
144
+ @db.execute(sql, {:server=>@opts[:server] || :read_only}.merge(opts), &block)
145
+ end
114
146
  end
@@ -1,58 +1,16 @@
1
- def bench(label = nil)
2
- Rack::Bench.close_bench_item(Kernel.caller[0])
3
- Rack::Bench.on
4
-
5
- if label
6
- Rack::Bench.push_bench_item(
7
- :label => label,
8
- :start_time => Time.now,
9
- :start_context => Kernel.caller[0]
10
- )
11
- end
12
- end
13
-
14
1
  module Rack
15
- # Rack::Bench adds benchmarking capabilities to Kiss applications.
16
- #
17
- # bench(label) starts a new timer, which ends upon the next call to
18
- # bench, or when execution returns to Rack::Bench.
19
- #
20
- # bench can be called without a label to end the previous timer
21
- # without starting a new one.
22
- #
23
- # Total request duration is also displayed for any request in which
24
- # the bench function is called.
2
+ # Rack::Bench shows total request duration for any request.
25
3
  class Bench
26
- def self.on
27
- @@bench = true
28
- end
29
-
30
- def self.close_bench_item(end_context = nil)
31
- if @@bench_items[-1] && !@@bench_items[-1][:end_time]
32
- @@bench_items[-1][:end_time] = Time.now
33
- @@bench_items[-1][:end_context] = end_context
34
- end
35
- end
36
-
37
- def self.push_bench_item(item)
38
- @@bench_items.push(item)
39
- end
40
-
41
4
  def initialize(app)
42
5
  @app = app
43
6
  end
44
7
 
45
8
  def call(env)
46
- @@bench = false
47
- @@bench_items = []
48
-
49
9
  start_time = Time.now
50
10
  code, headers, body = @app.call(env)
51
11
  end_time = Time.now
52
12
 
53
- if @@bench
54
- Rack::Bench.close_bench_item
55
- contents = <<-EOT
13
+ contents = <<-EOT
56
14
  <style>
57
15
  .kiss_bench {
58
16
  text-align: left;
@@ -73,59 +31,16 @@ module Rack
73
31
  text-decoration: underline;
74
32
  }
75
33
  </style>
76
- EOT
77
-
78
- contents += @@bench_items.map do |item|
79
- start_link = context_link(item[:start_context])
80
- end_link = context_link(item[:end_context])
81
-
82
- <<-EOT
83
- <div class="kiss_bench">
84
- <tt><b>#{item[:label].gsub(/\</,'&lt;')} duration: #{sprintf("%0.3f",item[:end_time].to_f - item[:start_time].to_f)} s</b></tt>
85
- <small style="line-height: 105%; display: block; padding-bottom: 3px">kiss bench<br/>started at #{start_link}<br/>ended at #{end_link || 'return to kiss bench'}</small>
86
- </div>
87
- EOT
88
- end.join
89
-
90
- contents += <<-EOT
91
34
  <div class="kiss_bench">
92
35
  <tt><b>TOTAL request duration: #{sprintf("%0.3f",end_time.to_f - start_time.to_f)} s</b></tt>
93
36
  <br><small>kiss bench request total</small>
94
37
  </div>
95
38
  EOT
96
- else
97
- contents = ''
98
- end
99
39
 
100
40
  body.each {|p| contents += p }
101
41
  headers['Content-Length'] = contents.length.to_s
102
42
 
103
43
  [ code, headers, contents ]
104
44
  end
105
-
106
- def absolute_path(filename)
107
- filename = ( filename =~ /\A\// ? '' : (Dir.pwd + '/') ) + filename
108
- end
109
-
110
- def context_link(context)
111
- return nil unless context
112
-
113
- filename, line, method = context.split(/:/)
114
- textmate_url = "txmt://open?url=file://" + h(absolute_path(filename)) + '&amp;line=' + line
115
- %Q(<a href="#{textmate_url}">#{filename}:#{line}</a> #{method})
116
- end
117
-
118
- def textmate_href(frame)
119
- "txmt://open?url=file://" + h(absolute_path(context)).sub(/:/,'&amp;line=')
120
- end
121
-
122
- def h(obj) # :nodoc:
123
- case obj
124
- when String
125
- Utils.escape_html(obj).gsub(/^(\s+)/) {'&nbsp;' * $1.length}
126
- else
127
- Utils.escape_html(obj.inspect)
128
- end
129
- end
130
45
  end
131
46
  end
@@ -1,23 +1,14 @@
1
1
  module Rack
2
- # Rack::ShowExceptions catches exceptions raised from the app,
3
- # showing a useful backtrace with clickable stack frames and
4
- # TextMate links to source files, as well as the last database
5
- # query, GET/POST params, cookies, and Rack environment variables.
6
- #
7
- # Be careful using this on public-facing sites as it could reveal
8
- # potentially sensitive information to malicious users.
2
+ # Deprecated; now does nothing.
3
+ # Functionality moved to Kiss#initialize (lib/kiss.rb).
9
4
 
10
5
  class LogExceptions
11
6
  def initialize(app,path)
12
7
  @app = app
13
- @@file = ::File.open(path,'w')
14
8
  end
15
9
 
16
10
  def call(env)
17
11
  @app.call(env)
18
- rescue StandardError, LoadError, SyntaxError => e
19
- @@file.print Kiss::ExceptionReport.generate(env, e) + "\n--- End of exception report --- \n\n"
20
- raise
21
12
  end
22
13
  end
23
14
  end
@@ -1,14 +1,6 @@
1
- $debug_messages = []
2
- def debug(object)
3
- $debug_messages.push( [object.inspect, Kernel.caller[0]] )
4
- object
5
- end
6
-
7
1
  module Rack
8
- # Rack::ShowDebug displays messages logged by the debug function.
9
- #
10
- # Be careful using this on public-facing sites as it could reveal
11
- # potentially sensitive information to malicious users.
2
+ # Deprecated; now does nothing.
3
+ # Functionality moved to Kiss#initialize (lib/kiss.rb).
12
4
 
13
5
  class ShowDebug
14
6
  def initialize(app)
@@ -16,67 +8,7 @@ module Rack
16
8
  end
17
9
 
18
10
  def call(env)
19
- $debug_messages = []
20
- code, headers, body = @app.call(env)
21
-
22
- if $debug_messages.size > 0
23
- contents = <<-EOT
24
- <style>
25
- .kiss_debug {
26
- text-align: left;
27
- padding: 3px 7px;
28
- border: 1px solid #ebe;
29
- border-top: 1px solid #fdf;
30
- border-bottom: 1px solid #d6d;
31
- background-color: #fbf;
32
- font-size: 12px;
33
- color: #101;
34
- }
35
- .kiss_debug a {
36
- color: #707;
37
- text-decoration: none;
38
- }
39
- .kiss_debug a:hover {
40
- color: #707;
41
- text-decoration: underline;
42
- }
43
- </style>
44
- EOT
45
- contents += $debug_messages.map do |object,context|
46
- filename, line, method = context.split(/:/)
47
- textmate_url = "txmt://open?url=file://" + h(absolute_path(filename)) + '&amp;line=' + line
48
- <<-EOT
49
- <div class="kiss_debug">
50
- <tt><b>#{object.gsub(/\</,'&lt;')}</b></tt>
51
- <br><small>kiss debug output at <a href="#{textmate_url}">#{filename}:#{line}</a> #{method}</small>
52
- </div>
53
- EOT
54
- end.join
55
- else
56
- contents = ''
57
- end
58
-
59
- body.each {|p| contents += p }
60
- headers['Content-Length'] = contents.length.to_s
61
-
62
- [ code, headers, contents ]
63
- end
64
-
65
- def absolute_path(filename)
66
- filename = ( filename =~ /\A\// ? '' : (Dir.pwd + '/') ) + filename
67
- end
68
-
69
- def textmate_href(frame)
70
- "txmt://open?url=file://" + h(absolute_path(context)).sub(/:/,'&amp;line=')
71
- end
72
-
73
- def h(obj) # :nodoc:
74
- case obj
75
- when String
76
- Utils.escape_html(obj).gsub(/^(\s+)/) {'&nbsp;' * $1.length}
77
- else
78
- Utils.escape_html(obj.inspect)
79
- end
11
+ @app.call(env)
80
12
  end
81
13
  end
82
14
  end
@@ -1,11 +1,6 @@
1
1
  module Rack
2
- # Rack::ShowExceptions catches exceptions raised from the app,
3
- # showing a useful backtrace with clickable stack frames and
4
- # TextMate links to source files, as well as the last database
5
- # query, GET/POST params, cookies, and Rack environment variables.
6
- #
7
- # Be careful using this on public-facing sites as it could reveal
8
- # potentially sensitive information to malicious users.
2
+ # Deprecated; now does nothing.
3
+ # Functionality moved to Kiss#initialize (lib/kiss.rb).
9
4
 
10
5
  class ShowExceptions
11
6
  def initialize(app)
@@ -14,14 +9,6 @@ module Rack
14
9
 
15
10
  def call(env)
16
11
  @app.call(env)
17
- rescue StandardError, LoadError, SyntaxError => e
18
- body = Kiss::ExceptionReport.generate(env, e)
19
- [500, {
20
- "Content-Type" => "text/html",
21
- "Content-Length" => body.length.to_s,
22
- "X-Kiss-Error-Type" => e.class.name,
23
- "X-Kiss-Error-Message" => e.message.sub(/\n.*/m,'')
24
- }, body]
25
12
  end
26
13
  end
27
14
  end
@@ -13,8 +13,10 @@ module Sequel
13
13
  # Fixes bug in Sequel 1.5; shouldn't be needed for Sequel 2.x
14
14
  # (need to double-check, however).
15
15
  def fetch_arrays(sql)
16
- @db.execute_select(sql) do |r|
17
- r.each_array {|row| yield row}
16
+ execute(sql) do |r|
17
+ while row = r.fetch_row
18
+ yield row
19
+ end
18
20
  end
19
21
  self
20
22
  end
@@ -0,0 +1,31 @@
1
+ class Kiss
2
+ class StaticFile
3
+ def initialize(path,mime_type = nil)
4
+ @path = path
5
+ @mime_type = mime_type
6
+ end
7
+
8
+ def finish
9
+ ext = File.extname(@path)[1..-1]
10
+
11
+ if File.file?(@path) && File.readable?(@path)
12
+ [200, {
13
+ "Last-Modified" => File.mtime(@path).rfc822,
14
+ "Content-Type" => @mime_type || Kiss.mime_type(ext) || "text/plain",
15
+ "Content-Length" => File.size(@path).to_s
16
+ }, self]
17
+ else
18
+ return [404, {"Content-Type" => "text/plain"},
19
+ ["File not found: #{@path}\n"]]
20
+ end
21
+ end
22
+
23
+ def each
24
+ File.open(@path, "rb") { |file|
25
+ while part = file.read(8192)
26
+ yield part
27
+ end
28
+ }
29
+ end
30
+ end
31
+ end