utopia 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -1
  4. data/Gemfile +3 -0
  5. data/README.md +11 -0
  6. data/benchmarks/hash_vs_openstruct.rb +52 -0
  7. data/benchmarks/struct_vs_class.rb +89 -0
  8. data/bin/utopia +4 -5
  9. data/lib/utopia.rb +1 -0
  10. data/lib/utopia/content.rb +24 -15
  11. data/lib/utopia/content/node.rb +69 -3
  12. data/lib/utopia/content/processor.rb +32 -5
  13. data/lib/utopia/content/transaction.rb +138 -147
  14. data/lib/utopia/content_length.rb +50 -0
  15. data/lib/utopia/controller.rb +4 -0
  16. data/lib/utopia/controller/variables.rb +1 -1
  17. data/lib/utopia/http.rb +2 -0
  18. data/lib/utopia/localization.rb +4 -8
  19. data/lib/utopia/path.rb +13 -13
  20. data/lib/utopia/static.rb +25 -14
  21. data/lib/utopia/tags/environment.rb +1 -1
  22. data/lib/utopia/tags/override.rb +1 -1
  23. data/lib/utopia/version.rb +1 -1
  24. data/setup/server/git/hooks/post-receive +32 -24
  25. data/setup/site/Gemfile +8 -0
  26. data/setup/site/Rakefile +29 -6
  27. data/setup/site/config.ru +8 -8
  28. data/setup/site/pages/_heading.xnode +1 -1
  29. data/setup/site/pages/_page.xnode +2 -2
  30. data/spec/utopia/content_spec.rb +3 -3
  31. data/spec/utopia/controller/sequence_spec.rb +1 -1
  32. data/spec/utopia/controller/variables_spec.rb +1 -1
  33. data/spec/utopia/pages/node/index.xnode +1 -1
  34. data/spec/utopia/performance_spec.rb +90 -0
  35. data/spec/utopia/performance_spec/cache/head/readme.txt +1 -0
  36. data/spec/utopia/performance_spec/cache/meta/readme.txt +1 -0
  37. data/spec/utopia/performance_spec/config.ru +39 -0
  38. data/spec/utopia/performance_spec/lib/readme.txt +1 -0
  39. data/spec/utopia/performance_spec/pages/_heading.xnode +2 -0
  40. data/spec/utopia/performance_spec/pages/_page.xnode +26 -0
  41. data/spec/utopia/performance_spec/pages/api/controller.rb +7 -0
  42. data/spec/utopia/performance_spec/pages/errors/exception.xnode +5 -0
  43. data/spec/utopia/performance_spec/pages/errors/file-not-found.xnode +5 -0
  44. data/spec/utopia/performance_spec/pages/links.yaml +2 -0
  45. data/spec/utopia/performance_spec/pages/welcome/index.xnode +17 -0
  46. data/spec/utopia/rack_helper.rb +5 -2
  47. data/spec/utopia/setup_spec.rb +93 -0
  48. data/utopia.gemspec +1 -1
  49. metadata +34 -5
  50. data/lib/utopia/mail_exceptions.rb +0 -136
