├── .gitignore ├── Gemfile ├── Gemfile.lock ├── README.md ├── Rakefile ├── app ├── assets │ ├── images │ │ └── rails.png │ ├── javascripts │ │ └── application.js │ └── stylesheets │ │ ├── .gitkeep │ │ └── application.css ├── controllers │ ├── application_controller.rb │ └── widgets_controller.rb ├── helpers │ └── application_helper.rb ├── metal │ └── twitter.rb ├── models │ └── widget.rb └── views │ └── layouts │ └── application.html.erb ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── backtrace_silencers.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── secret_token.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml └── routes.rb ├── db └── seeds.rb ├── doc └── README_FOR_APP ├── lib └── tasks │ └── .gitkeep ├── public ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico ├── index.html └── robots.txt ├── script └── rails ├── test ├── performance │ └── browsing_test.rb └── test_helper.rb └── vendor └── plugins └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | .bundle 2 | db/*.sqlite3 3 | log/*.log 4 | tmp/**/* 5 | *.swp 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://rubygems.org' 2 | 3 | gem 'rails', '3.1.0' 4 | gem 'sinatra' 5 | 6 | # Asset template engines 7 | gem 'sass-rails' 8 | gem 'coffee-script' 9 | gem 'uglifier' 10 | 11 | gem 'jquery-rails' 12 | 13 | # async wrappers 14 | gem 'eventmachine' 15 | gem 'rack-fiber_pool', :require => 'rack/fiber_pool' 16 | gem 'em-synchrony', :require => ['em-synchrony', 17 | 'em-synchrony/em-http', 18 | 'em-synchrony/activerecord'] 19 | 20 | # async activerecord requires 21 | gem 'mysql2' 22 | 23 | # async http requires 24 | gem 'em-http-request', :require => 'em-http' 25 | gem 'addressable', :require => 'addressable/uri' 26 | 27 | gem 'thin' 28 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: http://rubygems.org/ 3 | specs: 4 | actionmailer (3.1.0) 5 | actionpack (= 3.1.0) 6 | mail (~> 2.3.0) 7 | actionpack (3.1.0) 8 | activemodel (= 3.1.0) 9 | activesupport (= 3.1.0) 10 | builder (~> 3.0.0) 11 | erubis (~> 2.7.0) 12 | i18n (~> 0.6) 13 | rack (~> 1.3.2) 14 | rack-cache (~> 1.0.3) 15 | rack-mount (~> 0.8.2) 16 | rack-test (~> 0.6.1) 17 | sprockets (~> 2.0.0) 18 | activemodel (3.1.0) 19 | activesupport (= 3.1.0) 20 | bcrypt-ruby (~> 3.0.0) 21 | builder (~> 3.0.0) 22 | i18n (~> 0.6) 23 | activerecord (3.1.0) 24 | activemodel (= 3.1.0) 25 | activesupport (= 3.1.0) 26 | arel (~> 2.2.1) 27 | tzinfo (~> 0.3.29) 28 | activeresource (3.1.0) 29 | activemodel (= 3.1.0) 30 | activesupport (= 3.1.0) 31 | activesupport (3.1.0) 32 | multi_json (~> 1.0) 33 | addressable (2.2.6) 34 | arel (2.2.1) 35 | bcrypt-ruby (3.0.1) 36 | builder (3.0.4) 37 | coffee-script (2.2.0) 38 | coffee-script-source 39 | execjs 40 | coffee-script-source (1.1.2) 41 | concurrent-ruby (1.1.5) 42 | daemons (1.1.4) 43 | em-http-request (1.0.0) 44 | addressable (>= 2.2.3) 45 | em-socksify 46 | eventmachine (>= 1.0.0.beta.3) 47 | http_parser.rb (>= 0.5.2) 48 | em-socksify (0.1.0) 49 | eventmachine 50 | em-synchrony (1.0.0) 51 | eventmachine (>= 1.0.0.beta.1) 52 | erubis (2.7.0) 53 | eventmachine (1.0.0.beta.3) 54 | execjs (1.2.4) 55 | multi_json (~> 1.0) 56 | hike (1.2.3) 57 | http_parser.rb (0.5.2) 58 | i18n (0.9.5) 59 | concurrent-ruby (~> 1.0) 60 | jquery-rails (3.1.3) 61 | railties (>= 3.0, < 5.0) 62 | thor (>= 0.14, < 2.0) 63 | json (1.8.6) 64 | mail (2.3.0) 65 | i18n (>= 0.4.0) 66 | mime-types (~> 1.16) 67 | treetop (~> 1.4.8) 68 | mime-types (1.16) 69 | multi_json (1.14.1) 70 | mysql2 (0.3.7) 71 | polyglot (0.3.2) 72 | rack (1.3.10) 73 | rack-cache (1.0.3) 74 | rack (>= 0.4) 75 | rack-fiber_pool (0.9.2) 76 | rack-mount (0.8.3) 77 | rack (>= 1.0.0) 78 | rack-ssl (1.3.4) 79 | rack 80 | rack-test (0.6.3) 81 | rack (>= 1.0) 82 | rails (3.1.0) 83 | actionmailer (= 3.1.0) 84 | actionpack (= 3.1.0) 85 | activerecord (= 3.1.0) 86 | activeresource (= 3.1.0) 87 | activesupport (= 3.1.0) 88 | bundler (~> 1.0) 89 | railties (= 3.1.0) 90 | railties (3.1.0) 91 | actionpack (= 3.1.0) 92 | activesupport (= 3.1.0) 93 | rack-ssl (~> 1.3.2) 94 | rake (>= 0.8.7) 95 | rdoc (~> 3.4) 96 | thor (~> 0.14.6) 97 | rake (13.0.0) 98 | rdoc (3.12.2) 99 | json (~> 1.4) 100 | sass (3.1.7) 101 | sass-rails (3.1.0) 102 | actionpack (~> 3.1.0) 103 | railties (~> 3.1.0) 104 | sass (>= 3.1.4) 105 | sinatra (1.2.6) 106 | rack (~> 1.1) 107 | tilt (>= 1.2.2, < 2.0) 108 | sprockets (2.0.5) 109 | hike (~> 1.2) 110 | rack (~> 1.0) 111 | tilt (~> 1.1, != 1.3.0) 112 | thin (1.2.11) 113 | daemons (>= 1.0.9) 114 | eventmachine (>= 0.12.6) 115 | rack (>= 1.0.0) 116 | thor (0.14.6) 117 | tilt (1.4.1) 118 | treetop (1.4.10) 119 | polyglot 120 | polyglot (>= 0.3.1) 121 | tzinfo (0.3.29) 122 | uglifier (1.0.3) 123 | execjs (>= 0.3.0) 124 | multi_json (>= 1.0.2) 125 | 126 | PLATFORMS 127 | ruby 128 | 129 | DEPENDENCIES 130 | addressable 131 | coffee-script 132 | em-http-request 133 | em-synchrony 134 | eventmachine 135 | jquery-rails 136 | mysql2 137 | rack-fiber_pool 138 | rails (= 3.1.0) 139 | sass-rails 140 | sinatra 141 | thin 142 | uglifier 143 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Async Rails 3.1 stack demo 2 | 3 | Important warning: 4 | 5 | You should be aware when using fibers with Rails that you can get a stack overflow error if your stack grows 6 | bigger than 4Kb (which is enough for most things though), this got even worse with the 3.1 release in which 7 | you can easily overflow the stack, here is an example [here](https://github.com/schmurfy/assets_crash). 8 | 9 | Simple async demo stack with Rails 3.1 + EventMachine and Fibers. 10 | 11 | * Hit localhost:3000/widgets to do a 1s async mysql query 12 | * Hit localhost:3000/widgets/http to make an HTTP call back to /widgets - recursive! :-) 13 | * Hit localhost:3000/twitter to load a mounted async Sinatra app (reports latests rails 3 tweets) 14 | 15 | Howto / example commits: 16 | 17 | * Modify your config.ru to include the Rack::FiberPool middleware: [config.ru](https://github.com/igrigorik/async-rails/commit/72ea38433246cc58cd31e3863f4ed4e0c861ad28#config.ru) 18 | * Configure ActiveRecord to use async mysql driver: [Gemfile](https://github.com/igrigorik/async-rails/blob/master/Gemfile#L16), and [database.yml](https://github.com/igrigorik/async-rails/blob/master/config/database.yml#L4) 19 | * [Use async HTTP fetching within Rails](http://github.com/igrigorik/async-rails/commit/6307f3f416f21a40304d2f4a07509b923051744b) 20 | * [Mount async Sinatra app](http://github.com/igrigorik/async-rails/commit/50c5e4fd6701dfa2b3ecfc697ca53b40f8c57827) 21 | 22 | Requirements: 23 | 24 | * Ruby 1.9.x 25 | * Async app server (thin) 26 | * Rails 3.1 27 | 28 | Environment setup: 29 | 30 | * rvm install 1.9.2 31 | * rvm gemset create async-rails 32 | * rvm use 1.9.2@async-rails 33 | * gem install rails thin 34 | 35 | Starting up Rails: 36 | 37 | * bundle install 38 | * bundle exec thin -D start 39 | 40 | ## Concurrency 41 | 42 | ab -c 5 -n 10 http://127.0.0.1:3000/widgets/ 43 | 44 | Concurrency Level: 5 45 | Time taken for tests: 2.740 seconds 46 | Complete requests: 10 47 | 48 | We're running on a single reactor, so above is proof that we can execute HTTP+MySQL queries in non-blocking fashion on a single run loop / within single process: 49 | 50 | * AB opens 5 concurrent requests (10 total) 51 | * Each request to /widgets/http opens an async HTTP request to /widgets - aka, we ourselves spawn another 5 requests 52 | * Because the fiber pool is set to 10, it means we can process all 5 requests within ~1s (each mysql req takes 1s) 53 | * 10 requests finish in ~2s 54 | 55 | So, keep in mind that the size of 'database pool' is basically your concurrency throttle. In example above, we spawn 56 | 10 requests, which open another 10 internally, so in total we process 20 req's in ~2s on a single thing server. Just as expected. 57 | 58 | ## Benchmarks 59 | 60 | Pushing the stack on my MBP (db pool = 250; fiber pool = 250; env = production; thin 1.2.7) results in: 61 | 62 | Concurrency Level: 220 63 | Time taken for tests: 10.698 seconds 64 | Complete requests: 2000 65 | Failed requests: 0 66 | Write errors: 0 67 | Total transferred: 470235 bytes 68 | HTML transferred: 12006 bytes 69 | Requests per second: 186.95 [#/sec] (mean) 70 | Time per request: 1176.777 [ms] (mean) 71 | Time per request: 5.349 [ms] (mean, across all concurrent requests) 72 | Transfer rate: 42.93 [Kbytes/sec] received 73 | 74 | For full AB trace see [this gist](http://gist.github.com/503627) 75 | 76 | Resources: 77 | 78 | * [No callbacks, No threads - RailsConf 2010 Presentation](http://www.slideshare.net/igrigorik/no-callbacks-no-threads-railsconf-2010) 79 | * [Rails performance needs an overhaul](http://www.igvita.com/2010/06/07/rails-performance-needs-an-overhaul/) 80 | * [Non-blocking ActiveRecord](http://www.igvita.com/2010/04/15/non-blocking-activerecord-rails/) 81 | * [Untangling evented code with Ruby fibers](http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/) 82 | * [Introducing Phat, and Async Rails app](http://www.mikeperham.com/2010/04/03/introducing-phat-an-asynchronous-rails-app/) 83 | 84 | Other: 85 | 86 | * [Postgres + Async Rails driver](https://github.com/leftbee/em-postgresql-adapter) 87 | * [Fix: Asset Pipeline + Stack level too deep error](https://github.com/igrigorik/async-rails/wiki/Asset-Pipeline-+-Stack-Level-to-Deep) -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | require 'rake' 6 | 7 | AsyncRails3::Application.load_tasks 8 | -------------------------------------------------------------------------------- /app/assets/images/rails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igrigorik/async-rails/0d00f9baee66c0a81e313f8180187e76306848c2/app/assets/images/rails.png -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into including all the files listed below. 2 | // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically 3 | // be included in the compiled file accessible from http://example.com/assets/application.js 4 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 5 | // the compiled file. 6 | // 7 | //= require jquery 8 | //= require jquery_ujs 9 | //= require_tree . 10 | 11 | -------------------------------------------------------------------------------- /app/assets/stylesheets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igrigorik/async-rails/0d00f9baee66c0a81e313f8180187e76306848c2/app/assets/stylesheets/.gitkeep -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll automatically include all the stylesheets available in this directory 3 | * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at 4 | * the top of the compiled file, but it's generally better to create a new file per style scope. 5 | *= require_self 6 | *= require_tree . 7 | */ 8 | 9 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | protect_from_forgery 3 | layout 'application' 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/widgets_controller.rb: -------------------------------------------------------------------------------- 1 | class WidgetsController < ApplicationController 2 | def index 3 | Widget.find_by_sql("select sleep(1)") 4 | render :text => "Oh hai" 5 | end 6 | 7 | def http 8 | # going meta, query yourself, on the same thin server! 9 | http = EM::HttpRequest.new("http://#{request.host}:#{request.port}/widgets").get 10 | render :text => http.response 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/metal/twitter.rb: -------------------------------------------------------------------------------- 1 | class Twitter < Sinatra::Base 2 | get '/twitter' do 3 | http = EM::HttpRequest.new("http://search.twitter.com/search?q=rails+3&format=json").get 4 | tweets = ActiveSupport::JSON.decode(http.response) 5 | tweets = tweets['results'].collect {|t| t['text'] }.join("
") 6 | tweets 7 | end 8 | end -------------------------------------------------------------------------------- /app/models/widget.rb: -------------------------------------------------------------------------------- 1 | class Widget < ActiveRecord::Base 2 | end -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AsyncRails3 5 | <%= stylesheet_link_tag :all %> 6 | <%= javascript_include_tag :defaults %> 7 | <%= csrf_meta_tag %> 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | 5 | # include Rack::FiberPool in your stack and 6 | # set the number of fibers in the pool (100 is the current defaukt) 7 | use Rack::FiberPool, :size => 100 8 | run AsyncRails3::Application 9 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require 'rails/all' 4 | 5 | if defined?(Bundler) 6 | # If you precompile assets before deploying to production, use this line 7 | Bundler.require *Rails.groups(:assets => %w(development test)) 8 | # If you want your assets lazily compiled in production, use this line 9 | # Bundler.require(:default, :assets, Rails.env) 10 | end 11 | 12 | module AsyncRails3 13 | class Application < Rails::Application 14 | # Settings in config/environments/* take precedence over those specified here. 15 | # Application configuration should go into files in config/initializers 16 | # -- all .rb files in that directory are automatically loaded. 17 | 18 | # Custom directories with classes and modules you want to be autoloadable. 19 | # config.autoload_paths += %W(#{config.root}/extras) 20 | 21 | # Only load the plugins named here, in the order given (default is alphabetical). 22 | # :all can be used as a placeholder for all plugins not explicitly named. 23 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ] 24 | 25 | # Activate observers that should always be running. 26 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer 27 | 28 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 29 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 30 | # config.time_zone = 'Central Time (US & Canada)' 31 | 32 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 33 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 34 | # config.i18n.default_locale = :de 35 | 36 | # Configure the default encoding used in templates for Ruby 1.9. 37 | config.encoding = "utf-8" 38 | 39 | # Configure sensitive parameters which will be filtered from the log file. 40 | config.filter_parameters += [:password] 41 | 42 | # Enable the asset pipeline 43 | config.assets.enabled = true 44 | 45 | # Version of your assets, change this if you want to expire all your assets 46 | config.assets.version = '1.0' 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | 3 | # Set up gems listed in the Gemfile. 4 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 5 | 6 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) 7 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3-ruby (not necessary on OS X Leopard) 3 | development: 4 | adapter: em_mysql2 5 | database: widgets 6 | username: root 7 | pool: 250 8 | timeout: 5000 9 | 10 | # Warning: The database defined as "test" will be erased and 11 | # re-generated from your development database when you run "rake". 12 | # Do not set this db to the same as development or production. 13 | test: 14 | adapter: em_mysql2 15 | database: widgets_test 16 | username: root 17 | pool: 5 18 | timeout: 5000 19 | 20 | production: 21 | adapter: em_mysql2 22 | database: widgets 23 | username: root 24 | pool: 200 25 | timeout: 5000 26 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the rails application 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the rails application 5 | AsyncRails3::Application.initialize! 6 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | AsyncRails3::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Log error messages when you accidentally call methods on nil. 10 | config.whiny_nils = true 11 | 12 | # Show full error reports and disable caching 13 | config.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send 17 | config.action_mailer.raise_delivery_errors = false 18 | 19 | # Print deprecation notices to the Rails logger 20 | config.active_support.deprecation = :log 21 | 22 | # Only use best-standards-support built into browsers 23 | config.action_dispatch.best_standards_support = :builtin 24 | 25 | # Do not compress assets 26 | config.assets.compress = false 27 | 28 | 29 | # Enable threaded mode 30 | config.threadsafe! 31 | # Expands the lines which load the assets 32 | config.assets.debug = true 33 | end 34 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | AsyncRails3::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb 3 | 4 | # Code is not reloaded between requests 5 | config.cache_classes = true 6 | 7 | # Full error reports are disabled and caching is turned on 8 | config.consider_all_requests_local = false 9 | config.action_controller.perform_caching = true 10 | 11 | # Disable Rails's static asset server (Apache or nginx will already do this) 12 | config.serve_static_assets = false 13 | 14 | # Compress JavaScripts and CSS 15 | config.assets.compress = true 16 | 17 | # Don't fallback to assets pipeline if a precompiled asset is missed 18 | config.assets.compile = false 19 | 20 | # Generate digests for assets URLs 21 | config.assets.digest = true 22 | 23 | # Defaults to Rails.root.join("public/assets") 24 | # config.assets.manifest = YOUR_PATH 25 | 26 | # Specifies the header that your server uses for sending files 27 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache 28 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx 29 | 30 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 31 | # config.force_ssl = true 32 | 33 | # See everything in the log (default is :info) 34 | # config.log_level = :debug 35 | 36 | # Use a different logger for distributed setups 37 | # config.logger = SyslogLogger.new 38 | 39 | # Use a different cache store in production 40 | # config.cache_store = :mem_cache_store 41 | 42 | # Enable serving of images, stylesheets, and JavaScripts from an asset server 43 | # config.action_controller.asset_host = "http://assets.example.com" 44 | 45 | # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) 46 | # config.assets.precompile += %w( search.js ) 47 | 48 | # Disable delivery errors, bad email addresses will be ignored 49 | # config.action_mailer.raise_delivery_errors = false 50 | 51 | # Enable threaded mode 52 | config.threadsafe! 53 | 54 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 55 | # the I18n.default_locale when a translation can not be found) 56 | config.i18n.fallbacks = true 57 | 58 | # Send deprecation notices to registered listeners 59 | config.active_support.deprecation = :notify 60 | end 61 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | AsyncRails3::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Configure static asset server for tests with Cache-Control for performance 11 | config.serve_static_assets = true 12 | config.static_cache_control = "public, max-age=3600" 13 | 14 | # Log error messages when you accidentally call methods on nil 15 | config.whiny_nils = true 16 | 17 | # Show full error reports and disable caching 18 | config.consider_all_requests_local = true 19 | config.action_controller.perform_caching = false 20 | 21 | # Raise exceptions instead of rendering exception templates 22 | config.action_dispatch.show_exceptions = false 23 | 24 | # Disable request forgery protection in test environment 25 | config.action_controller.allow_forgery_protection = false 26 | 27 | # Tell Action Mailer not to deliver emails to the real world. 28 | # The :test delivery method accumulates sent emails in the 29 | # ActionMailer::Base.deliveries array. 30 | config.action_mailer.delivery_method = :test 31 | 32 | # Use SQL instead of Active Record's schema dumper when creating the test database. 33 | # This is necessary if your schema can't be completely dumped by the schema dumper, 34 | # like if you have constraints or database-specific column types 35 | # config.active_record.schema_format = :sql 36 | 37 | # Print deprecation notices to the stderr 38 | config.active_support.deprecation = :stderr 39 | 40 | # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets 41 | config.assets.allow_debugging = true 42 | end 43 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format 4 | # (all these examples are active by default): 5 | # ActiveSupport::Inflector.inflections do |inflect| 6 | # inflect.plural /^(ox)$/i, '\1en' 7 | # inflect.singular /^(ox)en/i, '\1' 8 | # inflect.irregular 'person', 'people' 9 | # inflect.uncountable %w( fish sheep ) 10 | # end 11 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | # Mime::Type.register_alias "text/html", :iphone 6 | -------------------------------------------------------------------------------- /config/initializers/secret_token.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | # Make sure the secret is at least 30 characters and all random, 6 | # no regular words or you'll be exposed to dictionary attacks. 7 | AsyncRails3::Application.config.secret_token = 'a045a3603aec7f70137302189d266905797bd1a43411cde33496a2c0de0fd925110050e25918127d56d51aadab2cd5f0288f4d2cfe67b7dec80db94e8c00a007' 8 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | AsyncRails3::Application.config.session_store :cookie_store, key: '_async_rails3_session' 4 | 5 | # Use the database for sessions instead of the cookie-based default, 6 | # which shouldn't be used to store highly confidential information 7 | # (create the session table with "rails generate session_migration") 8 | # AsyncRails3::Application.config.session_store :active_record_store 9 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | # 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # Disable root element in JSON by default. 12 | ActiveSupport.on_load(:active_record) do 13 | self.include_root_in_json = false 14 | end 15 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Sample localization file for English. Add more files in this directory for other locales. 2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. 3 | 4 | en: 5 | hello: "Hello world" 6 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | AsyncRails3::Application.routes.draw do 2 | # The priority is based upon order of creation: 3 | # first created -> highest priority. 4 | 5 | # Sample of regular route: 6 | # match 'products/:id' => 'catalog#view' 7 | # Keep in mind you can assign values other than :controller and :action 8 | 9 | # Sample of named route: 10 | # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase 11 | # This route can be invoked with purchase_url(:id => product.id) 12 | 13 | # Sample resource route (maps HTTP verbs to controller actions automatically): 14 | # resources :products 15 | 16 | # Sample resource route with options: 17 | # resources :products do 18 | # member do 19 | # get 'short' 20 | # post 'toggle' 21 | # end 22 | # 23 | # collection do 24 | # get 'sold' 25 | # end 26 | # end 27 | 28 | # Sample resource route with sub-resources: 29 | # resources :products do 30 | # resources :comments, :sales 31 | # resource :seller 32 | # end 33 | 34 | # Sample resource route with more complex sub-resources 35 | # resources :products do 36 | # resources :comments 37 | # resources :sales do 38 | # get 'recent', :on => :collection 39 | # end 40 | # end 41 | 42 | # Sample resource route within a namespace: 43 | # namespace :admin do 44 | # # Directs /admin/products/* to Admin::ProductsController 45 | # # (app/controllers/admin/products_controller.rb) 46 | # resources :products 47 | # end 48 | 49 | # You can have the root of your site routed with "root" 50 | # just remember to delete public/index.html. 51 | # root :to => 'welcome#index' 52 | 53 | # See how all your routes lay out with "rake routes" 54 | 55 | # This is a legacy wild controller route that's not recommended for RESTful applications. 56 | # Note: This route will make all actions in every controller accessible via GET requests. 57 | 58 | # mount async sinatra app (in metal folder) 59 | match '/twitter', :to => Twitter 60 | 61 | match ':controller(/:action(/:id(.:format)))' 62 | end 63 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) 7 | # Mayor.create(:name => 'Daley', :city => cities.first) 8 | -------------------------------------------------------------------------------- /doc/README_FOR_APP: -------------------------------------------------------------------------------- 1 | Use this README file to introduce your application and point to useful places in the API for learning more. 2 | Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. 3 | -------------------------------------------------------------------------------- /lib/tasks/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igrigorik/async-rails/0d00f9baee66c0a81e313f8180187e76306848c2/lib/tasks/.gitkeep -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

