alfa 0.0.5.pre → 0.0.6.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/dummy/project/.gitignore +16 -0
- data/dummy/project/.ruby-version +1 -0
- data/dummy/project/CHANGELOG +0 -0
- data/dummy/project/Gemfile.source +7 -2
- data/dummy/project/README +0 -0
- data/dummy/project/apps/admin/layouts/base.haml +10 -0
- data/dummy/project/apps/admin/layouts/index.haml.source +7 -0
- data/dummy/project/apps/admin/templates/default/index.haml +1 -0
- data/dummy/project/apps/frontend/layouts/base.haml +10 -0
- data/dummy/project/apps/frontend/layouts/index.haml.source +7 -0
- data/dummy/project/apps/frontend/templates/default/{index.tpl → index.haml} +0 -0
- data/dummy/project/config/db.rb +15 -0
- data/dummy/project/config/passwords/.gitignore.source +3 -0
- data/dummy/project/config/passwords/db-main.yml.source +8 -0
- data/dummy/project/config/passwords/secrets.sample.yml +2 -0
- data/dummy/project/config/passwords/secrets.yml.source +2 -0
- data/dummy/project/config/web_application.rb +1 -0
- data/dummy/project/db/main/migrations/.keep +0 -0
- data/dummy/project/db/main/models/.keep +0 -0
- data/dummy/project/db/main/schema/.keep +0 -0
- data/dummy/project/db/main/seed.rb +0 -0
- data/dummy/project/log/.keep +0 -0
- data/dummy/project/public/.htaccess +13 -0
- data/dummy/project/tasks/.keep +0 -0
- data/dummy/project/test/.keep +0 -0
- data/lib/alfa/application.rb +21 -1
- data/lib/alfa/commands/new.rb +14 -9
- data/lib/alfa/config.rb +3 -2
- data/lib/alfa/controller.rb +19 -104
- data/lib/alfa/database.rb +2 -1
- data/lib/alfa/exceptions.rb +5 -0
- data/lib/alfa/logger.rb +4 -3
- data/lib/alfa/resourcer.rb +29 -0
- data/lib/alfa/router.rb +34 -14
- data/lib/alfa/snippeter.rb +42 -0
- data/lib/alfa/support/common.rb +195 -0
- data/lib/alfa/support/nil_operations.rb +207 -0
- data/lib/alfa/support/time.rb +5 -0
- data/lib/alfa/support.rb +3 -135
- data/lib/alfa/tasks/assets.rake +16 -0
- data/lib/alfa/tasks/db.rake +169 -0
- data/lib/alfa/tasks/generators.rake +80 -0
- data/lib/alfa/tasks.rb +4 -0
- data/lib/alfa/tfile.rb +1 -1
- data/lib/alfa/user.rb +41 -6
- data/lib/alfa/web_application.rb +96 -31
- data/lib/alfa/wrapper.rb +155 -0
- data/lib/alfa.rb +0 -2
- data/lib/rack/file_alfa.rb +2 -1
- data/lib/sequel/extensions/igrep.rb +19 -0
- data/lib/sequel/extensions/with_pks.rb +15 -0
- data/lib/template-inheritance/alfa_helpers.rb +106 -25
- data/lib/tilt/alfa_patch.rb +1 -1
- data/test/data/test_router/1/apps/frontend/routes.rb +1 -0
- data/test/data/test_router/2/apps/frontend/routes.rb +1 -0
- data/test/data/test_web_application/apps/admin/controllers/second.rb +5 -0
- data/test/data/test_web_application/apps/admin/layouts/default.haml +1 -0
- data/test/data/test_web_application/apps/admin/layouts/default.tpl +1 -0
- data/test/data/test_web_application/apps/admin/routes.rb +1 -0
- data/test/data/test_web_application/apps/admin/templates/default/test_04.haml +1 -0
- data/test/data/test_web_application/apps/admin/templates/default/test_04.tpl +1 -0
- data/test/data/test_web_application/apps/admin/templates/default/test_08.haml +2 -0
- data/test/data/test_web_application/apps/admin/templates/default/test_08a.haml +1 -0
- data/test/data/test_web_application/apps/admin/templates/second/index.haml +1 -0
- data/test/data/test_web_application/apps/frontend/controllers/second.rb +5 -0
- data/test/data/test_web_application/apps/frontend/layouts/default.haml +1 -0
- data/test/data/test_web_application/apps/frontend/layouts/default.tpl +1 -0
- data/test/data/test_web_application/apps/frontend/routes.rb +1 -0
- data/test/data/test_web_application/apps/frontend/templates/default/bar.haml +0 -0
- data/test/data/test_web_application/apps/frontend/templates/default/bar.tpl +0 -0
- data/test/data/test_web_application/apps/frontend/templates/default/frontend_only.haml +0 -0
- data/test/data/test_web_application/apps/frontend/templates/default/frontend_only.tpl +0 -0
- data/test/data/test_web_application/apps/frontend/templates/default/index.haml +0 -0
- data/test/data/test_web_application/apps/frontend/templates/default/index.tpl +0 -0
- data/test/data/test_web_application/apps/frontend/templates/default/test_04.haml +1 -0
- data/test/data/test_web_application/apps/frontend/templates/default/test_04.tpl +1 -0
- data/test/data/test_web_application/apps/frontend/templates/default/test_08.haml +2 -0
- data/test/data/test_web_application/apps/frontend/templates/default/test_08a.haml +1 -0
- data/test/data/test_web_application/apps/frontend/templates/second/index.haml +1 -0
- data/test/test_config.rb +2 -2
- data/test/test_controller.rb +13 -3
- data/test/test_router.rb +13 -6
- data/test/test_ruby_core.rb +32 -0
- data/test/test_support.rb +152 -11
- data/test/test_web_application.rb +7 -0
- data/version.rb +1 -1
- metadata +100 -16
- data/lib/alfa/database/mysql.rb +0 -107
- data/lib/alfa/models/base.rb +0 -7
- data/lib/alfa/models/base_sql.rb +0 -9
- data/lib/alfa/models/dummy.rb +0 -7
- data/lib/alfa/models/mysql.rb +0 -62
- data/lib/alfa/models.rb +0 -2
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'sequel/extensions/migration'
|
2
|
+
require 'alfa/logger'
|
3
|
+
|
4
|
+
# All maintainable databases
|
5
|
+
def dbs
|
6
|
+
Alfa::VARS[:rakeapp_instance].instance_eval do
|
7
|
+
config[:db].select{|name, db| db[:maintain]}
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :db do
|
12
|
+
# Auxiliary task
|
13
|
+
# Check is database name given, if not given - exit with error message
|
14
|
+
task :require_db do
|
15
|
+
unless ENV['db']
|
16
|
+
puts "Please specify database such as: db=database"
|
17
|
+
puts "Known maintainable databases: " << dbs.map{|name, db| name}.join(', ')
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
@db_name = ENV['db'].to_sym
|
21
|
+
@db = dbs[@db_name]
|
22
|
+
unless @db
|
23
|
+
puts "Unknown database \"#{ENV['db']}\". Known maintainable databases: " << dbs.map{|name, db| name}.join(', ')
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Auxiliary task
|
29
|
+
# Set @db if database name given
|
30
|
+
task :optional_db do
|
31
|
+
@db = nil
|
32
|
+
@db_name = nil
|
33
|
+
if ENV['db']
|
34
|
+
@db_name = ENV['db'].to_sym
|
35
|
+
@db = dbs[@db_name]
|
36
|
+
unless @db
|
37
|
+
puts "Unknown database. Known maintainable databases: " << dbs.map{|name, db| name}.join(', ')
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Auxiliary task
|
44
|
+
# Set logger($stdout) for all databases
|
45
|
+
task :stdout_logger do
|
46
|
+
@stdout_logger ||= Alfa::Logger.new($stdout)
|
47
|
+
dbs.each_value do |db|
|
48
|
+
db[:instance].loggers << @stdout_logger
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Drop all tables in schema"
|
53
|
+
task :drop => [:require_db, :stdout_logger] do
|
54
|
+
@db[:instance].tables.each do |table|
|
55
|
+
@db[:instance].foreign_key_list(table).each do |key|
|
56
|
+
@db[:instance].alter_table table do
|
57
|
+
drop_foreign_key(key[:columns])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
@db[:instance].drop_table(*@db[:instance].tables)
|
62
|
+
end
|
63
|
+
|
64
|
+
desc "Create dumb migration for certain database and puts them into PROJECT_ROOT/db/%database%/migration"
|
65
|
+
task :'new-migration' => [:require_db, :stdout_logger] do
|
66
|
+
unless @db[:path]
|
67
|
+
puts "Error: not specified path for database #{@db_name}"
|
68
|
+
exit
|
69
|
+
end
|
70
|
+
ts = Time.now.utc.strftime('%Y%m%d%H%M%S')
|
71
|
+
pattern = <<EOL
|
72
|
+
# Migration #{ts}
|
73
|
+
# Don't rename this file after implement migration
|
74
|
+
|
75
|
+
Sequel.migration do
|
76
|
+
up do
|
77
|
+
# Put up migration code here
|
78
|
+
# Use Sequel migration syntax (http://sequel.jeremyevans.net/rdoc/files/doc/schema_modification_rdoc.html) or native SQL (run "SQL command")
|
79
|
+
end
|
80
|
+
|
81
|
+
down do
|
82
|
+
# Put down migration code here
|
83
|
+
end
|
84
|
+
end
|
85
|
+
EOL
|
86
|
+
filename = "#{ts}_m.rb"
|
87
|
+
migration_file = File.join(@db[:path], 'migrations', filename)
|
88
|
+
if File.exist?(migration_file)
|
89
|
+
puts "Error: file #{migration_file} already exists, exiting"
|
90
|
+
exit
|
91
|
+
end
|
92
|
+
|
93
|
+
File.open(migration_file, 'w') do |f|
|
94
|
+
f.write pattern
|
95
|
+
puts "Create migration #{migration_file}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
desc "Migrate database(s)"
|
100
|
+
task :migrate => [:optional_db, :stdout_logger] do
|
101
|
+
if @db
|
102
|
+
Sequel::Migrator.run(@db[:instance], File.join(@db[:path], 'migrations'))
|
103
|
+
else
|
104
|
+
dbs.each do |name, db|
|
105
|
+
Sequel::Migrator.run(db[:instance], File.join(db[:path], 'migrations'))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
namespace :migrate do
|
111
|
+
desc "Migrate database 1 step up"
|
112
|
+
task :up => [:require_db, :stdout_logger] do
|
113
|
+
migrator = Sequel::TimestampMigrator.new(@db[:instance], File.join(@db[:path], 'migrations'))
|
114
|
+
if migrator.migration_tuples
|
115
|
+
m = migrator.migration_tuples.first
|
116
|
+
if m[2] == :up
|
117
|
+
target = m[1].split('_').first.to_i
|
118
|
+
Sequel::Migrator.run(@db[:instance], File.join(@db[:path], 'migrations'), :target=>target)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
desc "Migrate database 1 step down"
|
124
|
+
task :down => [:require_db, :stdout_logger] do
|
125
|
+
migrator = Sequel::TimestampMigrator.new(@db[:instance], File.join(@db[:path], 'migrations'))
|
126
|
+
to_rollback = migrator.applied_migrations.last
|
127
|
+
if to_rollback
|
128
|
+
target = migrator.applied_migrations[0..-2].last # last but one applied migration
|
129
|
+
if target
|
130
|
+
target = target.split('_').first.to_i
|
131
|
+
else
|
132
|
+
target = 0
|
133
|
+
end
|
134
|
+
Sequel::Migrator.run(@db[:instance], File.join(@db[:path], 'migrations'), :target=>target)
|
135
|
+
else
|
136
|
+
puts "Nothing to rollback"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
desc "Test databases connection parameters"
|
142
|
+
task :test do
|
143
|
+
errors = 0
|
144
|
+
dbs.each do |name, db|
|
145
|
+
begin
|
146
|
+
db[:instance].test_connection
|
147
|
+
rescue Sequel::DatabaseConnectionError => e
|
148
|
+
errors = errors + 1
|
149
|
+
puts e.message
|
150
|
+
end
|
151
|
+
end
|
152
|
+
if errors > 0
|
153
|
+
puts "Some DSN problems found. Check config/passwords/db-*.yml"
|
154
|
+
else
|
155
|
+
puts "All DSNs are ok!"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
desc 'Seed chosen Database'
|
160
|
+
task :seed => [:optional_db, :stdout_logger] do
|
161
|
+
if @db
|
162
|
+
Kernel.load File.join(@db[:path], 'seed.rb')
|
163
|
+
else
|
164
|
+
dbs.each do |name, db|
|
165
|
+
Kernel.load File.join(db[:path], 'seed.rb')
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
namespace :+ do
|
2
|
+
|
3
|
+
task :require_model => [:'db:require_db'] do
|
4
|
+
unless ENV['model']
|
5
|
+
puts "Please specify model in single form such as: model=images"
|
6
|
+
exit
|
7
|
+
end
|
8
|
+
@model_name = ENV['model'].to_sym
|
9
|
+
if File.exist?(File.join(PROJECT_ROOT, 'db', @db_name.to_s, 'models', "#{@model_name.to_s}.rb"))
|
10
|
+
puts "Model #{@model_name} for db #{@db_name} already exists"
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Create model'
|
16
|
+
task :model => [:'db:require_db', :require_model] do
|
17
|
+
model_filename = Alfa::Support.underscore_name(@model_name)
|
18
|
+
model_classname = Alfa::Support.camelcase_name(@model_name)
|
19
|
+
db_classname = Alfa::Support.camelcase_name(@db_name)
|
20
|
+
ts = Time.now.utc.strftime('%Y%m%d%H%M%S')
|
21
|
+
pattern = <<EOL
|
22
|
+
# Migration #{ts} for model #{model_classname}
|
23
|
+
# Don't rename this file after implement migration
|
24
|
+
|
25
|
+
Sequel.migration do
|
26
|
+
up do
|
27
|
+
# Use Sequel migration syntax (http://sequel.jeremyevans.net/rdoc/files/doc/schema_modification_rdoc.html) or native SQL (run "SQL command")
|
28
|
+
create_table :#{model_filename}s do
|
29
|
+
primary_key :id
|
30
|
+
# ...
|
31
|
+
column :created_at, DateTime
|
32
|
+
column :updated_at, DateTime
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
down do
|
37
|
+
drop_table :#{model_filename}s
|
38
|
+
end
|
39
|
+
end
|
40
|
+
EOL
|
41
|
+
filename = "#{ts}_#{model_filename}s.rb"
|
42
|
+
migration_file = File.join(@db[:path], 'migrations', filename)
|
43
|
+
if File.exist?(migration_file)
|
44
|
+
puts "Error: file #{migration_file} already exists, exiting"
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
File.open(migration_file, 'w') do |f|
|
48
|
+
f.write pattern
|
49
|
+
puts "Create migration #{migration_file}"
|
50
|
+
end
|
51
|
+
|
52
|
+
pattern = <<EOL
|
53
|
+
class #{model_classname} < Sequel::Model(DB::#{db_classname}[:#{model_filename}s])
|
54
|
+
# Uncomment following plugins if necessary:
|
55
|
+
# plugin :timestamps, update_on_create: true
|
56
|
+
# plugin :prepared_statements
|
57
|
+
# plugin :serialization, %method%, %field%
|
58
|
+
# Read more about available plugins: http://sequel.jeremyevans.net/rdoc-plugins/classes/Sequel/Plugins.html
|
59
|
+
|
60
|
+
# Use associations:
|
61
|
+
# one_to_one :association_name, class: :OtherModel, key: :key_name
|
62
|
+
# one_to_many ...
|
63
|
+
# many_to_one ...
|
64
|
+
# many_to_many ...
|
65
|
+
# one_through_one ...
|
66
|
+
# Read more about association basics: http://sequel.jeremyevans.net/rdoc/files/doc/association_basics_rdoc.html
|
67
|
+
end
|
68
|
+
EOL
|
69
|
+
filename = "#{model_filename}.rb"
|
70
|
+
model_file = File.join(@db[:path], 'models', filename)
|
71
|
+
if File.exist?(model_file)
|
72
|
+
puts "Error: file #{model_file} already exists, exiting"
|
73
|
+
exit
|
74
|
+
end
|
75
|
+
File.open(model_file, 'w') do |f|
|
76
|
+
f.write pattern
|
77
|
+
puts "Create migration #{model_file}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/alfa/tasks.rb
CHANGED
data/lib/alfa/tfile.rb
CHANGED
data/lib/alfa/user.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'securerandom'
|
3
|
+
|
1
4
|
module Alfa
|
2
5
|
class << self
|
3
6
|
attr_accessor :GROUPS
|
@@ -27,16 +30,20 @@ module Alfa
|
|
27
30
|
def [](key)
|
28
31
|
nil
|
29
32
|
end
|
33
|
+
|
34
|
+
def method_missing(*o)
|
35
|
+
nil
|
36
|
+
end
|
30
37
|
end
|
31
38
|
|
39
|
+
|
32
40
|
class User
|
33
|
-
def initialize(
|
34
|
-
@
|
41
|
+
def initialize(object)
|
42
|
+
@object = object
|
35
43
|
end
|
36
44
|
|
37
45
|
def grants
|
38
|
-
|
39
|
-
@groups_p.map{|g| Alfa.GROUPS[g] || []}.flatten
|
46
|
+
(groups + [:public]).map{|g| Alfa.GROUPS[g] || []}.flatten
|
40
47
|
end
|
41
48
|
|
42
49
|
def grant?(name)
|
@@ -45,7 +52,7 @@ module Alfa
|
|
45
52
|
|
46
53
|
# @return Array
|
47
54
|
def groups
|
48
|
-
@groups
|
55
|
+
@object.groups.map{|s| s.to_s.strip.to_sym}
|
49
56
|
end
|
50
57
|
|
51
58
|
def group?(name)
|
@@ -57,7 +64,35 @@ module Alfa
|
|
57
64
|
end
|
58
65
|
|
59
66
|
def [](key)
|
60
|
-
@
|
67
|
+
@object[key]
|
68
|
+
end
|
69
|
+
|
70
|
+
def method_missing(*o)
|
71
|
+
@object.send(*o)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.method_missing(*o)
|
75
|
+
@object.class.send(*o)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Prepend this module in User model in your Project
|
80
|
+
# Example:
|
81
|
+
# class User < Sequel::Model(DB::Main[:users])
|
82
|
+
# prepend Alfa::UserModule
|
83
|
+
# end
|
84
|
+
module UserModule
|
85
|
+
def password=(p)
|
86
|
+
self.salt = SecureRandom.hex(5)
|
87
|
+
self.passhash = Digest::MD5.hexdigest("#{self.salt}#{p}")
|
88
|
+
end
|
89
|
+
|
90
|
+
def password_valid?(p)
|
91
|
+
self.passhash == Digest::MD5.hexdigest("#{self.salt}#{p}")
|
92
|
+
end
|
93
|
+
|
94
|
+
def groups=(g)
|
95
|
+
super(Array(g))
|
61
96
|
end
|
62
97
|
end
|
63
98
|
end
|
data/lib/alfa/web_application.rb
CHANGED
@@ -5,16 +5,17 @@ require 'alfa/tfile'
|
|
5
5
|
require 'alfa/controller'
|
6
6
|
require 'alfa/router'
|
7
7
|
require 'alfa/ruty'
|
8
|
-
require 'alfa/
|
8
|
+
require 'alfa/snippeter'
|
9
|
+
require 'alfa/wrapper'
|
10
|
+
require 'alfa/resourcer'
|
9
11
|
require 'rack/utils'
|
10
12
|
require 'rack/request'
|
11
13
|
require 'rack/file_alfa'
|
12
|
-
require 'digest/md5'
|
13
|
-
require 'securerandom'
|
14
14
|
require 'haml'
|
15
15
|
require 'alfa/template-inheritance'
|
16
16
|
require 'tilt/alfa_patch'
|
17
17
|
require 'haml/alfa_patch'
|
18
|
+
require 'json'
|
18
19
|
|
19
20
|
module Alfa
|
20
21
|
class WebApplication < Alfa::Application
|
@@ -32,6 +33,7 @@ module Alfa
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
36
|
+
# noinspection RubyResolve
|
35
37
|
def self.init!
|
36
38
|
super
|
37
39
|
Alfa::Router.reset
|
@@ -39,6 +41,9 @@ module Alfa
|
|
39
41
|
load File.join(@config[:project_root], 'config/routes.rb')
|
40
42
|
TemplateInheritance.logger = @logger
|
41
43
|
Alfa.GROUPS = @config[:groups]
|
44
|
+
Alfa::Snippeter.config = @config
|
45
|
+
Alfa::Snippeter.mounts = Alfa::Router.mounts
|
46
|
+
Alfa::Snippeter.load
|
42
47
|
end
|
43
48
|
|
44
49
|
# main Rack routine
|
@@ -77,37 +82,60 @@ module Alfa
|
|
77
82
|
headers['Expires'] = (Time.now + 2592000).httpdate
|
78
83
|
else
|
79
84
|
request = Rack::Request.new(env) # weakref?
|
80
|
-
app_sym =
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
+
app_sym, c_sym, a_sym, l_sym = route_to_symbols(route, params)
|
86
|
+
controller = self.invoke_controller(app_sym, c_sym, route)
|
87
|
+
unless controller.class.instance_methods(false).include?(a_sym)
|
88
|
+
if route[:rule] =~ /\A\/:(controller|action)\/?\z/
|
89
|
+
route, params = self.routes.find_route(Rack::Utils.unescape(env['PATH_INFO']), exclude: [route[:rule]])
|
90
|
+
app_sym, c_sym, a_sym, l_sym = route_to_symbols(route, params)
|
91
|
+
controller = self.invoke_controller(app_sym, c_sym, route)
|
92
|
+
raise Exceptions::Route404 unless controller
|
93
|
+
end
|
94
|
+
end
|
85
95
|
raise Exceptions::Route404 unless controller.class.instance_methods(false).include?(a_sym)
|
86
96
|
controller._clear_instance_variables # cleanup
|
87
97
|
controller.application = self
|
88
98
|
controller.request = request
|
89
99
|
controller.app_sym = app_sym
|
90
100
|
controller.c_sym = c_sym
|
91
|
-
controller.
|
92
|
-
data = controller.
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
101
|
+
controller.params = params
|
102
|
+
data = controller.__send__(a_sym)
|
103
|
+
case controller.class.get_content_type(a_sym)
|
104
|
+
when :json
|
105
|
+
headers['Content-Type'] = 'application/json; charset=utf-8'
|
106
|
+
body = JSON.generate(data, quirks_mode: true)
|
107
|
+
else
|
108
|
+
data = controller._instance_variables_hash
|
109
|
+
resourcer = Alfa::Resourcer.new
|
110
|
+
wrapper = Alfa::Wrapper.new(application: self, request: request, app_sym: app_sym, c_sym: c_sym, resourcer: resourcer, params: params, route: route)
|
111
|
+
Ruty::Tags::RequireStyle.clean_cache # cleanup
|
112
|
+
Ruty::Tags::RequireScript.clean_cache # cleanup
|
113
|
+
content = self.render_template(app_sym, c_sym, a_sym, controller, wrapper, data, &block)
|
114
|
+
if controller.class.get_render(a_sym) == :partial
|
115
|
+
body = content
|
116
|
+
else
|
117
|
+
body = self.render_layout(app_sym.to_s, l_sym.to_s, controller, wrapper, data.merge({:@body => content}))
|
118
|
+
end
|
119
|
+
headers['Content-Type'] = 'text/html; charset=utf-8'
|
120
|
+
end
|
98
121
|
end
|
99
122
|
rescue Alfa::Exceptions::Route404 => e
|
100
123
|
response_code = 404
|
101
|
-
body =
|
124
|
+
body = "Url not found (#{e.message}) <br>urls map:<br>"
|
102
125
|
body += self.routes.instance_variable_get(:@routes).inspect
|
103
126
|
l.info "404: Url not found (#{e.message})"
|
127
|
+
rescue Alfa::Exceptions::Route403 => e
|
128
|
+
response_code = 403
|
129
|
+
body = "Error 403: Forbidden (#{e.message})"
|
130
|
+
l.info "403: Forbidden"
|
104
131
|
rescue Exceptions::HttpRedirect => e
|
105
132
|
response_code = e.code
|
106
133
|
headers['Location'] = e.url.to_s
|
107
|
-
body =
|
134
|
+
body = "You was redirected to #{e.url}"
|
108
135
|
rescue Exception => e
|
109
136
|
response_code = 500
|
110
|
-
body = "Error occured: #{e.message} at #{e.backtrace.first}<br>Full backtrace:<br>\n#{e.backtrace.join("<br>\n")}"
|
137
|
+
body = "Error occured: #{CGI.escape_html(e.message)} at #{e.backtrace.first}<br>Full backtrace:<br>\n#{e.backtrace.join("<br>\n")}"
|
138
|
+
l.error "ERROR: #{e.message} at #{e.backtrace.first}"
|
111
139
|
end
|
112
140
|
if t_sym == :default
|
113
141
|
#debug_info = '<hr>Queries:<br>' + @logger.logs.map { |log|
|
@@ -124,17 +152,44 @@ module Alfa
|
|
124
152
|
return [response_code, headers, [body, @bputs.join('<br>')]]
|
125
153
|
end
|
126
154
|
|
155
|
+
|
156
|
+
def self.route_to_symbols(route, params)
|
157
|
+
app_sym = route[:options].has_key?(:app) ? route[:options][:app] : params[:app]
|
158
|
+
c_sym = route[:options].has_key?(:controller) ? route[:options][:controller] : params[:controller]
|
159
|
+
a_sym = route[:options].has_key?(:action) ? route[:options][:action] : params[:action]
|
160
|
+
l_sym = route[:options].has_key?(:layout) ? route[:options][:layout] : :default
|
161
|
+
return app_sym, c_sym, a_sym, l_sym
|
162
|
+
end
|
163
|
+
|
127
164
|
# router
|
128
165
|
def self.routes
|
129
166
|
@router ||= Alfa::Router
|
130
167
|
end
|
131
168
|
|
132
169
|
|
170
|
+
def self.snippets
|
171
|
+
@snippeter ||= Alfa::Snippeter
|
172
|
+
end
|
173
|
+
|
174
|
+
# Evaluate snippet with given name
|
175
|
+
# @param Symbol name
|
176
|
+
# @param Alfa::Controller controller
|
177
|
+
# return String
|
178
|
+
def self.snippet(name, wrapper)
|
179
|
+
block = snippets[wrapper.app_sym][name]
|
180
|
+
raise "Not found snippet #{name} for app #{wrapper.app_sym}" unless block
|
181
|
+
wrapper.instance_eval(&block)
|
182
|
+
data = wrapper._instance_variables_hash
|
183
|
+
render_snippet(wrapper.app_sym, name, wrapper, data)
|
184
|
+
end
|
185
|
+
|
186
|
+
|
133
187
|
def self.rackup(builder)
|
134
|
-
builder.use Rack::
|
188
|
+
builder.use Rack::Lock
|
189
|
+
builder.use Rack::Session::Cookie, key: @config[:session][:key], secret: @config[:session][:secret]
|
135
190
|
if @config[:serve_static]
|
136
191
|
builder.run Rack::Cascade.new([
|
137
|
-
Rack::FileAlfa.new(@config[:document_root]),
|
192
|
+
Rack::FileAlfa.new(@config[:document_root], {'Cache-Control'=>'max-age=2592000'}),
|
138
193
|
self,
|
139
194
|
])
|
140
195
|
else
|
@@ -152,6 +207,7 @@ module Alfa
|
|
152
207
|
raise Exceptions::HttpRedirect.new(url, code)
|
153
208
|
end
|
154
209
|
|
210
|
+
|
155
211
|
# private section
|
156
212
|
|
157
213
|
def self.verify_config
|
@@ -162,30 +218,39 @@ module Alfa
|
|
162
218
|
@config[:groups][:public] = [] unless @config[:groups][:public]
|
163
219
|
end
|
164
220
|
|
165
|
-
def self.invoke_controller(a_sym, c_sym)
|
166
|
-
|
221
|
+
def self.invoke_controller(a_sym, c_sym, route)
|
222
|
+
f = File.join(@config[:project_root], 'apps', a_sym.to_s, 'controllers', c_sym.to_s + '.rb')
|
223
|
+
return nil unless File.exists?(f)
|
224
|
+
load f
|
167
225
|
klass_name = Alfa::Support.camelcase_name(c_sym)+'Controller'
|
168
226
|
klass = Kernel.const_get(klass_name) # weakref?
|
169
|
-
instance = klass.new
|
227
|
+
instance = klass.new(route: route)
|
170
228
|
Object.module_eval{remove_const(klass_name)}
|
171
229
|
return instance
|
172
230
|
end
|
173
231
|
|
174
|
-
def self.render_template(app_sym, c_sym, a_sym, controller, data = {}, &block)
|
175
|
-
|
232
|
+
def self.render_template(app_sym, c_sym, a_sym, controller, wrapper, data = {}, &block)
|
233
|
+
wrapper.resourcer.level = :action
|
234
|
+
render(file: File.join(@config[:project_root], 'apps', app_sym.to_s, 'templates', c_sym.to_s, a_sym.to_s), controller: controller, data: data, wrapper: wrapper, &block)
|
235
|
+
end
|
236
|
+
|
237
|
+
def self.render_layout(app, layout, controller, wrapper, data = {})
|
238
|
+
wrapper.resourcer.level = :layout
|
239
|
+
render(file: File.join(@config[:project_root], 'apps', app, 'layouts', layout.to_s), controller: controller, wrapper: wrapper, data: data)
|
176
240
|
end
|
177
241
|
|
178
|
-
def self.
|
179
|
-
|
242
|
+
def self.render_snippet(app_sym, snip_sym, wrapper, data = {})
|
243
|
+
wrapper.resourcer.level = :snippet
|
244
|
+
render(file: File.join(@config[:project_root], 'apps', app_sym.to_s, 'templates/_snippets', snip_sym.to_s), wrapper: wrapper, data: data)
|
180
245
|
end
|
181
246
|
|
182
|
-
def self.render(file: nil, controller: nil, data: {})
|
247
|
+
def self.render(file: nil, controller: nil, wrapper: nil, data: {})
|
183
248
|
@config[:templates_priority].each do |ext|
|
184
249
|
f = "#{file}.#{ext}"
|
185
250
|
if File.exist?(f)
|
186
251
|
case ext
|
187
252
|
when :haml
|
188
|
-
template = self.haml_template(f, controller)
|
253
|
+
template = self.haml_template(f, controller, wrapper)
|
189
254
|
yield(controller, template) if block_given? # required only for thread isolation test
|
190
255
|
return template.render data
|
191
256
|
when :tpl
|
@@ -205,9 +270,9 @@ module Alfa
|
|
205
270
|
@ruty_loader ||= Ruty::Loaders::Filesystem.new(:dirname => File.join(@config[:project_root], 'apps'))
|
206
271
|
end
|
207
272
|
|
208
|
-
def self.haml_template(file, controller)
|
273
|
+
def self.haml_template(file, controller, wrapper)
|
209
274
|
# @haml_templates[file.to_sym] ||= TemplateInheritance::Template.new(file)
|
210
|
-
scope = TemplateInheritance::RenderScope.new(controller)
|
275
|
+
scope = TemplateInheritance::RenderScope.new(controller, wrapper, wrapper.resourcer)
|
211
276
|
TemplateInheritance::Template.new(file, scope)
|
212
277
|
end
|
213
278
|
|