@@ -0,0 +1 @@
1
+ This is a place-holder file so that this directory is created correctly.
@@ -0,0 +1 @@
1
+ This is a place-holder file so that this directory is created correctly.
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env rackup
2
+
3
+ require 'utopia'
4
+ require 'rack/cache'
5
+
6
+ # use Rack::ContentLength
7
+ use Utopia::ContentLength
8
+
9
+ use Utopia::Redirection::Rewrite,
10
+ '/' => '/welcome/index'
11
+
12
+ use Utopia::Redirection::DirectoryIndex
13
+
14
+ use Utopia::Redirection::Errors,
15
+ 404 => '/errors/file-not-found'
16
+
17
+ # use Utopia::Localization,
18
+ # :default_locale => 'en',
19
+ # :locales => ['en', 'de', 'ja', 'zh'],
20
+ # :nonlocalized => ['/_static/', '/_cache/']
21
+
22
+ use Utopia::Controller,
23
+ root: File.expand_path('pages', __dir__),
24
+ cache_controllers: true
25
+
26
+ use Utopia::Static,
27
+ root: File.expand_path('pages', __dir__)
28
+
29
+ # Serve dynamic content
30
+ use Utopia::Content,
31
+ root: File.expand_path('pages', __dir__),
32
+ cache_templates: true,
33
+ tags: {
34
+ 'deferred' => Utopia::Tags::Deferred,
35
+ 'override' => Utopia::Tags::Override,
36
+ 'node' => Utopia::Tags::Node,
37
+ }
38
+
39
+ run lambda { |env| [404, {}, []] }
@@ -0,0 +1 @@
1
+ You can add additional code for your application in this directory, and require it directly from the config.ru.
@@ -0,0 +1,2 @@
1
+ <?r transaction.attributes[:title] ||= content ?>
2
+ <h1><content/></h1>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <?r response.content_type = "text/html; charset=utf-8" ?>
5
+ <?r response.cache! ?>
6
+
7
+ <?r if title = self[:title] ?>
8
+ <title>#{title.gsub(/<.*?>/, "")} - Utopia</title>
9
+ <?r else ?>
10
+ <title>Utopia</title>
11
+ <?r end ?>
12
+
13
+ <link rel="icon" type="image/png" href="/_static/icon.png" />
14
+ <link rel="stylesheet" href="/_static/site.css" type="text/css" media="screen" />
15
+ </head>
16
+
17
+ <body class="#{self[:class]}">
18
+ <div id="header">
19
+ <img src="/_static/utopia.svg" />
20
+ </div>
21
+
22
+ <div id="page">
23
+ <content />
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,7 @@
1
+
2
+ prepend Respond
3
+ respond.with_json
4
+
5
+ on 'fetch' do
6
+ succeed! content: [1, 2, 3]
7
+ end
@@ -0,0 +1,5 @@
1
+ <page>
2
+ <heading>Exception</heading>
3
+
4
+ <p>It seems like something didn't quite work out as expected!</p>
5
+ </page>
@@ -0,0 +1,5 @@
1
+ <page>
2
+ <heading>File Not Found</heading>
3
+
4
+ <p>The file you requested is unfortunately not available at this time!</p>
5
+ </page>
@@ -0,0 +1,2 @@
1
+ errors:
2
+ display: false
@@ -0,0 +1,17 @@
1
+ <page class="front">
2
+ <heading>Welcome to Utopia</heading>
3
+
4
+ <p><strong>Utopia is designed to simplify web development.</strong> Utopia is a fully featured stack for both content-heavy sites and dynamic web applications.</p>
5
+
6
+ <h2>Server Side Tag Based Markup</h2>
7
+
8
+ <p>Server side tags reduce the amount of duplicate view code especially for content-heavy sites.</p>
9
+
10
+ <h2>Recursive Controller Layer</h2>
11
+
12
+ <p>Nested controllers make access control a breeze.</p>
13
+
14
+ <h2>Standards Based Localization</h2>
15
+
16
+ <p>Automatically sniff the user's desired language and provide content in the correct language.</p>
17
+ </page>
@@ -20,8 +20,11 @@
20
20
 
21
21
  require 'rack/test'
22
22
 
23
- RSpec.shared_context "rack app" do |rackup_path|
23
+ RSpec.shared_context "rack app" do |relative_rackup_path|
24
24
  include Rack::Test::Methods
25
25
 
26
- let(:app) {Rack::Builder.parse_file(File.expand_path(rackup_path, __dir__)).first}
26
+ let(:rackup_path) {File.expand_path(relative_rackup_path, __dir__)}
27
+ let(:rackup_directory) {File.dirname(rackup_path)}
28
+
29
+ let(:app) {Rack::Builder.parse_file(rackup_path).first}
27
30
  end
@@ -0,0 +1,93 @@
1
+ # Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'fileutils'
22
+
23
+ RSpec.describe "utopia executable" do
24
+ let(:utopia) {File.expand_path("../../bin/utopia", __dir__)}
25
+
26
+ before(:all) do
27
+ # We need to build a package to test deployment:
28
+ system("rake", "build")
29
+
30
+ ENV.delete 'BUNDLE_BIN_PATH'
31
+ ENV.delete 'BUNDLE_GEMFILE'
32
+ ENV.delete 'RUBYOPT'
33
+ end
34
+
35
+ def sh(*args)
36
+ puts args.join(' ')
37
+ system(*args)
38
+ return $?
39
+ end
40
+
41
+ def install_packages(dir)
42
+ package_path = File.expand_path("../../pkg/utopia-#{Utopia::VERSION}.gem", __dir__)
43
+
44
+ # We do a bit of a hack here to ensure the package is available:
45
+ FileUtils.mkpath File.join(dir, "vendor/cache")
46
+ FileUtils.cp package_path, File.join(dir, "vendor/cache")
47
+ end
48
+
49
+ it "should generate sample site" do
50
+ Dir.mktmpdir('test-site') do |dir|
51
+ install_packages(dir)
52
+
53
+ result = sh(utopia, "create", dir)
54
+ expect(result).to be == 0
55
+
56
+ expect(Dir.entries(dir)).to include(".bowerrc", ".git", "Gemfile", "Gemfile.lock", "README.md", "Rakefile", "cache", "config.ru", "lib", "pages", "public", "tmp")
57
+ end
58
+ end
59
+
60
+ it "should generate a sample server" do
61
+ Dir.mktmpdir('test-server') do |dir|
62
+ install_packages(dir)
63
+
64
+ result = sh(utopia, "server:create", dir)
65
+ expect(result).to be == 0
66
+
67
+ expect(Dir.entries(dir)).to include(".git")
68
+ end
69
+ end
70
+
71
+ it "can generate sample site, server and push to the server" do
72
+ Dir.mktmpdir('test') do |dir|
73
+ site_path = File.join(dir, 'site')
74
+
75
+ install_packages(site_path)
76
+
77
+ server_path = File.join(dir, 'server')
78
+
79
+ result = sh(utopia, "create", site_path)
80
+ expect(result).to be == 0
81
+
82
+ result = sh(utopia, "server:create", server_path)
83
+ expect(result).to be == 0
84
+
85
+ Dir.chdir(site_path) do
86
+ result = sh("git", "push", "--set-upstream", server_path, "master")
87
+ expect(result).to be == 0
88
+ end
89
+
90
+ expect(Dir.entries(server_path)).to include(".bowerrc", ".git", "Gemfile", "README.md", "Rakefile", "cache", "config.ru", "lib", "pages", "public", "tmp")
91
+ end
92
+ end
93
+ end
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.required_ruby_version = '~> 2.0'
26
26
 