The page you were looking for doesn't exist.

23 |

You may have mistyped the address or the page may have moved.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

The change you wanted was rejected.

23 |

Maybe you tried to change something you didn't have access to.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

We're sorry, but something went wrong.

23 |

We've been notified about this issue and we'll take a look at it shortly.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igrigorik/async-rails/0d00f9baee66c0a81e313f8180187e76306848c2/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ruby on Rails: Welcome aboard 5 | 185 | 208 | 209 | 210 |
211 | 241 | 242 |
243 | 247 | 248 | 252 | 253 |
254 |

Getting started

255 |

Here’s how to get rolling:

256 | 257 |
    258 |
  1. 259 |

    Use rails generate to create your models and controllers

    260 |

    To see all available options, run it without parameters.

    261 |
  2. 262 | 263 |
  3. 264 |

    Set up a default route and remove or rename this file

    265 |

    Routes are set up in config/routes.rb.

    266 |
  4. 267 | 268 |
  5. 269 |

    Create your database

    270 |

    Run rake db:migrate to create your database. If you're not using SQLite (the default), edit config/database.yml with your username and password.

    271 |
  6. 272 |
273 |
274 |
275 | 276 | 277 |
278 | 279 | 280 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-Agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | APP_PATH = File.expand_path('../../config/application', __FILE__) 5 | require File.expand_path('../../config/boot', __FILE__) 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /test/performance/browsing_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'rails/performance_test_help' 3 | 4 | # Profiling results for each test method are written to tmp/performance. 5 | class BrowsingTest < ActionDispatch::PerformanceTest 6 | def test_homepage 7 | get '/' 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV["RAILS_ENV"] = "test" 2 | require File.expand_path('../../config/environment', __FILE__) 3 | require 'rails/test_help' 4 | 5 | class ActiveSupport::TestCase 6 | # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. 7 | # 8 | # Note: You'll currently still have to declare fixtures explicitly in integration tests 9 | # -- they do not yet inherit this setting 10 | fixtures :all 11 | 12 | # Add more helper methods to be used by all tests here... 13 | end 14 | -------------------------------------------------------------------------------- /vendor/plugins/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igrigorik/async-rails/0d00f9baee66c0a81e313f8180187e76306848c2/vendor/plugins/.gitkeep --------------------------------------------------------------------------------