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.
Files changed (63) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/README.md +31 -7
  3. data/ROADMAP.md +0 -0
  4. data/Rakefile +17 -33
  5. data/app/controllers/async_controller.rb +1 -2
  6. data/app/helpers/async_helper.rb +8 -16
  7. data/app/models/async_cache.rb +37 -11
  8. data/init.rb +1 -0
  9. data/lib/async/engine.rb +0 -1
  10. data/lib/async/version.rb +3 -0
  11. data/rails-async.gemspec +90 -49
  12. data/test/helper.rb +11 -8
  13. data/test/rails_root/Gemfile +8 -0
  14. data/test/rails_root/README +256 -0
  15. data/test/rails_root/Rakefile +7 -0
  16. data/test/rails_root/app/controllers/application_controller.rb +8 -0
  17. data/test/rails_root/app/controllers/start_controller.rb +19 -0
  18. data/test/rails_root/app/helpers/application_helper.rb +2 -0
  19. data/test/rails_root/app/helpers/start_helper.rb +2 -0
  20. data/test/rails_root/app/views/layouts/application.html.erb +14 -0
  21. data/test/rails_root/app/views/start/_account.html.erb +1 -0
  22. data/test/rails_root/app/views/start/fast.html.erb +10 -0
  23. data/test/rails_root/app/views/start/fast_multi.html.erb +27 -0
  24. data/test/rails_root/app/views/start/index.html.erb +4 -0
  25. data/test/rails_root/app/views/start/slow.html.erb +8 -0
  26. data/test/rails_root/config.ru +4 -0
  27. data/test/rails_root/config/application.rb +42 -0
  28. data/test/rails_root/config/boot.rb +20 -0
  29. data/test/rails_root/config/database.yml +22 -0
  30. data/test/rails_root/config/environment.rb +5 -0
  31. data/test/rails_root/config/environments/development.rb +26 -0
  32. data/test/rails_root/config/environments/production.rb +49 -0
  33. data/test/rails_root/config/environments/test.rb +35 -0
  34. data/test/rails_root/config/initializers/backtrace_silencers.rb +7 -0
  35. data/test/rails_root/config/initializers/inflections.rb +10 -0
  36. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  37. data/test/rails_root/config/initializers/secret_token.rb +7 -0
  38. data/test/rails_root/config/initializers/session_store.rb +8 -0
  39. data/test/rails_root/config/locales/en.yml +5 -0
  40. data/test/rails_root/config/routes.rb +63 -0
  41. data/test/rails_root/db/schema.rb +15 -0
  42. data/test/rails_root/doc/README_FOR_APP +2 -0
  43. data/test/rails_root/public/404.html +26 -0
  44. data/test/rails_root/public/422.html +26 -0
  45. data/test/rails_root/public/500.html +26 -0
  46. data/test/rails_root/public/favicon.ico +0 -0
  47. data/test/rails_root/public/images/rails.png +0 -0
  48. data/test/rails_root/public/images/spinner.gif +0 -0
  49. data/test/rails_root/public/javascripts/jquery.js +6883 -0
  50. data/test/rails_root/public/javascripts/rails.js +132 -0
  51. data/test/rails_root/public/robots.txt +5 -0
  52. data/test/rails_root/script/rails +6 -0
  53. data/test/rails_root/test/functional/start_controller_test.rb +19 -0
  54. data/test/rails_root/test/performance/browsing_test.rb +9 -0
  55. data/test/rails_root/test/test_helper.rb +15 -0
  56. data/test/rails_root/test/unit/helpers/start_helper_test.rb +4 -0
  57. data/test/test_async_cache.rb +16 -0
  58. metadata +110 -33
  59. data/.document +0 -5
  60. data/.gitignore +0 -21
  61. data/README.rdoc +0 -17
  62. data/VERSION +0 -1
  63. data/test/test_async-rails.rb +0 -7
