kiss 1.0.1 → 1.0.3
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/VERSION +1 -1
- data/lib/kiss.rb +153 -109
- data/lib/kiss/action.rb +2 -2
- data/lib/kiss/controller_accessors.rb +13 -5
- data/lib/kiss/exception_report.rb +1 -0
- data/lib/kiss/hacks.rb +39 -106
- data/lib/kiss/model.rb +63 -10
- data/lib/kiss/sequel_session.rb +5 -5
- data/lib/kiss/template_methods.rb +14 -6
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.3
|
data/lib/kiss.rb
CHANGED
@@ -10,7 +10,6 @@ require 'rubygems'
|
|
10
10
|
require 'yaml'
|
11
11
|
require 'rack'
|
12
12
|
require 'rack/request'
|
13
|
-
require 'sequel'
|
14
13
|
require 'erubis'
|
15
14
|
|
16
15
|
require 'kiss/hacks'
|
@@ -19,7 +18,7 @@ require 'kiss/controller_accessors'
|
|
19
18
|
require 'kiss/template_methods'
|
20
19
|
require 'kiss/action'
|
21
20
|
|
22
|
-
|
21
|
+
autoload :Sequel, 'sequel'
|
23
22
|
|
24
23
|
module Rack
|
25
24
|
autoload :Bench, 'kiss/rack/bench'
|
@@ -86,11 +85,11 @@ class Kiss
|
|
86
85
|
|
87
86
|
# attributes below are application-wide
|
88
87
|
cattr_reader :action_dir, :template_dir, :email_template_dir, :model_dir, :upload_dir,
|
89
|
-
:evolution_dir, :asset_dir, :public_dir, :
|
88
|
+
:evolution_dir, :asset_dir, :public_dir, :environment, :options, :layout, :rack_file
|
90
89
|
|
91
90
|
# attributes below are request-specific
|
92
91
|
attr_reader :params, :args, :action, :action_subdir, :action_path, :extension, :host, :request,
|
93
|
-
:
|
92
|
+
:exception_cache
|
94
93
|
|
95
94
|
attr_accessor :last_sql
|
96
95
|
|
@@ -119,9 +118,6 @@ class Kiss
|
|
119
118
|
else
|
120
119
|
load(options)
|
121
120
|
end
|
122
|
-
|
123
|
-
# TODO: rewrite evolution file exists check for speed
|
124
|
-
check_evolution_number if @@db
|
125
121
|
|
126
122
|
app = self
|
127
123
|
builder_options = @@options[:rack_builder] || []
|
@@ -199,6 +195,7 @@ class Kiss
|
|
199
195
|
@@lib_dirs = ['lib']
|
200
196
|
@@gem_dirs = ['gems']
|
201
197
|
@@require = []
|
198
|
+
@@authenticate_exclude = ['/logout']
|
202
199
|
|
203
200
|
# common (shared) config
|
204
201
|
if (File.file?(config_file = @@config_dir+'/common.yml'))
|
@@ -218,7 +215,6 @@ class Kiss
|
|
218
215
|
@@asset_dir = @@public_dir = @@options[:asset_dir] || @@options[:public_dir] || 'public_html'
|
219
216
|
|
220
217
|
@@model_dir = @@options[:model_dir] || 'models'
|
221
|
-
Kiss::ModelCache.model_dir = @@model_dir
|
222
218
|
|
223
219
|
@@evolution_dir = @@options[:evolution_dir] || 'evolutions'
|
224
220
|
|
@@ -266,32 +262,8 @@ class Kiss
|
|
266
262
|
end
|
267
263
|
|
268
264
|
# database
|
269
|
-
|
270
|
-
|
271
|
-
@@db = sequel.is_a?(String) ? (Sequel.open sequel) : sequel.is_a?(Hash) ? (Sequel.open sequel) : sequel
|
272
|
-
|
273
|
-
if @@db.class.name == 'Sequel::MySQL::Database'
|
274
|
-
# add fetch_arrays, all_arrays methods
|
275
|
-
require 'kiss/sequel_mysql'
|
276
|
-
# turn off convert_tinyint_to_bool, unless options say otherwise
|
277
|
-
Sequel.convert_tinyint_to_bool = false unless @@options[:convert_tinyint_to_bool]
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
# setup session storage, if session class specified in config
|
282
|
-
@@session_class.setup_storage(self) if @@session_class
|
283
|
-
|
284
|
-
# prepare authenticate_exclude
|
285
|
-
if @@options[:authenticate_all]
|
286
|
-
if @@options[:authenticate_exclude].is_a?(Array)
|
287
|
-
@@options[:authenticate_exclude] = @@options[:authenticate_exclude].map do |action|
|
288
|
-
action = '/'+action unless action =~ /\A\//
|
289
|
-
action
|
290
|
-
end
|
291
|
-
else
|
292
|
-
@@options[:authenticate_exclude] = []
|
293
|
-
end
|
294
|
-
end
|
265
|
+
@@database_config = @@options[:database]
|
266
|
+
@@database_pool = []
|
295
267
|
|
296
268
|
self
|
297
269
|
end
|
@@ -328,6 +300,9 @@ class Kiss
|
|
328
300
|
if require_libs = config_options.delete(:require)
|
329
301
|
@@require.push( require_libs )
|
330
302
|
end
|
303
|
+
if auth_exclude = config_options.delete(:authenticate_exclude)
|
304
|
+
@@authenticate_exclude.push( *(auth_exclude.map { |action| action =~ /\A\// ? action : '/'+action }) )
|
305
|
+
end
|
331
306
|
|
332
307
|
@@options.merge!( config_options )
|
333
308
|
end
|
@@ -413,11 +388,6 @@ class Kiss
|
|
413
388
|
|
414
389
|
text
|
415
390
|
end
|
416
|
-
|
417
|
-
# Returns exception cache, for use in Kiss::ExceptionReport.
|
418
|
-
def exception_cache
|
419
|
-
@@exception_cache
|
420
|
-
end
|
421
391
|
|
422
392
|
# Given a file path, caches or returns the file's contents or the return value of
|
423
393
|
# the passed block applied to the file's contents.
|
@@ -449,39 +419,6 @@ class Kiss
|
|
449
419
|
(block_given?) ? yield(contents) : contents
|
450
420
|
end
|
451
421
|
end
|
452
|
-
|
453
|
-
# Returns Sequel dataset to evolution_number table, which specifies app's current evolution number.
|
454
|
-
# Creates evolution_number table if it does not exist.
|
455
|
-
def evolution_number_table
|
456
|
-
unless db.table_exists?(:evolution_number)
|
457
|
-
db.create_table :evolution_number do
|
458
|
-
column :version, :integer, :null=> false
|
459
|
-
end
|
460
|
-
db[:evolution_number].insert(:version => 0)
|
461
|
-
end
|
462
|
-
db[:evolution_number]
|
463
|
-
end
|
464
|
-
|
465
|
-
# Returns app's current evolution number.
|
466
|
-
def evolution_number
|
467
|
-
evolution_number_table.first.version
|
468
|
-
end
|
469
|
-
|
470
|
-
# Sets app's current evolution number.
|
471
|
-
def evolution_number=(version)
|
472
|
-
load unless @@options
|
473
|
-
evolution_number_table.update(:version => version)
|
474
|
-
end
|
475
|
-
|
476
|
-
# Check whether there exists a file in evolution_dir whose number is greater than app's
|
477
|
-
# current evolution number. If so, raise an error to indicate need to apply new evolutions.
|
478
|
-
def check_evolution_number
|
479
|
-
version = evolution_number
|
480
|
-
if Kiss.directory_exists?(@@evolution_dir) &&
|
481
|
-
Dir.entries(@@evolution_dir).select { |f| f =~ /\A0*#{version+1}_/ }.size > 0
|
482
|
-
raise "current evolution #{version} is outdated; apply evolutions or update evolution number"
|
483
|
-
end
|
484
|
-
end
|
485
422
|
end # end class methods
|
486
423
|
|
487
424
|
### Instance Methods
|
@@ -531,16 +468,17 @@ class Kiss
|
|
531
468
|
env['kiss.parsed_action'] = @action
|
532
469
|
env['kiss.parsed_args'] = @args.inspect
|
533
470
|
|
534
|
-
|
471
|
+
redirect_url(app_url + '/') if @action == '/login'
|
472
|
+
|
535
473
|
if login_session_valid?
|
536
474
|
load_from_login_session
|
537
475
|
elsif @@options[:authenticate_all]
|
538
|
-
if (!@@
|
539
|
-
@@
|
476
|
+
if (!@@authenticate_exclude.is_a?(Array) ||
|
477
|
+
@@authenticate_exclude.select {|action| action == @action}.size == 0)
|
540
478
|
authenticate
|
541
479
|
end
|
542
480
|
end
|
543
|
-
|
481
|
+
|
544
482
|
env['kiss.processed_action'] = @action
|
545
483
|
process.render
|
546
484
|
end
|
@@ -548,7 +486,7 @@ class Kiss
|
|
548
486
|
|
549
487
|
@response.finish
|
550
488
|
rescue StandardError, LoadError, SyntaxError => e
|
551
|
-
body = Kiss::ExceptionReport.generate(e, env, @exception_cache, @
|
489
|
+
body = Kiss::ExceptionReport.generate(e, env, @exception_cache, @db ? @db.last_query : nil)
|
552
490
|
if @@exception_log_file
|
553
491
|
@@exception_log_file.print(body + "\n--- End of exception report --- \n\n")
|
554
492
|
end
|
@@ -573,6 +511,8 @@ class Kiss
|
|
573
511
|
headers['Content-Length'] = body.length.to_s
|
574
512
|
end
|
575
513
|
|
514
|
+
@@database_pool.push(@db) if @db
|
515
|
+
|
576
516
|
[code,headers,body]
|
577
517
|
end
|
578
518
|
|
@@ -622,27 +562,37 @@ class Kiss
|
|
622
562
|
suffix ? @app_url + suffix : @app_url
|
623
563
|
end
|
624
564
|
|
625
|
-
#
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
565
|
+
# Returns Sequel dataset to evolution_number table, which specifies app's current evolution number.
|
566
|
+
# Creates evolution_number table if it does not exist.
|
567
|
+
def evolution_number_table
|
568
|
+
unless db.table_exists?(:evolution_number)
|
569
|
+
db.create_table :evolution_number do
|
570
|
+
column :version, :integer, :null=> false
|
571
|
+
end
|
572
|
+
db[:evolution_number].insert(:version => 0)
|
573
|
+
end
|
574
|
+
db[:evolution_number]
|
575
|
+
end
|
576
|
+
|
577
|
+
# Returns app's current evolution number.
|
578
|
+
def evolution_number
|
579
|
+
evolution_number_table.first.version
|
580
|
+
end
|
581
|
+
|
582
|
+
# Sets app's current evolution number.
|
583
|
+
def evolution_number=(version)
|
584
|
+
load unless @@options
|
585
|
+
evolution_number_table.update(:version => version)
|
586
|
+
end
|
587
|
+
|
588
|
+
# Check whether there exists a file in evolution_dir whose number is greater than app's
|
589
|
+
# current evolution number. If so, raise an error to indicate need to apply new evolutions.
|
590
|
+
def check_evolution_number
|
591
|
+
version = evolution_number
|
592
|
+
if Kiss.directory_exists?(@@evolution_dir) &&
|
593
|
+
Dir.entries(@@evolution_dir).select { |f| f =~ /\A0*#{version+1}_/ }.size > 0
|
594
|
+
raise "current evolution #{version} is outdated; apply evolutions or update evolution number"
|
595
|
+
end
|
646
596
|
end
|
647
597
|
|
648
598
|
# Saves session to session store, if session data has changed since load.
|
@@ -652,21 +602,62 @@ class Kiss
|
|
652
602
|
|
653
603
|
##### LOGIN SESSION #####
|
654
604
|
|
655
|
-
|
656
|
-
|
657
|
-
|
605
|
+
def session
|
606
|
+
@session ||= begin
|
607
|
+
@@session_class ? begin
|
608
|
+
@@session_setup ||= begin
|
609
|
+
# setup session storage
|
610
|
+
@@session_class.setup_storage(self)
|
611
|
+
true
|
612
|
+
end
|
613
|
+
|
614
|
+
session = @@session_class.persist(self,@request.cookies[@@cookie_name])
|
615
|
+
@session_fingerprint = Marshal.dump(session.data).hash
|
616
|
+
|
617
|
+
cookie_vars = {
|
618
|
+
:value => session.values[:session_id],
|
619
|
+
:path => @@options[:cookie_path] || @app_uri,
|
620
|
+
:domain => @@options[:cookie_domain] || @request.host
|
621
|
+
}
|
622
|
+
cookie_vars[:expires] = Time.now + @@options[:cookie_lifespan] if @@options[:cookie_lifespan]
|
623
|
+
|
624
|
+
# set_cookie here or at render time
|
625
|
+
@response.set_cookie @@cookie_name, cookie_vars
|
626
|
+
|
627
|
+
session
|
628
|
+
end : {}
|
629
|
+
end
|
658
630
|
end
|
659
|
-
|
631
|
+
|
632
|
+
def login
|
633
|
+
@login ||= begin
|
634
|
+
login = {}
|
635
|
+
|
636
|
+
login.merge!(session[:login]) if (session[:login] && session[:login][:expires_at] &&
|
637
|
+
session[:login][:expires_at] > Time.now)
|
638
|
+
|
639
|
+
login
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
# Deletes login data from session.
|
644
|
+
def logout
|
645
|
+
session.delete(:login)
|
646
|
+
@login = nil
|
647
|
+
end
|
648
|
+
alias_method :reset_login_session, :logout
|
649
|
+
alias_method :reset_login_data, :logout
|
660
650
|
|
661
651
|
# Merges data hash (key-value pairs) into request login hash.
|
662
652
|
def set_login_data(data)
|
663
|
-
|
653
|
+
login.merge!(data)
|
654
|
+
login
|
664
655
|
end
|
665
656
|
|
666
657
|
# Merges data hash (key-value pairs) into session login hash.
|
667
658
|
def set_login_session(data)
|
668
659
|
set_login_data(data)
|
669
|
-
|
660
|
+
session[:login] = (session[:login] || {}).merge(data)
|
670
661
|
end
|
671
662
|
|
672
663
|
# Sets expire time of session login hash, after which time it will be reset (emptied).
|
@@ -678,12 +669,12 @@ class Kiss
|
|
678
669
|
|
679
670
|
# Returns true if login hash is defined and not expired.
|
680
671
|
def login_session_valid?
|
681
|
-
|
672
|
+
login && !login_session_expired?
|
682
673
|
end
|
683
674
|
|
684
675
|
# Returns true if login hash is expired.
|
685
676
|
def login_session_expired?
|
686
|
-
|
677
|
+
login && (!login[:expires_at] || login[:expires_at] < Time.now)
|
687
678
|
end
|
688
679
|
|
689
680
|
# Calls login action's load_from_session method to populate request login hash.
|
@@ -708,10 +699,13 @@ class Kiss
|
|
708
699
|
else
|
709
700
|
klass = action_class('/login')
|
710
701
|
raise 'authenticate called, but no login action found' unless klass
|
711
|
-
|
712
|
-
|
702
|
+
|
703
|
+
old_template = @template
|
704
|
+
@template = '/login.rhtml'
|
705
|
+
|
713
706
|
process(klass,login_path)
|
714
|
-
|
707
|
+
|
708
|
+
@template = old_template
|
715
709
|
|
716
710
|
unless login_session_valid?
|
717
711
|
#raise 'login action completed without setting valid login session'
|
@@ -825,19 +819,69 @@ class Kiss
|
|
825
819
|
mailer
|
826
820
|
end
|
827
821
|
|
822
|
+
def db
|
823
|
+
@db ||= @@database_pool.shift || begin
|
824
|
+
raise 'database config missing' unless @@database_config
|
825
|
+
|
826
|
+
# open database connection (if not already open)
|
827
|
+
@db = @@database_config.is_a?(String) ? (Sequel.open @@database_config) :
|
828
|
+
@@database_config.is_a?(Hash) ? (Sequel.open @@database_config) : @@database_config
|
829
|
+
|
830
|
+
@@db_extras_loaded ||= begin
|
831
|
+
@db.class.class_eval do
|
832
|
+
@last_query = nil
|
833
|
+
def last_query
|
834
|
+
@last_query
|
835
|
+
end
|
836
|
+
|
837
|
+
alias_method :execute_old, :execute
|
838
|
+
def execute(sql, *args, &block)
|
839
|
+
@last_query = sql
|
840
|
+
execute_old(sql, *args, &block)
|
841
|
+
end
|
842
|
+
end
|
843
|
+
|
844
|
+
require 'kiss/model'
|
845
|
+
Kiss::ModelCache.model_dir = @@model_dir
|
846
|
+
|
847
|
+
if @db.class.name == 'Sequel::MySQL::Database'
|
848
|
+
# add fetch_arrays, all_arrays methods
|
849
|
+
require 'kiss/sequel_mysql'
|
850
|
+
# turn off convert_tinyint_to_bool, unless options say otherwise
|
851
|
+
Sequel.convert_tinyint_to_bool = false unless @@options[:convert_tinyint_to_bool]
|
852
|
+
end
|
853
|
+
true
|
854
|
+
end
|
855
|
+
|
856
|
+
# TODO: rewrite evolution file exists check for speed
|
857
|
+
check_evolution_number
|
858
|
+
|
859
|
+
@db
|
860
|
+
end
|
861
|
+
end
|
862
|
+
|
828
863
|
# Kiss Model cache, used to invoke and store Kiss database models.
|
829
864
|
#
|
830
865
|
# Example:
|
831
866
|
# models[:users] : database model for `users' table
|
832
867
|
def dbm
|
868
|
+
db unless @db
|
833
869
|
@dbm ||= Kiss::ModelCache.new(self)
|
834
870
|
end
|
835
871
|
alias_method :models, :dbm
|
836
872
|
|
873
|
+
def random_text(*args)
|
874
|
+
self.class.random_text(*args)
|
875
|
+
end
|
876
|
+
|
837
877
|
def h(*args)
|
838
878
|
self.class.h(*args)
|
839
879
|
end
|
840
880
|
|
881
|
+
def template
|
882
|
+
@template || @action
|
883
|
+
end
|
884
|
+
|
841
885
|
# Adds data to be displayed in "Cache" section of Kiss exception reports.
|
842
886
|
def set_exception_cache(data)
|
843
887
|
@exception_cache.merge!(data)
|
data/lib/kiss/action.rb
CHANGED
@@ -114,9 +114,9 @@ class Kiss
|
|
114
114
|
@base_url ||= app(action_subdir + '/')
|
115
115
|
@layout = options.is_a?(Hash) && options.has_key?(:layout) ? options[:layout] :
|
116
116
|
(extension == 'rhtml' ? Kiss.layout : nil)
|
117
|
-
|
117
|
+
|
118
118
|
content = options[:content].is_a?(String) ? options[:content] : process({
|
119
|
-
:template =>
|
119
|
+
:template => template,
|
120
120
|
:extension => extension
|
121
121
|
}.merge(options))
|
122
122
|
|
@@ -3,11 +3,6 @@ class Kiss
|
|
3
3
|
def environment
|
4
4
|
Kiss.environment
|
5
5
|
end
|
6
|
-
|
7
|
-
def db
|
8
|
-
Kiss.db
|
9
|
-
end
|
10
|
-
alias_method :database, :db
|
11
6
|
|
12
7
|
def upload_dir
|
13
8
|
Kiss.upload_dir
|
@@ -27,6 +22,11 @@ class Kiss
|
|
27
22
|
controller.bench(label, Kernel.caller[0])
|
28
23
|
end
|
29
24
|
|
25
|
+
def db
|
26
|
+
controller.db
|
27
|
+
end
|
28
|
+
alias_method :database, :db
|
29
|
+
|
30
30
|
def dbm
|
31
31
|
controller.dbm
|
32
32
|
end
|
@@ -67,6 +67,10 @@ class Kiss
|
|
67
67
|
def set_login_session(*args)
|
68
68
|
controller.set_login_session(*args)
|
69
69
|
end
|
70
|
+
|
71
|
+
def logout
|
72
|
+
controller.logout
|
73
|
+
end
|
70
74
|
|
71
75
|
def reset_login_data
|
72
76
|
controller.reset_login_data
|
@@ -92,6 +96,10 @@ class Kiss
|
|
92
96
|
controller.action
|
93
97
|
end
|
94
98
|
|
99
|
+
def template
|
100
|
+
controller.template
|
101
|
+
end
|
102
|
+
|
95
103
|
def action_subdir
|
96
104
|
controller.action_subdir
|
97
105
|
end
|
@@ -90,6 +90,7 @@ class Kiss
|
|
90
90
|
h2 span { font-size:80%; color:#000; font-weight:normal; }
|
91
91
|
h3 { margin:1em 0 .5em 0; }
|
92
92
|
h4 { margin:0 0 .5em 0; font-weight: normal; }
|
93
|
+
small { color #444; }
|
93
94
|
table {
|
94
95
|
border:1px solid #ccc; border-collapse: collapse; background:white; }
|
95
96
|
tbody td, tbody th { vertical-align:top; padding:2px 3px; }
|
data/lib/kiss/hacks.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
# Placeholder; to be overloaded by Kiss Rack builder option MultiBench
|
5
5
|
# (not yet implemented).
|
6
|
-
def multibench(*args); end
|
6
|
+
# def multibench(*args); end
|
7
7
|
|
8
8
|
# This gets called outside of controller contexts; used mainly for debugging
|
9
9
|
# during Kiss framework development.
|
@@ -72,19 +72,6 @@ class Fixnum
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
class BigDecimal
|
76
|
-
# Formats number with comma-separated thousands.
|
77
|
-
def format_thousands(value = to_f.to_s)
|
78
|
-
integer, decimal = value.split(/\./,2)
|
79
|
-
integer.reverse.gsub(/(\d{3})/,'\1,').sub(/\,(-?)$/,'\1').reverse + '.' + decimal
|
80
|
-
end
|
81
|
-
|
82
|
-
# Formats number to two decimal places.
|
83
|
-
def format_currency
|
84
|
-
format_thousands(sprintf("%0.2f",to_f))
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
75
|
class Date
|
89
76
|
# Returns string representing date in m/d/yyyy format
|
90
77
|
def mdy
|
@@ -110,6 +97,44 @@ class NilClass
|
|
110
97
|
end
|
111
98
|
end
|
112
99
|
|
100
|
+
class String
|
101
|
+
def to_const
|
102
|
+
begin
|
103
|
+
parts = self.split(/::/)
|
104
|
+
klass = Kernel
|
105
|
+
while (next_part = parts.shift)
|
106
|
+
klass = klass.const_get(next_part)
|
107
|
+
end
|
108
|
+
|
109
|
+
klass
|
110
|
+
rescue
|
111
|
+
raise "Constant '#{self}' not defined"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class Symbol
|
117
|
+
def to_const
|
118
|
+
self.to_s.to_const
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
module Rack
|
123
|
+
class Request
|
124
|
+
def server
|
125
|
+
url = scheme + "://"
|
126
|
+
url << host
|
127
|
+
|
128
|
+
if scheme == "https" && port != 443 ||
|
129
|
+
scheme == "http" && port != 80
|
130
|
+
url << ":#{port}"
|
131
|
+
end
|
132
|
+
|
133
|
+
url
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
113
138
|
class SequelZeroTime < String
|
114
139
|
def initialize(value = '0000-00-00 00:00',*args,&block)
|
115
140
|
super(value,*args,&block)
|
@@ -157,95 +182,3 @@ class SequelZeroTime < String
|
|
157
182
|
''
|
158
183
|
end
|
159
184
|
end
|
160
|
-
|
161
|
-
class Date
|
162
|
-
class << self
|
163
|
-
alias_method :old_parse, :parse
|
164
|
-
def parse(*args, &block)
|
165
|
-
return SequelZeroTime.new(args[0]) if args[0] =~ /0000/
|
166
|
-
old_parse(*args, &block)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
# comparision operators
|
171
|
-
def ==(value)
|
172
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
173
|
-
end
|
174
|
-
def >(value)
|
175
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? true : super(value)
|
176
|
-
end
|
177
|
-
def >=(value)
|
178
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? true : super(value)
|
179
|
-
end
|
180
|
-
def <(value)
|
181
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
182
|
-
end
|
183
|
-
def <=(value)
|
184
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
class Time
|
189
|
-
class << self
|
190
|
-
alias_method :old_parse, :parse
|
191
|
-
def parse(*args, &block)
|
192
|
-
return SequelZeroTime.new(args[0]) if args[0] =~ /0000/
|
193
|
-
old_parse(*args, &block)
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
# comparision operators
|
198
|
-
def ==(value)
|
199
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
200
|
-
end
|
201
|
-
def >(value)
|
202
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? true : super(value)
|
203
|
-
end
|
204
|
-
def >=(value)
|
205
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? true : super(value)
|
206
|
-
end
|
207
|
-
def <(value)
|
208
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
209
|
-
end
|
210
|
-
def <=(value)
|
211
|
-
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
class String
|
216
|
-
def to_const
|
217
|
-
begin
|
218
|
-
parts = self.split(/::/)
|
219
|
-
klass = Kernel
|
220
|
-
while (next_part = parts.shift)
|
221
|
-
klass = klass.const_get(next_part)
|
222
|
-
end
|
223
|
-
|
224
|
-
klass
|
225
|
-
rescue
|
226
|
-
raise "Constant '#{self}' not defined"
|
227
|
-
end
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
class Symbol
|
232
|
-
def to_const
|
233
|
-
self.to_s.to_const
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
module Rack
|
238
|
-
class Request
|
239
|
-
def server
|
240
|
-
url = scheme + "://"
|
241
|
-
url << host
|
242
|
-
|
243
|
-
if scheme == "https" && port != 443 ||
|
244
|
-
scheme == "http" && port != 80
|
245
|
-
url << ":#{port}"
|
246
|
-
end
|
247
|
-
|
248
|
-
url
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
data/lib/kiss/model.rb
CHANGED
@@ -76,8 +76,7 @@ class Kiss
|
|
76
76
|
|
77
77
|
def [](source)
|
78
78
|
@cache[source] ||= begin
|
79
|
-
dataset =
|
80
|
-
dataset.controller = @controller
|
79
|
+
dataset = @controller.db[source]
|
81
80
|
(@@model_dir && source.is_a?(Symbol)) ? begin
|
82
81
|
# use file_cache
|
83
82
|
model_path = "#{@@model_dir}/#{source}.rb"
|
@@ -101,7 +100,7 @@ class Kiss
|
|
101
100
|
end
|
102
101
|
|
103
102
|
def db
|
104
|
-
|
103
|
+
@controller.db
|
105
104
|
end
|
106
105
|
|
107
106
|
def literal(*args)
|
@@ -132,15 +131,69 @@ class Sequel::Model
|
|
132
131
|
end
|
133
132
|
end
|
134
133
|
|
135
|
-
class
|
136
|
-
|
137
|
-
|
134
|
+
class Date
|
135
|
+
class << self
|
136
|
+
alias_method :old_parse, :parse
|
137
|
+
def parse(*args, &block)
|
138
|
+
return SequelZeroTime.new(args[0]) if args[0] =~ /0000/
|
139
|
+
old_parse(*args, &block)
|
140
|
+
end
|
138
141
|
end
|
139
142
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
+
# comparision operators
|
144
|
+
def ==(value)
|
145
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
146
|
+
end
|
147
|
+
def >(value)
|
148
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? true : super(value)
|
149
|
+
end
|
150
|
+
def >=(value)
|
151
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? true : super(value)
|
152
|
+
end
|
153
|
+
def <(value)
|
154
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
155
|
+
end
|
156
|
+
def <=(value)
|
157
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class Time
|
162
|
+
class << self
|
163
|
+
alias_method :old_parse, :parse
|
164
|
+
def parse(*args, &block)
|
165
|
+
return SequelZeroTime.new(args[0]) if args[0] =~ /0000/
|
166
|
+
old_parse(*args, &block)
|
143
167
|
end
|
144
|
-
|
168
|
+
end
|
169
|
+
|
170
|
+
# comparision operators
|
171
|
+
def ==(value)
|
172
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
173
|
+
end
|
174
|
+
def >(value)
|
175
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? true : super(value)
|
176
|
+
end
|
177
|
+
def >=(value)
|
178
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? true : super(value)
|
179
|
+
end
|
180
|
+
def <(value)
|
181
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
182
|
+
end
|
183
|
+
def <=(value)
|
184
|
+
(value == 0 || value.is_a?(SequelZeroTime)) ? false : super(value)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class BigDecimal
|
189
|
+
# Formats number with comma-separated thousands.
|
190
|
+
def format_thousands(value = to_f.to_s)
|
191
|
+
integer, decimal = value.split(/\./,2)
|
192
|
+
integer.reverse.gsub(/(\d{3})/,'\1,').sub(/\,(-?)$/,'\1').reverse + '.' + decimal
|
193
|
+
end
|
194
|
+
|
195
|
+
# Formats number to two decimal places.
|
196
|
+
def format_currency
|
197
|
+
format_thousands(sprintf("%0.2f",to_f))
|
145
198
|
end
|
146
199
|
end
|
data/lib/kiss/sequel_session.rb
CHANGED
@@ -53,8 +53,8 @@ class Kiss
|
|
53
53
|
end
|
54
54
|
|
55
55
|
# Generates a new session ID and creates a row for the new session in the database.
|
56
|
-
def generate
|
57
|
-
new(Sequel::Model(:sessions).create(
|
56
|
+
def generate(controller)
|
57
|
+
new(Sequel::Model(controller.db[:sessions]).create(
|
58
58
|
:session_id => rand_uuid,
|
59
59
|
:data => marshal({}),
|
60
60
|
:created_at => Time.now,
|
@@ -64,14 +64,14 @@ class Kiss
|
|
64
64
|
|
65
65
|
# Gets the existing session based on the <tt>session_id</tt> available in cookies.
|
66
66
|
# If none is found, generates a new session.
|
67
|
-
def persist(session_id)
|
67
|
+
def persist(controller, session_id)
|
68
68
|
if session_id
|
69
|
-
if object = Sequel::Model(:sessions).where(:session_id => session_id).first
|
69
|
+
if object = Sequel::Model(controller.db[:sessions]).where(:session_id => session_id).first
|
70
70
|
session = new( object )
|
71
71
|
end
|
72
72
|
end
|
73
73
|
unless session
|
74
|
-
session = generate
|
74
|
+
session = generate( controller.db )
|
75
75
|
end
|
76
76
|
session
|
77
77
|
end
|
@@ -66,7 +66,15 @@ class Kiss
|
|
66
66
|
def get_template_path(options)
|
67
67
|
@current_template_dir ||= @template_dir + action_subdir
|
68
68
|
|
69
|
-
|
69
|
+
if options.is_a?(String)
|
70
|
+
path = options
|
71
|
+
extension = nil
|
72
|
+
else
|
73
|
+
path = options[:template]
|
74
|
+
extension = options[:extension]
|
75
|
+
end
|
76
|
+
|
77
|
+
path += ".#{extension || 'rhtml'}" unless path =~ /\./
|
70
78
|
(path =~ /\A\//) ? "#{@template_dir}#{path}" : "#{@current_template_dir}/#{path}"
|
71
79
|
end
|
72
80
|
|
@@ -85,12 +93,12 @@ class Kiss
|
|
85
93
|
# macros
|
86
94
|
template.gsub!(/\<\%\s*macro\s+(\w+.*?)\s*\%\>/,'<% def \1; _buf = \'\' %>')
|
87
95
|
template.gsub!(/\<\%\s*end\s+macro\s*\%\>/,'<% _buf; end %>')
|
88
|
-
|
96
|
+
|
97
|
+
# generic loop iterator, using 'iterate'
|
98
|
+
template.gsub!(/\<\%\s*iterate\s+(\w+)\s+(.*?)\s*\%\>/,"<% \\1 = Kiss::Iterator.new; \\2; \\1.increment %>")
|
89
99
|
# for loop iterator
|
90
|
-
template.gsub!(/\<\%\s*for\s+(\w+)\s+in\s+(.*?)\s*\%\>/,
|
91
|
-
|
92
|
-
template.gsub!(/\<\%\s*while\s+(.*?)\s*\%\>/,'<% loop = Kiss::Iterator.new; while \1; loop.increment %>')
|
93
|
-
|
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 %>")
|
101
|
+
|
94
102
|
Erubis::Eruby.new(template).src
|
95
103
|
end
|
96
104
|
result = eval eruby_src, template_binding, path
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kiss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shawn Van Ittersum
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-10-05 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|