27
- spec.add_dependency 'trenni', '~> 1.4.5'
27
+ spec.add_dependency 'trenni', '~> 1.5.0'
28
28
  spec.add_dependency 'mime-types', '~> 2.0'
29
29
 
30
30
  spec.add_dependency 'rack', '~> 1.6'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: utopia
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-23 00:00:00.000000000 Z
11
+ date: 2016-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trenni
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.4.5
19
+ version: 1.5.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.4.5
26
+ version: 1.5.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: mime-types
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -182,6 +182,8 @@ files:
182
182
  - Gemfile
183
183
  - README.md
184
184
  - Rakefile
185
+ - benchmarks/hash_vs_openstruct.rb
186
+ - benchmarks/struct_vs_class.rb
185
187
  - bin/utopia
186
188
  - ext/utopia/xnode/fast_scanner/extconf.rb
187
189
  - ext/utopia/xnode/fast_scanner/parser.c
@@ -193,6 +195,7 @@ files:
193
195
  - lib/utopia/content/processor.rb
194
196
  - lib/utopia/content/tag.rb
195
197
  - lib/utopia/content/transaction.rb
198
+ - lib/utopia/content_length.rb
196
199
  - lib/utopia/controller.rb
197
200
  - lib/utopia/controller/action.rb
198
201
  - lib/utopia/controller/base.rb
@@ -208,7 +211,6 @@ files:
208
211
  - lib/utopia/http.rb
209
212
  - lib/utopia/locale.rb
210
213
  - lib/utopia/localization.rb
211
- - lib/utopia/mail_exceptions.rb
212
214
  - lib/utopia/middleware.rb
213
215
  - lib/utopia/path.rb
214
216
  - lib/utopia/path/matcher.rb
@@ -314,12 +316,25 @@ files:
314
316
  - spec/utopia/pages/test.txt
315
317
  - spec/utopia/path/matcher_spec.rb
316
318
  - spec/utopia/path_spec.rb
319
+ - spec/utopia/performance_spec.rb
320
+ - spec/utopia/performance_spec/cache/head/readme.txt
321
+ - spec/utopia/performance_spec/cache/meta/readme.txt
322
+ - spec/utopia/performance_spec/config.ru
323
+ - spec/utopia/performance_spec/lib/readme.txt
324
+ - spec/utopia/performance_spec/pages/_heading.xnode
325
+ - spec/utopia/performance_spec/pages/_page.xnode
326
+ - spec/utopia/performance_spec/pages/api/controller.rb
327
+ - spec/utopia/performance_spec/pages/errors/exception.xnode
328
+ - spec/utopia/performance_spec/pages/errors/file-not-found.xnode
329
+ - spec/utopia/performance_spec/pages/links.yaml
330
+ - spec/utopia/performance_spec/pages/welcome/index.xnode
317
331
  - spec/utopia/rack_helper.rb
318
332
  - spec/utopia/rack_spec.rb
319
333
  - spec/utopia/redirection_spec.rb
320
334
  - spec/utopia/redirection_spec.ru
321
335
  - spec/utopia/session_spec.rb
322
336
  - spec/utopia/session_spec.ru
337
+ - spec/utopia/setup_spec.rb
323
338
  - spec/utopia/static_spec.rb
324
339
  - spec/utopia/static_spec.ru
325
340
  - utopia.gemspec
@@ -415,11 +430,25 @@ test_files:
415
430
  - spec/utopia/pages/test.txt
416
431
  - spec/utopia/path/matcher_spec.rb
417
432
  - spec/utopia/path_spec.rb