@@ -0,0 +1,5 @@
1
+ ### 0.1.1
2
+
3
+ * use threads instead of forks
4
+ * require library users to include an `after\_filter` in their application controller
5
+ * fix id bug that occurs when multiple `asynchronously do` blocks are created on the same page.
data/README.md CHANGED
@@ -1,20 +1,34 @@
1
- This is Alpha, naive, itch scratching bozo code.
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
- Good luck.
5
+ This is Alpha, naive, itch scratching bozo code.
4
6
 
5
- ## Install
7
+ Don't reinvent the wheel. Always reinvent the wheel.
6
8
 
7
- Get the gem:
9
+ Ponder this, good luck.
8
10
 
9
- gem install rails-async
11
+ ## Install
10
12
 
11
- Or add it to your gemfile:
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?
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
- Rake::TestTask.new(:test) do |test|
23
- test.libs << 'lib' << 'test'
24
- test.pattern = 'test/**/test_*.rb'
25
- test.verbose = true
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/**/test_*.rb'
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
- task :test => :check_dependencies
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 => :test
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
@@ -1,7 +1,6 @@
1
- puts "CONTROLLER"
2
1
  class AsyncController < ApplicationController
3
2
  def show
4
- @as_cache = AsyncCache.read(params[:tag])
3
+ @as_cache = AsyncCache.instance.read(params[:tag])
5
4
  render :json => {:content => @as_cache}
6
5
  end
7
6
  end
@@ -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
- connection = ActiveRecord::Base.remove_connection
24
- child = Process.fork do
25
- begin
26
- ActiveRecord::Base.establish_connection((connection || {}).merge({:allow_concurrency => true})) if defined?(ActiveRecord)
27
- # anything rendered within capture will be stored in _content
28
- _content = capture do
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
@@ -1,19 +1,45 @@
1
- puts "MODEL"
2
1
  class AsyncCache
3
- def self.read(tag)
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
- status = Timeout.timeout(5) do
6
- until File.exists?(path(tag))
7
- sleep 0.2
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
- @content = File.read(path(tag))
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 self.write(tag, content)
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 self.setup
53
+ def setup
28
54
  FileUtils.mkdir_p parent
29
55
  end
30
56
 
31
- def self.parent
57
+ def parent
32
58
  File.join(Rails.root, "tmp", "async")
33
59
  end
34
60
 
35
- def self.path tag
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'
@@ -5,6 +5,5 @@ require 'async'
5
5
 
6
6
  module Async
7
7
  class Engine < Rails::Engine
8
- engine_name :async
9
8
  end
10
9
  end
@@ -0,0 +1,3 @@
1
+ module Async
2
+ VERSION = "0.1.1"
3
+ end
@@ -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 = %q{rails-async}
8
- s.version = "0.1.0"
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 = ["Adam Bachman"]
12
- s.date = %q{2010-09-19}
13
- s.description = %q{Don't wait for your pages to render.}
14
- s.email = %q{adam.bachman@gmail.com}
15
- s.extra_rdoc_files = [
16
- "LICENSE",
17
- "README.md",
18
- "README.rdoc"
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
- ".document",
22
- ".gitignore",
23
- "LICENSE",
24
- "README.rdoc",
25
- "Rakefile",
26
- "VERSION",
27
- "app/controllers/async_controller.rb",
28
- "app/helpers/async_helper.rb",
29
- "app/models/async_cache.rb",
30
- "config/routes.rb",
31
- "lib/async.rb",
32
- "lib/async/engine.rb",
33
- "rails-async.gemspec",
34
- "test/helper.rb",
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
- if s.respond_to? :specification_version then
48
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
- s.specification_version = 3
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
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
- s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
53
- else
54
- s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
55
- end
56
- else
57
- s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
58
- end
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
 
@@ -1,10 +1,13 @@
1
- require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
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
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
- $LOAD_PATH.unshift(File.dirname(__FILE__))
7
- require 'async-rails'
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'
@@ -0,0 +1,8 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rails', '3.0.0'
4
+ gem 'rails-async', :require => 'async', :path => '/home/adam/projects/rails-async'
5
+ gem 'sqlite3-ruby', :require => 'sqlite3'
6
+ gem 'minitest'
7
+ gem 'redgreen'
8
+