aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG2
-rw-r--r--railties/guides/source/action_controller_overview.textile22
-rw-r--r--railties/guides/source/active_record_querying.textile56
-rw-r--r--railties/guides/source/active_record_validations_callbacks.textile2
-rw-r--r--railties/guides/source/configuring.textile3
-rw-r--r--railties/guides/source/routing.textile12
-rw-r--r--railties/guides/source/security.textile6
-rw-r--r--railties/guides/source/testing.textile4
-rw-r--r--railties/lib/rails/application.rb17
-rw-r--r--railties/lib/rails/application/configuration.rb3
-rw-r--r--railties/lib/rails/engine.rb4
-rw-r--r--railties/lib/rails/generators/app_base.rb39
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt18
-rw-r--r--railties/railties.gemspec1
-rw-r--r--railties/test/application/middleware_test.rb6
-rw-r--r--railties/test/railties/engine_test.rb39
17 files changed, 198 insertions, 38 deletions
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index 75f1df44e7..c1e0a214d2 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,5 +1,7 @@
*Rails 3.1.0 (unreleased)*
+* Added `config.force_ssl` configuration which loads Rack::SSL middleware and force all requests to be under HTTPS protocol [DHH, Prem Sichanugrist, and Josh Peek]
+
* Added `rails plugin new` command which generates rails plugin with gemspec, tests and dummy application for testing [Piotr Sarnacki]
* Added -j parameter with jquery/prototype as options. Now you can create your apps with jQuery using `rails new myapp -j jquery`. The default is still Prototype. [siong1987]
diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile
index ecb03a48e4..178d98c2d6 100644
--- a/railties/guides/source/action_controller_overview.textile
+++ b/railties/guides/source/action_controller_overview.textile
@@ -816,6 +816,28 @@ end
NOTE: Certain exceptions are only rescuable from the +ApplicationController+ class, as they are raised before the controller gets initialized and the action gets executed. See Pratik Naik's "article":http://m.onkey.org/2008/7/20/rescue-from-dispatching on the subject for more information.
+h3. Force HTTPS protocol
+
+Sometime you might want to force a particular controller to only be accessible via an HTTPS protocol for security reason. Since Rails 3.1 you can now use +force_ssl+ method in your controller to enforce that:
+
+<ruby>
+class DinnerController
+ force_ssl
+end
+</ruby>
+
+Just like the filter, you could also passing +:only+ and +:except+ to enforce the secure connection only to specific actions
+
+<ruby>
+class DinnerController
+ force_ssl :only => :cheeseburger
+ # or
+ force_ssl :except => :cheeseburger
+end
+</ruby>
+
+Please note that if you found yourself adding +force_ssl+ to many controllers, you may found yourself wanting to force the whole application to use HTTPS instead. In that case, you can set the +config.force_ssl+ in your environment file.
+
h3. Changelog
* February 17, 2009: Yet another proofread by Xavier Noria.
diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile
index 009d541106..f3a10b8b92 100644
--- a/railties/guides/source/active_record_querying.textile
+++ b/railties/guides/source/active_record_querying.textile
@@ -76,7 +76,7 @@ Primary operation of <tt>Model.find(options)</tt> can be summarized as:
h4. Retrieving a Single Object
-Active Record lets you retrieve a single object using three different ways.
+Active Record lets you retrieve a single object using five different ways.
h5. Using a Primary Key
@@ -130,6 +130,40 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
<tt>Model.last</tt> returns +nil+ if no matching record is found. No exception will be raised.
+h5. +first!+
+
+<tt>Model.first!</tt> finds the first record. For example:
+
+<ruby>
+client = Client.first!
+=> #<Client id: 1, first_name: "Lifo">
+</ruby>
+
+SQL equivalent of the above is:
+
+<sql>
+SELECT * FROM clients LIMIT 1
+</sql>
+
+<tt>Model.first!</tt> raises +RecordNotFound+ if no matching record is found.
+
+h5. +last!+
+
+<tt>Model.last!</tt> finds the last record. For example:
+
+<ruby>
+client = Client.last!
+=> #<Client id: 221, first_name: "Russel">
+</ruby>
+
+SQL equivalent of the above is:
+
+<sql>
+SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
+</sql>
+
+<tt>Model.last!</tt> raises +RecordNotFound+ if no matching record is found.
+
h4. Retrieving Multiple Objects
h5. Using Multiple Primary Keys
@@ -928,6 +962,26 @@ Client.exists?
The above returns +false+ if the +clients+ table is empty and +true+ otherwise.
+You can also use +any?+ and +many?+ to check for existence on a model or relation.
+
+<ruby>
+# via a model
+Post.any?
+Post.many?
+
+# via a named scope
+Post.recent.any?
+Post.recent.many?
+
+# via a relation
+Post.where(:published => true).any?
+Post.where(:published => true).many?
+
+# via an association
+Post.first.categories.any?
+Post.first.categories.many?
+</ruby>
+
h3. Calculations
This section uses count as an example method in this preamble, but the options described apply to all sub-sections.
diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile
index e5349d546c..514d0322b9 100644
--- a/railties/guides/source/active_record_validations_callbacks.textile
+++ b/railties/guides/source/active_record_validations_callbacks.textile
@@ -84,6 +84,7 @@ The following methods skip validations, and will save the object to the database
* +toggle!+
* +update_all+
* +update_attribute+
+* +update_column+
* +update_counters+
Note that +save+ also has the ability to skip validations if passed +:validate => false+ as argument. This technique should be used with caution.
@@ -993,6 +994,7 @@ Just as with validations, it's also possible to skip callbacks. These methods sh
* +increment+
* +increment_counter+
* +toggle+
+* +update_column+
* +update_all+
* +update_counters+
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 62b846e871..298335d484 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -81,6 +81,8 @@ end
* +config.filter_parameters+ used for filtering out the parameters that you don't want shown in the logs, such as passwords or credit card numbers.
+* +config.force_ssl+ forcing all requests to be under HTTPS protocol by using +Rack::SSL+ middleware. This will secure your application from a session hijack attempt.
+
* +config.helper_paths+ configures where Rails can find helpers for this application.
* +config.log_level+ defines the verbosity of the Rails logger. In production mode, this defaults to +:info+. In development mode, it defaults to +:debug+.
@@ -147,6 +149,7 @@ h4. Configuring Middleware
Every Rails application comes with a standard set of middleware which it uses in this order in the development environment:
+* +Rack::SSL+ Will force every requests to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to _true_.
* +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is _true_.
* +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to _false_, which it is by default.
* +ActiveSupport::Cache::Strategy::LocalCache+ Serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.
diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile
index c447fd911a..58b75b9a1d 100644
--- a/railties/guides/source/routing.textile
+++ b/railties/guides/source/routing.textile
@@ -557,6 +557,18 @@ match '*a/foo/*b' => 'test#index'
would match +zoo/woo/foo/bar/baz+ with +params[:a]+ equals +"zoo/woo"+, and +params[:b]+ equals +"bar/baz"+.
+NOTE: Starting from Rails 3.1, wildcard route will always matching the optional format segment by default. For example if you have this route:
+
+<ruby>
+map '*pages' => 'pages#show'
+</ruby>
+
+NOTE: By requesting +"/foo/bar.json"+, your +params[:pages]+ will be equals to +"foo/bar"+ with the request format of JSON. If you want the old 3.0.x behavior back, you could supply +:format => false+ like this:
+
+<ruby>
+map '*pages' => 'pages#show', :format => false
+</ruby>
+
h4. Redirection
You can redirect any path to another path using the +redirect+ helper in your router:
diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile
index 182f3631ef..893f65856c 100644
--- a/railties/guides/source/security.textile
+++ b/railties/guides/source/security.textile
@@ -57,7 +57,11 @@ Many web applications have an authentication system: a user provides a user name
Hence, the cookie serves as temporary authentication for the web application. Everyone who seizes a cookie from someone else, may use the web application as this user – with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures:
-* Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _(highlight)provide a secure connection over SSL_.
+* Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _(highlight)provide a secure connection over SSL_. In Rails 3.1 and later, this could be accomplished by always forcing SSL connection in your application config file:
+
+<ruby>
+config.force_ssl = true
+</ruby>
* Most people don't clear out the cookies after working at a public terminal. So if the last user didn't log out of a web application, you would be able to use it as this user. Provide the user with a _(highlight)log-out button_ in the web application, and _(highlight)make it prominent_.
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index 4ebdb3edf6..d3f72509c6 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -81,7 +81,7 @@ Each fixture is given a name followed by an indented list of colon-separated key
h5. ERb'in It Up
-ERb allows you embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERb when you load fixtures. This allows you to use Ruby to help you generate some sample data.
+ERb allows you to embed ruby code within templates. Both the YAML and CSV fixture formats are pre-processed with ERb when you load fixtures. This allows you to use Ruby to help you generate some sample data.
<erb>
<% earth_size = 20 %>
@@ -227,7 +227,7 @@ $ rake db:migrate
$ rake db:test:load
</shell>
-Above +rake db:migrate+ runs any pending migrations on the _development_ environment and updates +db/schema.rb+. +rake db:test:load+ recreates the test database from the current +db/schema.rb+. On subsequent attempts, it is a good idea to first run +db:test:prepare+, as it first checks for pending migrations and warns you appropriately.
+The +rake db:migrate+ above runs any pending migrations on the _development_ environment and updates +db/schema.rb+. The +rake db:test:load+ recreates the test database from the current +db/schema.rb+. On subsequent attempts, it is a good idea to first run +db:test:prepare+, as it first checks for pending migrations and warns you appropriately.
NOTE: +db:test:prepare+ will fail with an error if +db/schema.rb+ doesn't exist.
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 754b03258a..5b8841fd97 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -174,15 +174,21 @@ module Rails
def default_middleware_stack
ActionDispatch::MiddlewareStack.new.tap do |middleware|
- rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache
+ if rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache
+ require "action_dispatch/http/rack_cache"
+ middleware.use ::Rack::Cache, rack_cache
+ end
- require "action_dispatch/http/rack_cache" if rack_cache
- middleware.use ::Rack::Cache, rack_cache if rack_cache
+ if config.force_ssl
+ require "rack/ssl"
+ middleware.use ::Rack::SSL
+ end
if config.serve_static_assets
asset_paths = ActiveSupport::OrderedHash[config.static_asset_paths.to_a.reverse]
middleware.use ::ActionDispatch::Static, asset_paths
end
+
middleware.use ::Rack::Lock unless config.allow_concurrency
middleware.use ::Rack::Runtime
middleware.use ::Rails::Rack::Logger
@@ -203,7 +209,10 @@ module Rails
middleware.use ::ActionDispatch::Head
middleware.use ::Rack::ConditionalGet
middleware.use ::Rack::ETag, "no-cache"
- middleware.use ::ActionDispatch::BestStandardsSupport, config.action_dispatch.best_standards_support if config.action_dispatch.best_standards_support
+
+ if config.action_dispatch.best_standards_support
+ middleware.use ::ActionDispatch::BestStandardsSupport, config.action_dispatch.best_standards_support
+ end
end
end
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 9e87714e4f..4ec5336f6c 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -9,7 +9,7 @@ module Rails
:filter_parameters, :helpers_paths, :logger,
:preload_frameworks, :reload_plugins,
:secret_token, :serve_static_assets, :session_options,
- :time_zone, :whiny_nils,
+ :time_zone, :whiny_nils, :force_ssl,
:asset_pipeline, :precompile_assets
attr_writer :log_level
@@ -23,6 +23,7 @@ module Rails
@helpers_paths = []
@dependency_loading = true
@serve_static_assets = true
+ @force_ssl = false
@session_store = :cookie_store
@session_options = {}
@time_zone = "UTC"
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 4fc23fe277..ee265366ff 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -360,11 +360,11 @@ module Rails
def isolate_namespace(mod)
engine_name(generate_railtie_name(mod))
- name = engine_name
- self.routes.default_scope = {:module => name}
+ self.routes.default_scope = { :module => ActiveSupport::Inflector.underscore(mod.name) }
self.isolated = true
unless mod.respond_to?(:_railtie)
+ name = engine_name
_railtie = self
mod.singleton_class.instance_eval do
define_method(:_railtie) do
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index ab7ed4eb9e..a2eaf7a6fb 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -1,5 +1,6 @@
require 'digest/md5'
require 'active_support/secure_random'
+require 'active_support/core_ext/string/strip'
require 'rails/version' unless defined?(Rails::VERSION)
require 'rbconfig'
require 'open-uri'
@@ -112,30 +113,38 @@ module Rails
end
def database_gemfile_entry
- options[:skip_active_record] ? "" : "gem '#{gem_for_database}'"
+ entry = options[:skip_active_record] ? "" : "gem '#{gem_for_database}'"
+ if options[:database] == 'mysql'
+ if options.dev? || options.edge?
+ entry += ", :git => 'git://github.com/brianmario/mysql2.git'"
+ else
+ entry += "\n# gem 'mysql2', :git => 'git://github.com/brianmario/mysql2.git'"
+ end
+ end
+ entry
end
def rails_gemfile_entry
if options.dev?
- <<-GEMFILE
-gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}'
-gem 'arel', :git => 'git://github.com/rails/arel.git'
-gem "rack", :git => "git://github.com/rack/rack.git"
+ <<-GEMFILE.strip_heredoc
+ gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}'
+ gem 'arel', :git => 'git://github.com/rails/arel.git'
+ gem 'rack', :git => 'git://github.com/rack/rack.git'
GEMFILE
elsif options.edge?
- <<-GEMFILE
-gem 'rails', :git => 'git://github.com/rails/rails.git'
-gem 'arel', :git => 'git://github.com/rails/arel.git'
-gem "rack", :git => "git://github.com/rack/rack.git"
+ <<-GEMFILE.strip_heredoc
+ gem 'rails', :git => 'git://github.com/rails/rails.git'
+ gem 'arel', :git => 'git://github.com/rails/arel.git'
+ gem 'rack', :git => 'git://github.com/rack/rack.git'
GEMFILE
else
- <<-GEMFILE
-gem 'rails', '#{Rails::VERSION::STRING}'
+ <<-GEMFILE.strip_heredoc
+ gem 'rails', '#{Rails::VERSION::STRING}'
-# Bundle edge Rails instead:
-# gem 'rails', :git => 'git://github.com/rails/rails.git'
-# gem 'arel', :git => 'git://github.com/rails/arel.git'
-# gem "rack", :git => "git://github.com/rack/rack.git"
+ # Bundle edge Rails instead:
+ # gem 'rails', :git => 'git://github.com/rails/rails.git'
+ # gem 'arel', :git => 'git://github.com/rails/arel.git'
+ # gem 'rack', :git => 'git://github.com/rack/rack.git'
GEMFILE
end
end
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
index 91d3133ea4..bdb897ad33 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
@@ -3,7 +3,7 @@
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
- # since you don't have to restart the webserver when you make code changes.
+ # since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
index 89bb891ddd..874cc403ba 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
@@ -1,7 +1,6 @@
<%= app_const %>.configure do
# Settings specified here will take precedence over those in config/application.rb
- # The production environment is meant for finished, "live" apps.
# Code is not reloaded between requests
config.cache_classes = true
@@ -9,14 +8,15 @@
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
- # Specifies the header that your server uses for sending files
- config.action_dispatch.x_sendfile_header = "X-Sendfile"
+ # Disable Rails's static asset server (Apache or nginx will already do this)
+ config.serve_static_assets = false
- # For nginx:
- # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
+ # Specifies the header that your server uses for sending files
+ # (comment out if your front-end server doesn't support this)
+ config.action_dispatch.x_sendfile_header = "X-Sendfile" # Use 'X-Accel-Redirect' for nginx
- # If you have no front-end server that supports something like X-Sendfile,
- # just comment this out and Rails will serve the files
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
# See everything in the log (default is :info)
# config.log_level = :debug
@@ -27,10 +27,6 @@
# Use a different cache store in production
# config.cache_store = :mem_cache_store
- # Disable Rails's static asset server
- # In production, Apache or nginx will already do this
- config.serve_static_assets = false
-
# Enable serving of images, stylesheets, and javascripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
diff --git a/railties/railties.gemspec b/railties/railties.gemspec
index c3793d3ac3..c51fe856be 100644
--- a/railties/railties.gemspec
+++ b/railties/railties.gemspec
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
s.add_dependency('rake', '>= 0.8.7')
s.add_dependency('thor', '~> 0.14.4')
+ s.add_dependency('rack-ssl', '~> 1.3.2')
s.add_dependency('activesupport', version)
s.add_dependency('actionpack', version)
end
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index b314832685..01e6c49d9c 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -52,6 +52,12 @@ module ApplicationTests
assert_equal "Rack::Cache", middleware.first
end
+ test "Rack::SSL is present when force_ssl is set" do
+ add_to_config "config.force_ssl = true"
+ boot!
+ assert middleware.include?("Rack::SSL")
+ end
+
test "removing Active Record omits its middleware" do
use_frameworks []
boot!
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 0ce00db3c4..20797a2b0c 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -559,6 +559,45 @@ module RailtiesTest
assert_match /name="post\[title\]"/, last_response.body
end
+ test "isolated engine should set correct route module prefix for nested namespace" do
+ @plugin.write "lib/bukkits.rb", <<-RUBY
+ module Bukkits
+ module Awesome
+ class Engine < ::Rails::Engine
+ isolate_namespace Bukkits::Awesome
+ end
+ end
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ AppTemplate::Application.routes.draw do
+ mount Bukkits::Awesome::Engine => "/bukkits", :as => "bukkits"
+ end
+ RUBY
+
+ @plugin.write "config/routes.rb", <<-RUBY
+ Bukkits::Awesome::Engine.routes.draw do
+ match "/foo" => "foo#index"
+ end
+ RUBY
+
+ @plugin.write "app/controllers/bukkits/awesome/foo_controller.rb", <<-RUBY
+ class Bukkits::Awesome::FooController < ActionController::Base
+ def index
+ render :text => "ok"
+ end
+ end
+ RUBY
+
+ add_to_config("config.action_dispatch.show_exceptions = false")
+
+ boot_rails
+
+ get("/bukkits/foo")
+ assert_equal "ok", last_response.body
+ end
+
test "loading seed data" do
@plugin.write "db/seeds.rb", <<-RUBY
Bukkits::Engine.config.bukkits_seeds_loaded = true