433
+ - spec/utopia/performance_spec.rb
434
+ - spec/utopia/performance_spec/cache/head/readme.txt
435
+ - spec/utopia/performance_spec/cache/meta/readme.txt
436
+ - spec/utopia/performance_spec/config.ru
437
+ - spec/utopia/performance_spec/lib/readme.txt
438
+ - spec/utopia/performance_spec/pages/_heading.xnode
439
+ - spec/utopia/performance_spec/pages/_page.xnode
440
+ - spec/utopia/performance_spec/pages/api/controller.rb
441
+ - spec/utopia/performance_spec/pages/errors/exception.xnode
442
+ - spec/utopia/performance_spec/pages/errors/file-not-found.xnode
443
+ - spec/utopia/performance_spec/pages/links.yaml
444
+ - spec/utopia/performance_spec/pages/welcome/index.xnode
418
445
  - spec/utopia/rack_helper.rb
419
446
  - spec/utopia/rack_spec.rb
420
447
  - spec/utopia/redirection_spec.rb
421
448
  - spec/utopia/redirection_spec.ru
422
449
  - spec/utopia/session_spec.rb
423
450
  - spec/utopia/session_spec.ru
451
+ - spec/utopia/setup_spec.rb
424
452
  - spec/utopia/static_spec.rb
425
453
  - spec/utopia/static_spec.ru
454
+ has_rdoc:
@@ -1,136 +0,0 @@
1
- # Copyright, 2013, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
20
-
21
- require 'net/smtp'
22
- require 'mail'
23
-
24
- module Utopia
25
- # Catches all exceptions raised from the app it wraps and sends a useful email with the exception, stacktrace, and contents of the environment.
26
- class MailExceptions
27
- # A basic local non-authenticated SMTP server.
28
- LOCAL_SMTP = [:smtp, {
29
- :address => "localhost",
30
- :port => 25,
31
- :enable_starttls_auto => false
32
- }]
33
-
34
- def initialize(app, config = {})
35
- @app = app
36
-
37
- @to = config[:to] || "postmaster"
38
- @from = config.fetch(:from) {(ENV['USER'] || 'rack') + "@localhost"}
39
- @subject = config[:subject] || '%{exception} [PID %{pid} : %{cwd}]'
40
- @delivery_method = config.fetch(:delivery_method, LOCAL_SMTP)
41
-
42
- @dump_environment = config.fetch(:dump_environment, false)
43
- end
44
-
45
- def call(env)
46
- begin
47
- return @app.call(env)
48
- rescue => exception
49
- send_notification exception, env
50
-
51
- raise
52
- end
53
- end
54
-
55
- private
56
-
57
- REQUEST_KEYS = [:ip, :referrer, :path, :user_agent]
58
-
59
- def generate_body(exception, env)
60
- io = StringIO.new
61
-
62
- # Dump out useful rack environment variables:
63
- request = Rack::Request.new(env)
64
-
65
- io.puts "#{request.request_method} #{request.url}"
66
-
67
- io.puts
68
-
69
- REQUEST_KEYS.each do |key|
70
- value = request.send(key)
71
- io.puts "request.#{key}: #{value.inspect}"
72
- end
73
-
74
- request.params.each do |key, value|
75
- io.puts "request.params.#{key}: #{value.inspect}"
76
- end
77
-
78
- io.puts
79
-
80
- io.puts "#{exception.class.name}: #{exception.to_s}"
81
-
82
- if exception.respond_to?(:backtrace)
83
- io.puts exception.backtrace
84
- else
85
- io.puts exception.to_s
86
- end
87
-
88
- return io.string
89
- end
90
-
91
- def generate_mail(exception, env)
92
- attributes = {
93
- exception: exception.class.name,
94
- pid: $$,
95
- cwd: Dir.getwd,
96
- }
97
-
98
- mail = Mail.new(
99
- :from => @from,
100
- :to => @to,
101
- :subject => @subject % attributes
102
- )
103
-
104
- mail.text_part = Mail::Part.new
105
- mail.text_part.body = generate_body(exception, env)
106
-
107
- if body = extract_body(env) and body.size > 0
108
- mail.attachments['body.bin'] = body
109
- end
110
-
111
- if @dump_environment
112
- mail.attachments['environment.yaml'] = YAML::dump(env)
113
- end
114
-
115
- return mail
116
- end
117
-
118
- def send_notification(exception, env)
119
- mail = generate_mail(exception, env)
120
-
121
- mail.delivery_method(*@delivery_method) if @delivery_method
122
-
123
- mail.deliver
124
- rescue => mail_exception
125
- $stderr.puts mail_exception.to_s
126
- $stderr.puts mail_exception.backtrace
127
- end
128
-
129
- def extract_body(env)
130
- if io = env['rack.input']
131
- io.rewind if io.respond_to?(:rewind)
132
- io.read
133
- end
134
- end
135
- end
136
- end