rails-async 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+