rails-async 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/README.md +31 -7
- data/ROADMAP.md +0 -0
- data/Rakefile +17 -33
- data/app/controllers/async_controller.rb +1 -2
- data/app/helpers/async_helper.rb +8 -16
- data/app/models/async_cache.rb +37 -11
- data/init.rb +1 -0
- data/lib/async/engine.rb +0 -1
- data/lib/async/version.rb +3 -0
- data/rails-async.gemspec +90 -49
- data/test/helper.rb +11 -8
- data/test/rails_root/Gemfile +8 -0
- data/test/rails_root/README +256 -0
- data/test/rails_root/Rakefile +7 -0
- data/test/rails_root/app/controllers/application_controller.rb +8 -0
- data/test/rails_root/app/controllers/start_controller.rb +19 -0
- data/test/rails_root/app/helpers/application_helper.rb +2 -0
- data/test/rails_root/app/helpers/start_helper.rb +2 -0
- data/test/rails_root/app/views/layouts/application.html.erb +14 -0
- data/test/rails_root/app/views/start/_account.html.erb +1 -0
- data/test/rails_root/app/views/start/fast.html.erb +10 -0
- data/test/rails_root/app/views/start/fast_multi.html.erb +27 -0
- data/test/rails_root/app/views/start/index.html.erb +4 -0
- data/test/rails_root/app/views/start/slow.html.erb +8 -0
- data/test/rails_root/config.ru +4 -0
- data/test/rails_root/config/application.rb +42 -0
- data/test/rails_root/config/boot.rb +20 -0
- data/test/rails_root/config/database.yml +22 -0
- data/test/rails_root/config/environment.rb +5 -0
- data/test/rails_root/config/environments/development.rb +26 -0
- data/test/rails_root/config/environments/production.rb +49 -0
- data/test/rails_root/config/environments/test.rb +35 -0
- data/test/rails_root/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails_root/config/initializers/inflections.rb +10 -0
- data/test/rails_root/config/initializers/mime_types.rb +5 -0
- data/test/rails_root/config/initializers/secret_token.rb +7 -0
- data/test/rails_root/config/initializers/session_store.rb +8 -0
- data/test/rails_root/config/locales/en.yml +5 -0
- data/test/rails_root/config/routes.rb +63 -0
- data/test/rails_root/db/schema.rb +15 -0
- data/test/rails_root/doc/README_FOR_APP +2 -0
- data/test/rails_root/public/404.html +26 -0
- data/test/rails_root/public/422.html +26 -0
- data/test/rails_root/public/500.html +26 -0
- data/test/rails_root/public/favicon.ico +0 -0
- data/test/rails_root/public/images/rails.png +0 -0
- data/test/rails_root/public/images/spinner.gif +0 -0
- data/test/rails_root/public/javascripts/jquery.js +6883 -0
- data/test/rails_root/public/javascripts/rails.js +132 -0
- data/test/rails_root/public/robots.txt +5 -0
- data/test/rails_root/script/rails +6 -0
- data/test/rails_root/test/functional/start_controller_test.rb +19 -0
- data/test/rails_root/test/performance/browsing_test.rb +9 -0
- data/test/rails_root/test/test_helper.rb +15 -0
- data/test/rails_root/test/unit/helpers/start_helper_test.rb +4 -0
- data/test/test_async_cache.rb +16 -0
- metadata +110 -33
- data/.document +0 -5
- data/.gitignore +0 -21
- data/README.rdoc +0 -17
- data/VERSION +0 -1
- data/test/test_async-rails.rb +0 -7
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,20 +1,34 @@
|
|
1
|
-
|
1
|
+
A Rails engine that provides a view helper that will speed your page loads. See
|
2
|
+
the bottom of the README for the example use, that will probably make more sense
|
3
|
+
than me explaining it here.
|
2
4
|
|
3
|
-
|
5
|
+
This is Alpha, naive, itch scratching bozo code.
|
4
6
|
|
5
|
-
|
7
|
+
Don't reinvent the wheel. Always reinvent the wheel.
|
6
8
|
|
7
|
-
|
9
|
+
Ponder this, good luck.
|
8
10
|
|
9
|
-
|
11
|
+
## Install
|
10
12
|
|
11
|
-
|
13
|
+
Add it to your gemfile:
|
12
14
|
|
13
15
|
gem "rails-async", :require => "async"
|
14
16
|
|
15
17
|
## Setup
|
16
18
|
|
19
|
+
Add the following to your `app/controllers/application\_controller.rb`:
|
20
|
+
|
21
|
+
class ApplicationController < ActionController::Base
|
22
|
+
helper :async
|
23
|
+
after_filter do
|
24
|
+
Thread.new { AsyncCache.instance.build }
|
25
|
+
end
|
26
|
+
|
27
|
+
# ...
|
28
|
+
end
|
17
29
|
|
30
|
+
That's it. If you don't want it available on every request, add it to the
|
31
|
+
specific controllers where you intend to use it.
|
18
32
|
|
19
33
|
## Use
|
20
34
|
|
@@ -44,4 +58,14 @@ Fast page:
|
|
44
58
|
<% end %>
|
45
59
|
</ul>
|
46
60
|
|
47
|
-
|
61
|
+
Async worries about responding, you worry about why your code is so slow.
|
62
|
+
|
63
|
+
## Unanswered Questions
|
64
|
+
|
65
|
+
**Speed**: at what point is an approach like this worse than just rendering the
|
66
|
+
whole page at once? Gotta measure to know if you're improved anything.
|
67
|
+
|
68
|
+
**Practicality of testing**: what's the mimimum viable test rig?
|
69
|
+
|
70
|
+
**Praticality in general**: who's gonna use it? When would this be more useful
|
71
|
+
than manual ajax / async page splitting?
|
data/ROADMAP.md
ADDED
File without changes
|
data/Rakefile
CHANGED
@@ -1,46 +1,29 @@
|
|
1
|
+
ENV['BUNDLE_GEMFILE'] = File.dirname(__FILE__) + '/test/rails_root/Gemfile'
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
4
|
require 'rake'
|
3
5
|
|
4
|
-
begin
|
5
|
-
require 'jeweler'
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "rails-async"
|
8
|
-
gem.summary = %Q{Simple async blocks.}
|
9
|
-
gem.description = %Q{Don't wait for your pages to render.}
|
10
|
-
gem.email = "adam.bachman@gmail.com"
|
11
|
-
gem.homepage = "http://github.com/abachman/rails-async"
|
12
|
-
gem.authors = ["Adam Bachman"]
|
13
|
-
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
-
end
|
16
|
-
Jeweler::GemcutterTasks.new
|
17
|
-
rescue LoadError
|
18
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
-
end
|
20
|
-
|
21
6
|
require 'rake/testtask'
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
begin
|
29
|
-
require 'rcov/rcovtask'
|
30
|
-
Rcov::RcovTask.new do |test|
|
7
|
+
namespace :test do
|
8
|
+
Rake::TestTask.new(:basic => ["generator:cleanup",
|
9
|
+
"generator:async"]) do |test|
|
10
|
+
test.libs << 'lib'
|
31
11
|
test.libs << 'test'
|
32
|
-
test.pattern = 'test
|
12
|
+
test.pattern = 'test/test_*.rb'
|
33
13
|
test.verbose = true
|
34
14
|
end
|
35
|
-
rescue LoadError
|
36
|
-
task :rcov do
|
37
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
-
end
|
39
15
|
end
|
40
16
|
|
41
|
-
|
17
|
+
namespace :generator do
|
18
|
+
task :cleanup do
|
19
|
+
end
|
20
|
+
|
21
|
+
task :async do
|
22
|
+
system "cd test/rails_root && bundle install"
|
23
|
+
end
|
24
|
+
end
|
42
25
|
|
43
|
-
task :default => :
|
26
|
+
task :default => 'test:basic'
|
44
27
|
|
45
28
|
require 'rake/rdoctask'
|
46
29
|
Rake::RDocTask.new do |rdoc|
|
@@ -50,4 +33,5 @@ Rake::RDocTask.new do |rdoc|
|
|
50
33
|
rdoc.title = "rails-async #{version}"
|
51
34
|
rdoc.rdoc_files.include('README*')
|
52
35
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
36
|
+
rdoc.rdoc_files.include('app/**/*.rb')
|
53
37
|
end
|
data/app/helpers/async_helper.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
puts "HELPER"
|
2
1
|
module AsyncHelper
|
3
2
|
def asynchronously
|
4
3
|
id = Time.new.to_i
|
4
|
+
id = "#{ id }#{ AsyncCache.instance.counter }"
|
5
5
|
|
6
6
|
# insert javascript callback
|
7
7
|
safe_concat %{
|
@@ -19,21 +19,13 @@ module AsyncHelper
|
|
19
19
|
});
|
20
20
|
</script>
|
21
21
|
}
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
yield
|
30
|
-
end
|
31
|
-
AsyncCache.write(id, _content)
|
32
|
-
ensure
|
33
|
-
ActiveRecord::Base.remove_connection
|
34
|
-
end
|
22
|
+
|
23
|
+
AsyncCache.instance.schedule do
|
24
|
+
# anything rendered within capture will be stored in _content
|
25
|
+
_content = capture do
|
26
|
+
yield
|
27
|
+
end
|
28
|
+
AsyncCache.instance.write(id, _content)
|
35
29
|
end
|
36
|
-
ensure
|
37
|
-
ActiveRecord::Base.establish_connection((connection || {}).merge({:allow_concurrency => true}))
|
38
30
|
end
|
39
31
|
end
|
data/app/models/async_cache.rb
CHANGED
@@ -1,19 +1,45 @@
|
|
1
|
-
puts "MODEL"
|
2
1
|
class AsyncCache
|
3
|
-
|
2
|
+
include Singleton
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@@counter = 0
|
6
|
+
@@chunks = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def schedule(&block)
|
10
|
+
@@counter += 1
|
11
|
+
@@chunks << block
|
12
|
+
end
|
13
|
+
|
14
|
+
def counter
|
15
|
+
@@counter
|
16
|
+
end
|
17
|
+
|
18
|
+
def build
|
19
|
+
@@chunks.each {|chunk| chunk.call }
|
20
|
+
end
|
21
|
+
|
22
|
+
# since the async controller read request happens immediately on pages
|
23
|
+
# that use the `asynchronously do` block, the AsyncCache#read method
|
24
|
+
# has to block until the file it's looking for exists.
|
25
|
+
def read(tag)
|
4
26
|
@content = nil
|
5
|
-
|
6
|
-
|
7
|
-
|
27
|
+
begin
|
28
|
+
status = Timeout.timeout(10) do
|
29
|
+
until File.exists?(path(tag))
|
30
|
+
sleep 0.2
|
31
|
+
end
|
32
|
+
@content = File.read(path(tag))
|
8
33
|
end
|
9
|
-
|
34
|
+
rescue Timeout::Error
|
35
|
+
Rails.logger.error("\e[31mTimeout Error in AsyncCache\e[0m")
|
36
|
+
@content = ""
|
10
37
|
end
|
11
|
-
Rails.logger.debug("Returned from timeout with status #{ status.inspect }")
|
12
38
|
|
13
39
|
@content
|
14
40
|
end
|
15
41
|
|
16
|
-
def
|
42
|
+
def write(tag, content)
|
17
43
|
if !File.exists?(parent)
|
18
44
|
setup
|
19
45
|
end
|
@@ -24,15 +50,15 @@ class AsyncCache
|
|
24
50
|
end
|
25
51
|
|
26
52
|
private
|
27
|
-
def
|
53
|
+
def setup
|
28
54
|
FileUtils.mkdir_p parent
|
29
55
|
end
|
30
56
|
|
31
|
-
def
|
57
|
+
def parent
|
32
58
|
File.join(Rails.root, "tmp", "async")
|
33
59
|
end
|
34
60
|
|
35
|
-
def
|
61
|
+
def path tag
|
36
62
|
File.join(parent, tag.to_s)
|
37
63
|
end
|
38
64
|
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'async'
|
data/lib/async/engine.rb
CHANGED
data/rails-async.gemspec
CHANGED
@@ -1,60 +1,101 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
|
5
|
+
require 'async/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
8
|
+
s.name = %q{rails-async}
|
9
|
+
s.version = Async::VERSION
|
9
10
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors
|
12
|
-
s.date
|
13
|
-
s.
|
14
|
-
s.
|
15
|
-
s.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
s.authors = ["Adam Bachman"]
|
13
|
+
s.date = %q{2010-11-04}
|
14
|
+
s.summary = %q{Simple asynchronously loaded blocks in your Rails 3 views.}
|
15
|
+
s.description = %q{The Rails Async engine lets your controllers respond instantly.}
|
16
|
+
s.email = %q{adam.bachman@gmail.com}
|
17
|
+
s.homepage = %q{http://github.com/abachman/rails-async}
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.rubygems_version = %q{1.3.7}
|
20
|
+
|
21
|
+
s.files = Dir.glob("{bin,lib,app}/**/*") + %w(LICENSE README.md ROADMAP.md CHANGELOG.md)
|
20
22
|
s.files = [
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
"test/test_async-rails.rb"
|
36
|
-
]
|
37
|
-
s.homepage = %q{http://github.com/abachman/rails-async}
|
38
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
39
|
-
s.require_paths = ["lib"]
|
40
|
-
s.rubygems_version = %q{1.3.7}
|
41
|
-
s.summary = %q{Simple async blocks.}
|
42
|
-
s.test_files = [
|
43
|
-
"test/helper.rb",
|
44
|
-
"test/test_async-rails.rb"
|
23
|
+
'CHANGELOG.md',
|
24
|
+
'init.rb',
|
25
|
+
'LICENSE',
|
26
|
+
'README.md',
|
27
|
+
'ROADMAP.md',
|
28
|
+
'Rakefile',
|
29
|
+
'app/controllers/async_controller.rb',
|
30
|
+
'app/helpers/async_helper.rb',
|
31
|
+
'app/models/async_cache.rb',
|
32
|
+
'config/routes.rb',
|
33
|
+
'lib/async/engine.rb',
|
34
|
+
'lib/async/version.rb',
|
35
|
+
'lib/async.rb',
|
36
|
+
'rails-async.gemspec'
|
45
37
|
]
|
46
38
|
|
47
|
-
|
48
|
-
|
49
|
-
|
39
|
+
# require 'find'
|
40
|
+
# Find.find('test/rails_root') do |f|
|
41
|
+
# if (/\.bundle/ !~ f &&
|
42
|
+
# /tmp/ !~ f &&
|
43
|
+
# /log/ !~ f &&
|
44
|
+
# /seeds\.rb/ !~ f &&
|
45
|
+
# /\.sqlite/ !~ f &&
|
46
|
+
# /\.git/ !~ f &&
|
47
|
+
# !File.directory?(f))
|
48
|
+
# puts " '#{f}',"
|
49
|
+
# end
|
50
|
+
# end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
s.test_files = [
|
53
|
+
'test/helper.rb',
|
54
|
+
'test/test_async_cache.rb',
|
55
|
+
'test/rails_root/Gemfile',
|
56
|
+
'test/rails_root/README',
|
57
|
+
'test/rails_root/Rakefile',
|
58
|
+
'test/rails_root/app/controllers/application_controller.rb',
|
59
|
+
'test/rails_root/app/controllers/start_controller.rb',
|
60
|
+
'test/rails_root/app/helpers/application_helper.rb',
|
61
|
+
'test/rails_root/app/helpers/start_helper.rb',
|
62
|
+
'test/rails_root/app/views/layouts/application.html.erb',
|
63
|
+
'test/rails_root/app/views/start/_account.html.erb',
|
64
|
+
'test/rails_root/app/views/start/fast.html.erb',
|
65
|
+
'test/rails_root/app/views/start/fast_multi.html.erb',
|
66
|
+
'test/rails_root/app/views/start/index.html.erb',
|
67
|
+
'test/rails_root/app/views/start/slow.html.erb',
|
68
|
+
'test/rails_root/config.ru',
|
69
|
+
'test/rails_root/config/application.rb',
|
70
|
+
'test/rails_root/config/boot.rb',
|
71
|
+
'test/rails_root/config/database.yml',
|
72
|
+
'test/rails_root/config/environment.rb',
|
73
|
+
'test/rails_root/config/environments/development.rb',
|
74
|
+
'test/rails_root/config/environments/production.rb',
|
75
|
+
'test/rails_root/config/environments/test.rb',
|
76
|
+
'test/rails_root/config/initializers/backtrace_silencers.rb',
|
77
|
+
'test/rails_root/config/initializers/inflections.rb',
|
78
|
+
'test/rails_root/config/initializers/mime_types.rb',
|
79
|
+
'test/rails_root/config/initializers/secret_token.rb',
|
80
|
+
'test/rails_root/config/initializers/session_store.rb',
|
81
|
+
'test/rails_root/config/locales/en.yml',
|
82
|
+
'test/rails_root/config/routes.rb',
|
83
|
+
'test/rails_root/db/schema.rb',
|
84
|
+
'test/rails_root/doc/README_FOR_APP',
|
85
|
+
'test/rails_root/public/404.html',
|
86
|
+
'test/rails_root/public/422.html',
|
87
|
+
'test/rails_root/public/500.html',
|
88
|
+
'test/rails_root/public/favicon.ico',
|
89
|
+
'test/rails_root/public/images/rails.png',
|
90
|
+
'test/rails_root/public/images/spinner.gif',
|
91
|
+
'test/rails_root/public/javascripts/jquery.js',
|
92
|
+
'test/rails_root/public/javascripts/rails.js',
|
93
|
+
'test/rails_root/public/robots.txt',
|
94
|
+
'test/rails_root/script/rails',
|
95
|
+
'test/rails_root/test/functional/start_controller_test.rb',
|
96
|
+
'test/rails_root/test/performance/browsing_test.rb',
|
97
|
+
'test/rails_root/test/test_helper.rb',
|
98
|
+
'test/rails_root/test/unit/helpers/start_helper_test.rb',
|
99
|
+
]
|
59
100
|
end
|
60
101
|
|
data/test/helper.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
require File.expand_path(File.dirname(__FILE__) +
|
3
|
+
"/rails_root/config/environment")
|
4
|
+
require 'rails/test_help'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
require '
|
8
|
-
|
9
|
-
class Test::Unit::TestCase
|
6
|
+
require 'minitest/spec'
|
7
|
+
begin
|
8
|
+
require 'redgreen'
|
9
|
+
rescue LoadError
|
10
10
|
end
|
11
|
+
|
12
|
+
$: << File.expand_path(File.dirname(__FILE__) + '/..')
|
13
|
+
require 'async'
|