nyara 0.1.pre.0 → 0.1.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/nyara +2 -14
- data/changes +3 -0
- data/example/factorial.rb +19 -0
- data/example/hello.rb +5 -0
- data/example/project.rb +11 -0
- data/example/stream.rb +14 -0
- data/ext/extconf.rb +19 -0
- data/ext/hashes.c +160 -57
- data/ext/inc/ary_intern.h +36 -0
- data/ext/route.cc +2 -1
- data/ext/url_encoded.c +1 -0
- data/lib/nyara.rb +1 -0
- data/lib/nyara/command.rb +60 -79
- data/lib/nyara/config.rb +19 -1
- data/lib/nyara/controller.rb +64 -7
- data/lib/nyara/hashes/config_hash.rb +3 -20
- data/lib/nyara/hashes/header_hash.rb +2 -2
- data/lib/nyara/hashes/param_hash.rb +1 -0
- data/lib/nyara/nyara.rb +45 -37
- data/lib/nyara/part.rb +2 -2
- data/lib/nyara/reload.rb +63 -64
- data/lib/nyara/route.rb +7 -6
- data/lib/nyara/session.rb +4 -0
- data/lib/nyara/templates/{Gemfile → Gemfile.tt} +4 -0
- data/lib/nyara/templates/Linnerfile +28 -0
- data/lib/nyara/templates/Rakefile +16 -2
- data/lib/nyara/templates/app/assets/files/favicon.ico +1 -0
- data/lib/nyara/templates/app/assets/files/robots.txt +5 -0
- data/lib/nyara/templates/app/assets/scripts/app.coffee +4 -0
- data/lib/nyara/templates/app/assets/scripts/module-example.coffee +4 -0
- data/lib/nyara/templates/app/assets/styles/app.scss +2 -0
- data/lib/nyara/templates/app/controllers/application_controller.rb +8 -0
- data/lib/nyara/templates/app/views/layouts/application.erb.tt +12 -0
- data/lib/nyara/templates/config/application.rb +4 -0
- data/lib/nyara/templates/config/{database.yml → database.yml.tt} +3 -3
- data/lib/nyara/templates/config/production.rb +2 -0
- data/lib/nyara/view.rb +6 -2
- data/nyara.gemspec +3 -1
- data/rakefile +7 -26
- data/spec/apps/reload.rb +35 -0
- data/spec/command_spec.rb +24 -10
- data/spec/config_spec.rb +19 -8
- data/spec/controller_spec.rb +14 -0
- data/spec/evented_io_spec.rb +3 -1
- data/spec/ext_route_spec.rb +25 -3
- data/spec/hashes_spec.rb +45 -21
- data/spec/integration_spec.rb +28 -2
- data/spec/path_helper_spec.rb +7 -0
- data/spec/performance_spec.rb +1 -1
- data/spec/public/test.css +1 -0
- data/{lib/nyara/templates/public/robot.txt → spec/public/test.jpg} +0 -0
- data/spec/public/test.js +1 -0
- data/spec/reload_spec.rb +50 -0
- data/spec/route_spec.rb +4 -4
- data/spec/spec_helper.rb +15 -9
- data/spec/url_encoded_spec.rb +5 -0
- data/spec/view_spec.rb +7 -0
- data/spec/views/_partial.slim +1 -1
- data/tools/bug.rb +53 -0
- data/tools/hello.rb +49 -0
- data/tools/memcheck.rb +33 -0
- metadata +73 -41
- data/ext/inc/status_codes.inc +0 -64
- data/lib/nyara/templates/app/views/layouts/application.erb +0 -12
- data/lib/nyara/templates/public/css/app.css +0 -1
- data/lib/nyara/templates/public/js/app.js +0 -1
@@ -0,0 +1,36 @@
|
|
1
|
+
/* array internals, from ruby source code array.c */
|
2
|
+
|
3
|
+
#pragma once
|
4
|
+
|
5
|
+
# define ARY_SHARED_P(ary) \
|
6
|
+
(assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
|
7
|
+
FL_TEST((ary),ELTS_SHARED)!=0)
|
8
|
+
# define ARY_EMBED_P(ary) \
|
9
|
+
(assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
|
10
|
+
FL_TEST((ary), RARRAY_EMBED_FLAG)!=0)
|
11
|
+
|
12
|
+
#define ARY_SET_PTR(ary, p) do { \
|
13
|
+
assert(!ARY_EMBED_P(ary)); \
|
14
|
+
assert(!OBJ_FROZEN(ary)); \
|
15
|
+
RARRAY(ary)->as.heap.ptr = (p); \
|
16
|
+
} while (0)
|
17
|
+
#define ARY_SET_EMBED_LEN(ary, n) do { \
|
18
|
+
long tmp_n = (n); \
|
19
|
+
assert(ARY_EMBED_P(ary)); \
|
20
|
+
assert(!OBJ_FROZEN(ary)); \
|
21
|
+
RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
|
22
|
+
RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
|
23
|
+
} while (0)
|
24
|
+
#define ARY_SET_HEAP_LEN(ary, n) do { \
|
25
|
+
assert(!ARY_EMBED_P(ary)); \
|
26
|
+
RARRAY(ary)->as.heap.len = (n); \
|
27
|
+
} while (0)
|
28
|
+
#define ARY_SET_LEN(ary, n) do { \
|
29
|
+
if (ARY_EMBED_P(ary)) { \
|
30
|
+
ARY_SET_EMBED_LEN((ary), (n)); \
|
31
|
+
} \
|
32
|
+
else { \
|
33
|
+
ARY_SET_HEAP_LEN((ary), (n)); \
|
34
|
+
} \
|
35
|
+
assert(RARRAY_LEN(ary) == (n)); \
|
36
|
+
} while (0)
|
data/ext/route.cc
CHANGED
@@ -254,7 +254,8 @@ RouteResult nyara_lookup_route(enum http_method method_num, VALUE vpath, VALUE a
|
|
254
254
|
if (suffix_len) {
|
255
255
|
r.format = extract_ext(suffix, suffix_len);
|
256
256
|
if (r.format == Qnil) {
|
257
|
-
|
257
|
+
// suffix not match
|
258
|
+
continue;
|
258
259
|
}
|
259
260
|
}
|
260
261
|
r.args = rb_ary_new3(1, i->id);
|
data/ext/url_encoded.c
CHANGED
data/lib/nyara.rb
CHANGED
data/lib/nyara/command.rb
CHANGED
@@ -1,105 +1,86 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
module Command
|
4
|
-
extend self
|
1
|
+
require "thor"
|
2
|
+
require "shellwords"
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
module Nyara
|
5
|
+
class Command < Thor
|
6
|
+
include Thor::Actions
|
7
|
+
map '-v' => :version
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
nyara new APP_NAME\t\tTo initialize a new project with default template in current directory.
|
13
|
-
nyara version\t\t\tDisplay current version
|
14
|
-
)
|
9
|
+
def self.source_root
|
10
|
+
__dir__
|
15
11
|
end
|
16
12
|
|
13
|
+
desc "version", "Show version"
|
17
14
|
def version
|
18
15
|
puts "Nyara #{Nyara::VERSION}"
|
19
16
|
end
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
force: false
|
25
|
-
}
|
26
|
-
OptionParser.new do |opt|
|
27
|
-
opt.banner = 'Usage: nyara new APP_NAME [options]'
|
28
|
-
opt.on('-f', 'Force override old') do
|
29
|
-
opts[:force] = true
|
30
|
-
end
|
31
|
-
end.parse(args)
|
32
|
-
|
18
|
+
desc "new APP_NAME", "Create a project"
|
19
|
+
method_option :force, aliases: '-f', desc: 'Force override old', type: :boolean, default: false
|
20
|
+
def new name
|
33
21
|
require 'fileutils'
|
34
|
-
require "erb"
|
35
|
-
require 'ostruct'
|
36
|
-
require_relative "view_handlers/erb"
|
37
22
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
return
|
42
|
-
end
|
43
|
-
|
44
|
-
app_dir = File.join(Dir.pwd, name)
|
23
|
+
app_dir = File.expand_path File.join(Dir.pwd, name)
|
24
|
+
@rel_dir = name
|
25
|
+
@app_name = File.basename app_dir
|
45
26
|
templte_dir = File.join(File.dirname(__FILE__), "templates")
|
46
27
|
|
47
|
-
FileUtils.rm_rf(app_dir) if
|
48
|
-
|
49
|
-
if Dir.exist?(app_dir)
|
50
|
-
puts "This has same dir name's '#{name}' existed, Nyara can not override it."
|
51
|
-
return
|
52
|
-
end
|
53
|
-
|
54
|
-
Dir.mkdir(app_dir)
|
55
|
-
|
56
|
-
puts "Generate Nyara project..."
|
57
|
-
source_templates = Dir.glob("#{templte_dir}/*")
|
58
|
-
puts source_templates.map{|f| File.basename f }
|
59
|
-
FileUtils.cp_r(source_templates, app_dir)
|
28
|
+
FileUtils.rm_rf(app_dir) if options[:force]
|
29
|
+
directory 'templates', name
|
60
30
|
|
61
|
-
|
62
|
-
|
63
|
-
render_opts = {
|
64
|
-
app_name: name
|
65
|
-
}
|
66
|
-
files.each do |fname|
|
67
|
-
if not File.directory?(fname)
|
68
|
-
render_template(fname, render_opts)
|
69
|
-
end
|
31
|
+
create_file app_dir + '/.gitignore' do
|
32
|
+
%w".DS_Store config/session.key config/session_cipher.key".join "\n"
|
70
33
|
end
|
34
|
+
generate 'session.key'
|
35
|
+
puts ' \\ 👻 /'
|
36
|
+
ensure
|
37
|
+
@app_name = nil
|
38
|
+
@rel_dir = nil
|
39
|
+
end
|
71
40
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
41
|
+
desc "generate THING", "(PROJECT) Generate things, THING can be:
|
42
|
+
session.key # config/session.key
|
43
|
+
session_cipher.key # config/session_cipher.key"
|
44
|
+
def generate thing, app_dir=nil
|
45
|
+
case thing
|
46
|
+
when 'session.key'
|
47
|
+
file = "config/session.key"
|
48
|
+
file = File.join @rel_dir, file if @rel_dir
|
49
|
+
create_file file do
|
50
|
+
Session.generate_key
|
76
51
|
end
|
77
|
-
|
78
|
-
|
79
|
-
File.
|
80
|
-
|
81
|
-
|
52
|
+
when 'session_cipher.key'
|
53
|
+
file = 'config/session_cipher.key'
|
54
|
+
file = File.join @rel_dir, file if @rel_dir
|
55
|
+
create_file file do
|
56
|
+
Session.generate_cipher_key
|
82
57
|
end
|
83
58
|
end
|
84
|
-
|
85
|
-
puts "Enjoy!"
|
86
59
|
end
|
87
60
|
|
88
|
-
|
89
|
-
|
90
|
-
|
61
|
+
desc "server", "(PROJECT) Start server"
|
62
|
+
method_option :environment, aliases: %w'-e -E', default: 'development'
|
63
|
+
def server
|
64
|
+
env = options[:environment].shellescape
|
65
|
+
exec "NYARA_ENV=#{env} ruby config/boot.rb"
|
91
66
|
end
|
92
67
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
68
|
+
desc "console", "(PROJECT) Start console"
|
69
|
+
method_option :environment, aliases: %w'-e -E', default: 'development'
|
70
|
+
method_option :shell, aliases: '-s', desc: "tell me which shell you want to use, pry or irb?"
|
71
|
+
def console
|
72
|
+
env = options[:environment].shellescape
|
73
|
+
cmd = options[:shell]
|
74
|
+
unless cmd
|
75
|
+
if File.read('Gemfile') =~ /\bpry\b/
|
76
|
+
cmd = 'pry'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
cmd ||= 'irb'
|
80
|
+
if cmd != 'irb'
|
81
|
+
cmd = "bundle exec #{cmd}"
|
102
82
|
end
|
83
|
+
exec "NYARA_ENV=#{env} #{cmd} -r./config/application.rb"
|
103
84
|
end
|
104
85
|
|
105
86
|
end
|
data/lib/nyara/config.rb
CHANGED
@@ -7,11 +7,14 @@ module Nyara
|
|
7
7
|
# * `host` - host name used in `url_to` helper
|
8
8
|
# * `root` - root path, default is `Dir.pwd`
|
9
9
|
# * `views` - views (templates) directory, relative to root, default is `"views"`
|
10
|
+
# * `assets` - assets directory, relative to root, default is `"assets"`
|
10
11
|
# * `public` - static files directory, relative to root, default is `"public"`
|
11
12
|
# * `x_send_file` - header field name for `X-Sendfile` or `X-Accel-Redirect`, see [Nyara::Controller#send_file](Controller#send_file.html-instance_method) for details
|
12
13
|
# * `session` - see [Nyara::Session](Session.html) for sub options
|
13
14
|
# * `prefer_erb` - use ERB instead of ERubis for `.erb` templates
|
14
15
|
# * `logger` - if set, every request is logged, and you can use `Nyara.logger` to do your own logging.
|
16
|
+
# * `app_files` - application source file glob patterns, they will be required automatically.
|
17
|
+
# In developemnt mode, this option enables automatic reloading for views and app.
|
15
18
|
# * `before_fork` - a proc to run before forking
|
16
19
|
# * `after_fork` - a proc to run after forking
|
17
20
|
#
|
@@ -51,13 +54,18 @@ module Nyara
|
|
51
54
|
unless self['root']
|
52
55
|
set :root, Dir.pwd
|
53
56
|
end
|
54
|
-
self['root'] = File.expand_path self['root']
|
57
|
+
self['root'] = File.realpath File.expand_path self['root']
|
55
58
|
|
59
|
+
# todo warn paths not under project?
|
56
60
|
self['views'] = project_path(self['views'] || 'views')
|
57
61
|
if self['public']
|
58
62
|
self['public'] = project_path(self['public'])
|
59
63
|
end
|
60
64
|
|
65
|
+
if self['assets']
|
66
|
+
self['assets'] = project_path(self['assets'])
|
67
|
+
end
|
68
|
+
|
61
69
|
self.logger = create_logger
|
62
70
|
|
63
71
|
assert !self['before_fork'] || self['before_fork'].respond_to?('call')
|
@@ -111,6 +119,16 @@ module Nyara
|
|
111
119
|
path_under 'views', path, strict
|
112
120
|
end
|
113
121
|
|
122
|
+
# Get absoute path under assets path
|
123
|
+
#
|
124
|
+
# #### Options
|
125
|
+
#
|
126
|
+
# * `strict` - return `nil` if path is not under the dir
|
127
|
+
#
|
128
|
+
def assets_path path, strict=true
|
129
|
+
path_under "assets", path, strict
|
130
|
+
end
|
131
|
+
|
114
132
|
# Get path under the dir configured `Nyara.config[key]`
|
115
133
|
#
|
116
134
|
# #### Options
|
data/lib/nyara/controller.rb
CHANGED
@@ -9,6 +9,11 @@ module Nyara
|
|
9
9
|
# end
|
10
10
|
#
|
11
11
|
def http method, path, &blk
|
12
|
+
# special treatment: '/' also maps ''
|
13
|
+
if path == '/'
|
14
|
+
http method, '', &blk
|
15
|
+
end
|
16
|
+
|
12
17
|
@routes ||= []
|
13
18
|
@used_ids = {}
|
14
19
|
method = method.to_s.upcase
|
@@ -164,6 +169,40 @@ module Nyara
|
|
164
169
|
end
|
165
170
|
end
|
166
171
|
|
172
|
+
def self.process_reload request, l
|
173
|
+
if request.http_method == 'POST' and request.path =~ /\A\/reload:([\w-]+)\z/
|
174
|
+
ty = $1
|
175
|
+
files = request.param['files']
|
176
|
+
case ty
|
177
|
+
when 'views-modified'
|
178
|
+
files.each do |f|
|
179
|
+
if l
|
180
|
+
l.info "modified: #{f}"
|
181
|
+
end
|
182
|
+
View.on_removed f
|
183
|
+
View.on_modified f
|
184
|
+
end
|
185
|
+
when 'views-removed'
|
186
|
+
files.each do |f|
|
187
|
+
if l
|
188
|
+
l.info "removed: #{f}"
|
189
|
+
end
|
190
|
+
View.on_removed f
|
191
|
+
end
|
192
|
+
when 'app-modified'
|
193
|
+
files.each do |f|
|
194
|
+
if l
|
195
|
+
l.info "modified: #{f}"
|
196
|
+
end
|
197
|
+
Reload.load_file f
|
198
|
+
end
|
199
|
+
else
|
200
|
+
return false
|
201
|
+
end
|
202
|
+
true
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
167
206
|
def self.dispatch request, instance, args
|
168
207
|
if cookie_str = request.header._aref('Cookie')
|
169
208
|
ParamHash.parse_cookie request.cookie, cookie_str
|
@@ -172,25 +211,35 @@ module Nyara
|
|
172
211
|
request.session = Session.decode(request.cookie)
|
173
212
|
)
|
174
213
|
|
214
|
+
l = Nyara.logger
|
215
|
+
|
175
216
|
if instance
|
176
|
-
if l
|
217
|
+
if l
|
177
218
|
l.info "#{request.http_method} #{request.path} => #{instance.class}"
|
219
|
+
if %W"POST PUT PATCH".include?(request.http_method)
|
220
|
+
l.info " params: #{instance.params.inspect}"
|
221
|
+
end
|
178
222
|
end
|
179
223
|
instance.send *args
|
180
224
|
return
|
181
225
|
elsif request.http_method == 'GET' and Config['public']
|
182
226
|
path = Config.public_path request.path
|
183
227
|
if File.file?(path)
|
184
|
-
if l
|
185
|
-
l.info "GET #{path} => public 200"
|
228
|
+
if l
|
229
|
+
l.info "GET #{request.path} => public 200"
|
186
230
|
end
|
187
231
|
instance = Controller.new request
|
188
232
|
instance.send_file path
|
189
233
|
return
|
190
234
|
end
|
235
|
+
elsif Config.development?
|
236
|
+
if process_reload(request, l)
|
237
|
+
Ext.request_send_data request, "HTTP/1.1 200 OK\r\n\r\n"
|
238
|
+
return
|
239
|
+
end
|
191
240
|
end
|
192
241
|
|
193
|
-
if l
|
242
|
+
if l
|
194
243
|
l.info "#{request.http_method} #{request.path} => 404"
|
195
244
|
end
|
196
245
|
Ext.request_send_data request, "HTTP/1.1 404 Not Found\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
|
@@ -207,6 +256,9 @@ module Nyara
|
|
207
256
|
end
|
208
257
|
|
209
258
|
template, meth = self.class.path_templates[id.to_s]
|
259
|
+
if template.blank? && meth.blank?
|
260
|
+
raise ArgumentError, "#{id} route not found."
|
261
|
+
end
|
210
262
|
r = template % args
|
211
263
|
|
212
264
|
if opts
|
@@ -273,8 +325,11 @@ module Nyara
|
|
273
325
|
end
|
274
326
|
|
275
327
|
# Shortcut for `redirect url_to *xs`
|
276
|
-
def redirect_to *xs
|
277
|
-
|
328
|
+
def redirect_to identifier, *xs
|
329
|
+
if identifier !~ /\A\w*#\w++(?:\-\w++)*\z/
|
330
|
+
raise ArgumentError, "not action identifier: #{identifier.inspect}, did you mean `redirect`?"
|
331
|
+
end
|
332
|
+
redirect url_to(identifier, *xs)
|
278
333
|
end
|
279
334
|
|
280
335
|
# Stop processing and close connection<br>
|
@@ -479,6 +534,8 @@ module Nyara
|
|
479
534
|
unless content_type
|
480
535
|
extname = File.extname(file)
|
481
536
|
extname = File.extname(filename) if extname.blank? and filename
|
537
|
+
extname.gsub!(".","")
|
538
|
+
|
482
539
|
content_type = MIME_TYPES[extname] || 'application/octet-stream'
|
483
540
|
end
|
484
541
|
header['Content-Type'] = content_type
|
@@ -526,7 +583,7 @@ module Nyara
|
|
526
583
|
|
527
584
|
# Render a template as string
|
528
585
|
def partial view_path, locals: nil
|
529
|
-
view = View.new self, view_path, nil,
|
586
|
+
view = View.new self, view_path, nil, locals, {}
|
530
587
|
view.partial
|
531
588
|
end
|
532
589
|
|
@@ -1,33 +1,16 @@
|
|
1
1
|
module Nyara
|
2
2
|
# Extended hash class for the use in configuration.
|
3
3
|
class ConfigHash
|
4
|
-
# @private
|
5
|
-
alias _aref [] # :nodoc:
|
6
|
-
# @private
|
7
|
-
alias _aset []= # :nodoc:
|
8
|
-
|
9
4
|
# #### Call-seq
|
10
5
|
#
|
11
|
-
# config['a', 'very', 'deep', 'key']
|
6
|
+
# config['a', 'very', 'deep', '', 'key']
|
12
7
|
#
|
13
8
|
# Equivalent to
|
14
9
|
#
|
15
|
-
# config['a']['very']['deep']['key'] rescue nil
|
10
|
+
# config['a']['very']['deep'].last['key'] rescue nil
|
16
11
|
#
|
17
12
|
def [] *keys
|
18
|
-
|
19
|
-
keys.each do |key|
|
20
|
-
if h.has_key?(key)
|
21
|
-
if h.is_a?(ConfigHash)
|
22
|
-
h = h._aref key
|
23
|
-
else
|
24
|
-
h = h[key]
|
25
|
-
end
|
26
|
-
else
|
27
|
-
return nil # todo default value?
|
28
|
-
end
|
29
|
-
end
|
30
|
-
h
|
13
|
+
nested_aref keys.map(&:to_s)
|
31
14
|
end
|
32
15
|
|
33
16
|
# #### Call-seq
|