Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' into bodyparts

  • Loading branch information...
commit 6335f5d5186dfb97453dfa1a55aabe4c6f3962b0 2 parents 70e3dfb + dc88847
@jeremy jeremy authored
Showing with 2,238 additions and 1,203 deletions.
  1. +1 −4 actionmailer/CHANGELOG
  2. +1 −1  actionmailer/Rakefile
  3. +1 −1  actionmailer/lib/action_mailer/version.rb
  4. +1 −4 actionpack/CHANGELOG
  5. +1 −1  actionpack/Rakefile
  6. +1 −1  actionpack/lib/action_controller/integration.rb
  7. +6 −10 actionpack/lib/action_controller/resources.rb
  8. +2 −1  actionpack/lib/action_controller/vendor/rack-1.0/rack.rb
  9. +49 −0 actionpack/lib/action_controller/vendor/rack-1.0/rack/chunked.rb
  10. +1 −1  actionpack/lib/action_controller/vendor/rack-1.0/rack/file.rb
  11. +4 −0 actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb
  12. +3 −0  actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb
  13. +4 −1 actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb
  14. +3 −1 actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb
  15. +3 −1 actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb
  16. +3 −0  actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb
  17. +2 −1  actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb
  18. +19 −35 actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb
  19. +5 −1 actionpack/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb
  20. +1 −1  actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb
  21. +1 −1  actionpack/lib/action_pack/version.rb
  22. +2 −2 actionpack/lib/action_view/helpers/date_helper.rb
  23. +1 −1  actionpack/lib/action_view/helpers/number_helper.rb
  24. +1 −1  actionpack/lib/action_view/paths.rb
  25. +1 −1  actionpack/lib/action_view/template.rb
  26. +3 −3 actionpack/test/controller/integration_test.rb
  27. +10 −0 actionpack/test/controller/render_test.rb
  28. +1 −1  actionpack/test/controller/request/multipart_params_parsing_test.rb
  29. +19 −1 actionpack/test/controller/resources_test.rb
  30. +14 −16 actionpack/test/controller/session/cookie_store_test.rb
  31. +1 −1  activemodel/lib/active_model/validations/inclusion.rb
  32. +1 −3 activerecord/CHANGELOG
  33. +1 −1  activerecord/Rakefile
  34. +9 −5 activerecord/lib/active_record/associations/association_collection.rb
  35. +2 −2 activerecord/lib/active_record/base.rb
  36. +23 −15 activerecord/lib/active_record/batches.rb
  37. +33 −22 activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
  38. +1 −1  activerecord/lib/active_record/validations.rb
  39. +1 −1  activerecord/lib/active_record/version.rb
  40. +25 −1 activerecord/test/cases/migration_test.rb
  41. +10 −5 activerecord/test/cases/transactions_test.rb
  42. +2 −7 activeresource/CHANGELOG
  43. +1 −1  activeresource/Rakefile
  44. +1 −1  activeresource/lib/active_resource/version.rb
  45. +1 −7 activesupport/CHANGELOG
  46. +1 −1  activesupport/lib/active_support/core_ext/date/calculations.rb
  47. +1 −1  activesupport/lib/active_support/version.rb
  48. +1 −4 railties/CHANGELOG
  49. +5 −5 railties/Rakefile
  50. +4 −0 railties/builtin/rails_info/rails/info.rb
  51. +1 −0  railties/environments/boot.rb
  52. +14 −2 railties/guides/files/stylesheets/main.css
  53. BIN  railties/guides/images/error_messages.png
  54. BIN  railties/guides/images/fxn.jpg
  55. BIN  railties/guides/images/i18n/demo_localized_pirate.png
  56. BIN  railties/guides/images/i18n/demo_translated_en.png
  57. BIN  railties/guides/images/i18n/demo_translated_pirate.png
  58. BIN  railties/guides/images/i18n/demo_translation_missing.png
  59. BIN  railties/guides/images/i18n/demo_untranslated.png
  60. +19 −8 railties/guides/rails_guides.rb
  61. +5 −21 railties/guides/rails_guides/generator.rb
  62. +1 −1  railties/guides/rails_guides/indexer.rb
  63. +80 −35 railties/guides/source/2_3_release_notes.textile
  64. +16 −16 railties/guides/source/action_controller_overview.textile
  65. +48 −12 railties/guides/source/action_mailer_basics.textile
  66. +4 −4 railties/guides/source/active_record_basics.textile
  67. +119 −51 railties/guides/source/active_record_querying.textile
  68. +337 −206 railties/guides/source/activerecord_validations_callbacks.textile
  69. +40 −40 railties/guides/source/association_basics.textile
  70. +79 −71 railties/guides/source/caching_with_rails.textile
  71. +23 −20 railties/guides/source/command_line.textile
  72. +8 −14 railties/guides/source/contribute.textile
  73. +239 −0 railties/guides/source/contributing_to_rails.textile
  74. +23 −10 railties/guides/source/credits.erb.textile
  75. +6 −6 railties/guides/source/debugging_rails_applications.textile
  76. +28 −28 railties/guides/source/form_helpers.textile
  77. +7 −6 railties/guides/source/getting_started.textile
  78. +161 −133 railties/guides/source/i18n.textile
  79. +7 −3 railties/guides/source/index.erb.textile
  80. +12 −9 railties/guides/source/layout.html.erb
  81. +38 −24 railties/guides/source/layouts_and_rendering.textile
  82. +23 −23 railties/guides/source/migrations.textile
  83. +222 −0 railties/guides/source/nested_model_forms.textile
  84. +30 −30 railties/guides/source/performance_testing.textile
  85. +17 −17 railties/guides/source/plugins.textile
  86. +60 −7 railties/guides/source/rails_on_rack.textile
  87. +17 −17 railties/guides/source/routing.textile
  88. +61 −39 railties/guides/source/security.textile
  89. +14 −14 railties/guides/source/testing.textile
  90. +3 −1 railties/lib/initializer.rb
  91. +125 −98 railties/lib/rails/gem_dependency.rb
  92. +1 −1  railties/lib/rails/rack/metal.rb
  93. +1 −1  railties/lib/rails/version.rb
  94. +32 −46 railties/lib/tasks/gems.rake
  95. +2 −0  railties/test/boot_test.rb
  96. +1 −1  railties/test/fixtures/metal/multiplemetals/app/metal/metal_a.rb
  97. +1 −1  railties/test/fixtures/metal/multiplemetals/app/metal/metal_b.rb
  98. +5 −0 railties/test/fixtures/metal/pluralmetal/app/metal/legacy_routes.rb
  99. +1 −1  railties/test/fixtures/metal/singlemetal/app/metal/foo_metal.rb
  100. +1 −1  railties/test/fixtures/metal/subfolders/app/metal/Folder/metal_a.rb
  101. +1 −1  railties/test/fixtures/metal/subfolders/app/metal/Folder/metal_b.rb
  102. +10 −7 railties/test/gem_dependency_test.rb
  103. +6 −0 railties/test/metal_test.rb
  104. +1 −1  railties/test/vendor/gems/dummy-gem-g-1.0.0/.specification
View
5 actionmailer/CHANGELOG
@@ -1,10 +1,7 @@
-*2.3.1 [RC2] (March 5, 2009)*
+*2.3.2 [Final] (March 15, 2009)*
* Fixed that ActionMailer should send correctly formatted Return-Path in MAIL FROM for SMTP #1842 [Matt Jones]
-
-*2.3.0 [RC1] (February 1st, 2009)*
-
* Fixed RFC-2045 quoted-printable bug #1421 [squadette]
* Fixed that no body charset would be set when there are attachments present #740 [Paweł Kondzior]
View
2  actionmailer/Rakefile
@@ -55,7 +55,7 @@ spec = Gem::Specification.new do |s|
s.rubyforge_project = "actionmailer"
s.homepage = "http://www.rubyonrails.org"
- s.add_dependency('actionpack', '= 2.3.1' + PKG_BUILD)
+ s.add_dependency('actionpack', '= 2.3.2' + PKG_BUILD)
s.has_rdoc = true
s.requirements << 'none'
View
2  actionmailer/lib/action_mailer/version.rb
@@ -2,7 +2,7 @@ module ActionMailer
module VERSION #:nodoc:
MAJOR = 2
MINOR = 3
- TINY = 1
+ TINY = 2
STRING = [MAJOR, MINOR, TINY].join('.')
end
View
5 actionpack/CHANGELOG
@@ -1,4 +1,4 @@
-*2.3.1 [RC2] (March 5, 2009)*
+*2.3.2 [Final] (March 15, 2009)*
* Fixed that redirection would just log the options, not the final url (which lead to "Redirected to #<Post:0x23150b8>") [DHH]
@@ -14,9 +14,6 @@
* Added localized rescue template when I18n.locale is set (ex: public/404.da.html) #1835 [José Valim]
-
-*2.3.0 [RC1] (February 1st, 2009)*
-
* Make the form_for and fields_for helpers support the new Active Record nested update options. #1202 [Eloy Duran]
<% form_for @person do |person_form| %>
View
2  actionpack/Rakefile
@@ -80,7 +80,7 @@ spec = Gem::Specification.new do |s|
s.has_rdoc = true
s.requirements << 'none'
- s.add_dependency('activesupport', '= 2.3.1' + PKG_BUILD)
+ s.add_dependency('activesupport', '= 2.3.2' + PKG_BUILD)
s.require_path = 'lib'
s.autorequire = 'action_controller'
View
2  actionpack/lib/action_controller/integration.rb
@@ -5,7 +5,7 @@
module ActionController
module Integration #:nodoc:
# An integration Session instance represents a set of requests and responses
- # performed sequentially by some virtual user. Becase you can instantiate
+ # performed sequentially by some virtual user. Because you can instantiate
# multiple sessions and run them side-by-side, you can also mimic (to some
# limited extent) multiple simultaneous users interacting with your system.
#
View
16 actionpack/lib/action_controller/resources.rb
@@ -630,7 +630,7 @@ def map_member_actions(map, resource)
action_path = resource.options[:path_names][action] if resource.options[:path_names].is_a?(Hash)
action_path ||= Base.resources_path_names[action] || action
- map_resource_routes(map, resource, action, "#{resource.member_path}#{resource.action_separator}#{action_path}", "#{action}_#{resource.shallow_name_prefix}#{resource.singular}", m)
+ map_resource_routes(map, resource, action, "#{resource.member_path}#{resource.action_separator}#{action_path}", "#{action}_#{resource.shallow_name_prefix}#{resource.singular}", m, { :force_id => true })
end
end
end
@@ -641,9 +641,9 @@ def map_member_actions(map, resource)
map_resource_routes(map, resource, :destroy, resource.member_path, route_path)
end
- def map_resource_routes(map, resource, action, route_path, route_name = nil, method = nil)
+ def map_resource_routes(map, resource, action, route_path, route_name = nil, method = nil, resource_options = {} )
if resource.has_action?(action)
- action_options = action_options_for(action, resource, method)
+ action_options = action_options_for(action, resource, method, resource_options)
formatted_route_path = "#{route_path}.:format"
if route_name && @set.named_routes[route_name.to_sym].nil?
@@ -660,9 +660,10 @@ def add_conditions_for(conditions, method)
end
end
- def action_options_for(action, resource, method = nil)
+ def action_options_for(action, resource, method = nil, resource_options = {})
default_options = { :action => action.to_s }
require_id = !resource.kind_of?(SingletonResource)
+ force_id = resource_options[:force_id] && !resource.kind_of?(SingletonResource)
case default_options[:action]
when "index", "new"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements)
@@ -670,12 +671,7 @@ def action_options_for(action, resource, method = nil)
when "show", "edit"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements(require_id))
when "update"; default_options.merge(add_conditions_for(resource.conditions, method || :put)).merge(resource.requirements(require_id))
when "destroy"; default_options.merge(add_conditions_for(resource.conditions, method || :delete)).merge(resource.requirements(require_id))
- else
- if method.nil? || resource.member_methods.nil? || resource.member_methods[method.to_sym].nil?
- default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements)
- else
- resource.member_methods[method.to_sym].include?(action) ? default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements(require_id)) : default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements)
- end
+ else default_options.merge(add_conditions_for(resource.conditions, method)).merge(resource.requirements(force_id))
end
end
end
View
3  actionpack/lib/action_controller/vendor/rack-1.0/rack.rb
@@ -23,11 +23,12 @@ def self.version
# Return the Rack release as a dotted string.
def self.release
- "0.4"
+ "1.0 bundled"
end
autoload :Builder, "rack/builder"
autoload :Cascade, "rack/cascade"
+ autoload :Chunked, "rack/chunked"
autoload :CommonLogger, "rack/commonlogger"
autoload :ConditionalGet, "rack/conditionalget"
autoload :ContentLength, "rack/content_length"
View
49 actionpack/lib/action_controller/vendor/rack-1.0/rack/chunked.rb
@@ -0,0 +1,49 @@
+require 'rack/utils'
+
+module Rack
+
+ # Middleware that applies chunked transfer encoding to response bodies
+ # when the response does not include a Content-Length header.
+ class Chunked
+ include Rack::Utils
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ status, headers, body = @app.call(env)
+ headers = HeaderHash.new(headers)
+
+ if env['HTTP_VERSION'] == 'HTTP/1.0' ||
+ STATUS_WITH_NO_ENTITY_BODY.include?(status) ||
+ headers['Content-Length'] ||
+ headers['Transfer-Encoding']
+ [status, headers.to_hash, body]
+ else
+ dup.chunk(status, headers, body)
+ end
+ end
+
+ def chunk(status, headers, body)
+ @body = body
+ headers.delete('Content-Length')
+ headers['Transfer-Encoding'] = 'chunked'
+ [status, headers.to_hash, self]
+ end
+
+ def each
+ term = "\r\n"
+ @body.each do |chunk|
+ size = bytesize(chunk)
+ next if size == 0
+ yield [size.to_s(16), term, chunk, term].join
+ end
+ yield ["0", term, "", term].join
+ end
+
+ def close
+ @body.close if @body.respond_to?(:close)
+ end
+ end
+end
View
2  actionpack/lib/action_controller/vendor/rack-1.0/rack/file.rb
@@ -60,7 +60,7 @@ def serving
body = self
else
body = [F.read(@path)]
- size = body.first.size
+ size = Utils.bytesize(body.first)
end
[200, {
View
4 actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb
@@ -1,3 +1,5 @@
+require 'rack/content_length'
+
module Rack
module Handler
class CGI
@@ -6,6 +8,8 @@ def self.run(app, options=nil)
end
def self.serve(app)
+ app = ContentLength.new(app)
+
env = ENV.to_hash
env.delete "HTTP_CONTENT_LENGTH"
View
3  actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb
@@ -1,5 +1,6 @@
require 'fcgi'
require 'socket'
+require 'rack/content_length'
module Rack
module Handler
@@ -29,6 +30,8 @@ def read(*args)
end
def self.serve(request, app)
+ app = Rack::ContentLength.new(app)
+
env = request.env
env.delete "HTTP_CONTENT_LENGTH"
View
5 actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb
@@ -1,5 +1,6 @@
require 'lsapi'
-#require 'cgi'
+require 'rack/content_length'
+
module Rack
module Handler
class LSWS
@@ -9,6 +10,8 @@ def self.run(app, options=nil)
end
end
def self.serve(app)
+ app = Rack::ContentLength.new(app)
+
env = ENV.to_hash
env.delete "HTTP_CONTENT_LENGTH"
env["SCRIPT_NAME"] = "" if env["SCRIPT_NAME"] == "/"
View
4 actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb
@@ -1,5 +1,7 @@
require 'mongrel'
require 'stringio'
+require 'rack/content_length'
+require 'rack/chunked'
module Rack
module Handler
@@ -33,7 +35,7 @@ def self.run(app, options={})
end
def initialize(app)
- @app = app
+ @app = Rack::Chunked.new(Rack::ContentLength.new(app))
end
def process(request, response)
View
4 actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb
@@ -1,5 +1,7 @@
require 'scgi'
require 'stringio'
+require 'rack/content_length'
+require 'rack/chunked'
module Rack
module Handler
@@ -14,7 +16,7 @@ def self.run(app, options=nil)
end
def initialize(settings = {})
- @app = settings[:app]
+ @app = Rack::Chunked.new(Rack::ContentLength.new(settings[:app]))
@log = Object.new
def @log.info(*args); end
def @log.error(*args); end
View
3  actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb
@@ -1,9 +1,12 @@
require "thin"
+require "rack/content_length"
+require "rack/chunked"
module Rack
module Handler
class Thin
def self.run(app, options={})
+ app = Rack::Chunked.new(Rack::ContentLength.new(app))
server = ::Thin::Server.new(options[:Host] || '0.0.0.0',
options[:Port] || 8080,
app)
View
3  actionpack/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb
@@ -1,5 +1,6 @@
require 'webrick'
require 'stringio'
+require 'rack/content_length'
module Rack
module Handler
@@ -14,7 +15,7 @@ def self.run(app, options={})
def initialize(server, app)
super server
- @app = app
+ @app = Rack::ContentLength.new(app)
end
def service(req, res)
View
54 actionpack/lib/action_controller/vendor/rack-1.0/rack/lint.rb
@@ -374,59 +374,43 @@ def check_content_type(status, headers)
## === The Content-Length
def check_content_length(status, headers, env)
- chunked_response = false
- headers.each { |key, value|
- if key.downcase == 'transfer-encoding'
- chunked_response = value.downcase != 'identity'
- end
- }
-
headers.each { |key, value|
if key.downcase == 'content-length'
- ## There must be a <tt>Content-Length</tt>, except when the
- ## +Status+ is 1xx, 204 or 304, in which case there must be none
- ## given.
+ ## There must not be a <tt>Content-Length</tt> header when the
+ ## +Status+ is 1xx, 204 or 304.
assert("Content-Length header found in #{status} response, not allowed") {
not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
}
- assert('Content-Length header should not be used if body is chunked') {
- not chunked_response
- }
-
bytes = 0
string_body = true
- @body.each { |part|
- unless part.kind_of?(String)
- string_body = false
- break
- end
+ if @body.respond_to?(:to_ary)
+ @body.each { |part|
+ unless part.kind_of?(String)
+ string_body = false
+ break
+ end
- bytes += Rack::Utils.bytesize(part)
- }
-
- if env["REQUEST_METHOD"] == "HEAD"
- assert("Response body was given for HEAD request, but should be empty") {
- bytes == 0
+ bytes += Rack::Utils.bytesize(part)
}
- else
- if string_body
- assert("Content-Length header was #{value}, but should be #{bytes}") {
- value == bytes.to_s
+
+ if env["REQUEST_METHOD"] == "HEAD"
+ assert("Response body was given for HEAD request, but should be empty") {
+ bytes == 0
}
+ else
+ if string_body
+ assert("Content-Length header was #{value}, but should be #{bytes}") {
+ value == bytes.to_s
+ }
+ end
end
end
return
end
}
-
- if [ String, Array ].include?(@body.class) && !chunked_response
- assert('No Content-Length header found') {
- Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
- }
- end
end
## === The Body
View
6 actionpack/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb
@@ -12,7 +12,11 @@ module Rack
# first, since they are most specific.
class URLMap
- def initialize(map)
+ def initialize(map = {})
+ remap(map)
+ end
+
+ def remap(map)
@mapping = map.map { |location, app|
if location =~ %r{\Ahttps?://(.*?)(/.*)}
host, location = $1, $2
View
2  actionpack/lib/action_controller/vendor/rack-1.0/rack/utils.rb
@@ -372,7 +372,7 @@ def self.parse_multipart(env)
data = body
end
- Utils.normalize_params(params, name, data)
+ Utils.normalize_params(params, name, data) unless data.nil?
break if buf.empty? || content_length == -1
}
View
2  actionpack/lib/action_pack/version.rb
@@ -2,7 +2,7 @@ module ActionPack #:nodoc:
module VERSION #:nodoc:
MAJOR = 2
MINOR = 3
- TINY = 1
+ TINY = 2
STRING = [MAJOR, MINOR, TINY].join('.')
end
View
4 actionpack/lib/action_view/helpers/date_helper.rb
@@ -876,8 +876,8 @@ def input_id_from_type(type)
input_name_from_type(type).gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '')
end
- # Given an ordering of datetime components, create the selection html
- # and join them with their appropriate seperators
+ # Given an ordering of datetime components, create the selection HTML
+ # and join them with their appropriate separators.
def build_selects_from_types(order)
select = ''
order.reverse.each do |type|
View
2  actionpack/lib/action_view/helpers/number_helper.rb
@@ -140,7 +140,7 @@ def number_to_percentage(number, options = {})
# number_with_delimiter(12345678) # => 12,345,678
# number_with_delimiter(12345678.05) # => 12,345,678.05
# number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
- # number_with_delimiter(12345678, :seperator => ",") # => 12,345,678
+ # number_with_delimiter(12345678, :separator => ",") # => 12,345,678
# number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
# # => 98 765 432,98
#
View
2  actionpack/lib/action_view/paths.rb
@@ -61,7 +61,7 @@ def find_template(original_template_path, format = nil, html_fallback = true)
end
end
- return Template.new(original_template_path, original_template_path =~ /\A\// ? "" : ".") if File.file?(original_template_path)
+ return Template.new(original_template_path, original_template_path.to_s =~ /\A\// ? "" : ".") if File.file?(original_template_path)
raise MissingTemplate.new(self, original_template_path, format)
end
View
2  actionpack/lib/action_view/template.rb
@@ -218,7 +218,7 @@ def valid_locale?(locale)
# Returns file split into an array
# [base_path, name, locale, format, extension]
def split(file)
- if m = file.match(/^(.*\/)?([^\.]+)\.(.*)$/)
+ if m = file.to_s.match(/^(.*\/)?([^\.]+)\.(.*)$/)
base_path = m[1]
name = m[2]
extensions = m[3]
View
6 actionpack/test/controller/integration_test.rb
@@ -2,7 +2,7 @@
class SessionTest < Test::Unit::TestCase
StubApp = lambda { |env|
- [200, {"Content-Type" => "text/html", "Content-Length" => "13"}, "Hello, World!"]
+ [200, {"Content-Type" => "text/html", "Content-Length" => "13"}, ["Hello, World!"]]
}
def setup
@@ -389,9 +389,9 @@ class MetalTest < ActionController::IntegrationTest
class Poller
def self.call(env)
if env["PATH_INFO"] =~ /^\/success/
- [200, {"Content-Type" => "text/plain", "Content-Length" => "12"}, "Hello World!"]
+ [200, {"Content-Type" => "text/plain", "Content-Length" => "12"}, ["Hello World!"]]
else
- [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, '']
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
end
end
end
View
10 actionpack/test/controller/render_test.rb
@@ -157,6 +157,11 @@ def render_file_not_using_full_path_with_dot_in_path
render :file => 'test/dot.directory/render_file_with_ivar'
end
+ def render_file_using_pathname
+ @secret = 'in the sauce'
+ render :file => Pathname.new(File.dirname(__FILE__)).join('..', 'fixtures', 'test', 'dot.directory', 'render_file_with_ivar.erb')
+ end
+
def render_file_from_template
@secret = 'in the sauce'
@path = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.erb'))
@@ -861,6 +866,11 @@ def test_render_file_not_using_full_path_with_dot_in_path
assert_equal "The secret is in the sauce\n", @response.body
end
+ def test_render_file_using_pathname
+ get :render_file_using_pathname
+ assert_equal "The secret is in the sauce\n", @response.body
+ end
+
def test_render_file_with_locals
get :render_file_with_locals
assert_equal "The secret is in the sauce\n", @response.body
View
2  actionpack/test/controller/request/multipart_params_parsing_test.rb
@@ -103,7 +103,7 @@ def teardown
test "does not create tempfile if no file has been selected" do
params = parse_multipart('none')
- assert_equal %w(files submit-name), params.keys.sort
+ assert_equal %w(submit-name), params.keys.sort
assert_equal 'Larry', params['submit-name']
assert_equal nil, params['files']
end
View
20 actionpack/test/controller/resources_test.rb
@@ -175,6 +175,24 @@ def test_with_collection_actions_and_name_prefix
end
end
+ def test_with_collection_actions_and_name_prefix_and_member_action_with_same_name
+ actions = { 'a' => :get }
+
+ with_restful_routing :messages, :path_prefix => '/threads/:thread_id', :name_prefix => "thread_", :collection => actions, :member => actions do
+ assert_restful_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options|
+ actions.each do |action, method|
+ assert_recognizes(options.merge(:action => action), :path => "/threads/1/messages/#{action}", :method => method)
+ end
+ end
+
+ assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options|
+ actions.keys.each do |action|
+ assert_named_route "/threads/1/messages/#{action}", "#{action}_thread_messages_path", :action => action
+ end
+ end
+ end
+ end
+
def test_with_collection_action_and_name_prefix_and_formatted
actions = { 'a' => :get, 'b' => :put, 'c' => :post, 'd' => :delete }
@@ -211,7 +229,7 @@ def test_with_member_action
def test_with_member_action_and_requirement
expected_options = {:controller => 'messages', :action => 'mark', :id => '1.1.1'}
-
+
with_restful_routing(:messages, :requirements => {:id => /[0-9]\.[0-9]\.[0-9]/}, :member => { :mark => :get }) do
assert_recognizes(expected_options, :path => 'messages/1.1.1/mark', :method => :get)
end
View
30 actionpack/test/controller/session/cookie_store_test.rb
@@ -199,29 +199,18 @@ def test_session_store_with_expire_after
with_test_route_set do
# First request accesses the session
- time = Time.local(2008, 4, 24)
- Time.stubs(:now).returns(time)
- expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d-%b-%Y %H:%M:%S GMT")
-
cookies[SessionKey] = SignedBar
get '/set_session_value'
assert_response :success
+ cookie = headers['Set-Cookie']
- cookie_body = response.body
- assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly",
- headers['Set-Cookie']
-
- # Second request does not access the session
- time = Time.local(2008, 4, 25)
- Time.stubs(:now).returns(time)
- expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d-%b-%Y %H:%M:%S GMT")
-
+ # Second request does not access the session so the
+ # expires header should not be changed
get '/no_session_access'
assert_response :success
-
- assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly",
- headers['Set-Cookie']
+ assert_equal cookie, headers['Set-Cookie'],
+ "#{unmarshal_session(cookie).inspect} expected but was #{unmarshal_session(headers['Set-Cookie']).inspect}"
end
end
@@ -236,4 +225,13 @@ def with_test_route_set
yield
end
end
+
+ def unmarshal_session(cookie_string)
+ session = Rack::Utils.parse_query(cookie_string, ';,').inject({}) {|h,(k,v)|
+ h[k] = Array === v ? v.first : v
+ h
+ }[SessionKey]
+ verifier = ActiveSupport::MessageVerifier.new(SessionSecret, 'SHA1')
+ verifier.verify(session)
+ end
end
View
2  activemodel/lib/active_model/validations/inclusion.rb
@@ -4,7 +4,7 @@ module ClassMethods
# Validates whether the value of the specified attribute is available in a particular enumerable object.
#
# class Person < ActiveRecord::Base
- # validates_inclusion_of :gender, :in => %w( m f ), :message => "woah! what are you then!??!!"
+ # validates_inclusion_of :gender, :in => %w( m f )
# validates_inclusion_of :age, :in => 0..99
# validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension %s is not included in the list"
# end
View
4 activerecord/CHANGELOG
@@ -1,11 +1,9 @@
-*2.3.1 [RC2] (March 5, 2009)*
+*2.3.2 [Final] (March 15, 2009)*
* Added ActiveRecord::Base.find_each and ActiveRecord::Base.find_in_batches for batch processing [DHH/Jamis Buck]
* Added that ActiveRecord::Base.exists? can be called with no arguments #1817 [Scott Taylor]
-*2.3.0 [RC1] (February 1st, 2009)*
-
* Add Support for updating deeply nested models from a single form. #1202 [Eloy Duran]
class Book < ActiveRecord::Base
View
2  activerecord/Rakefile
@@ -177,7 +177,7 @@ spec = Gem::Specification.new do |s|
s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
end
- s.add_dependency('activesupport', '= 2.3.1' + PKG_BUILD)
+ s.add_dependency('activesupport', '= 2.3.2' + PKG_BUILD)
s.files.delete FIXTURES_ROOT + "/fixture_database.sqlite"
s.files.delete FIXTURES_ROOT + "/fixture_database_2.sqlite"
View
14 activerecord/lib/active_record/associations/association_collection.rb
@@ -143,6 +143,8 @@ def transaction(*args)
end
# Remove all records from this association
+ #
+ # See delete for more info.
def delete_all
load_target
delete(@target)
@@ -200,11 +202,11 @@ def delete(*records)
end
end
- # Destroy +records+ and remove from this association calling +before_remove+
- # and +after_remove+ callbacks.
+ # Destroy +records+ and remove them from this association calling
+ # +before_remove+ and +after_remove+ callbacks.
#
- # Note this method will always remove records from database ignoring the
- # +:dependent+ option.
+ # Note that this method will _always_ remove records from the database
+ # ignoring the +:dependent+ option.
def destroy(*records)
remove_records(records) do |records, old_records|
old_records.each { |record| record.destroy }
@@ -226,7 +228,9 @@ def clear
self
end
- # Destory all the records from this association
+ # Destory all the records from this association.
+ #
+ # See destroy for more info.
def destroy_all
load_target
destroy(@target)
View
4 activerecord/lib/active_record/base.rb
@@ -736,12 +736,12 @@ def create(attributes = nil, &block)
# ==== Parameters
#
# * +id+ - This should be the id or an array of ids to be updated.
- # * +attributes+ - This should be a Hash of attributes to be set on the object, or an array of Hashes.
+ # * +attributes+ - This should be a hash of attributes to be set on the object, or an array of hashes.
#
# ==== Examples
#
# # Updating one record:
- # Person.update(15, { :user_name => 'Samuel', :group => 'expert' })
+ # Person.update(15, :user_name => 'Samuel', :group => 'expert')
#
# # Updating multiple records:
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
View
38 activerecord/lib/active_record/batches.rb
@@ -4,10 +4,12 @@ def self.included(base)
base.extend(ClassMethods)
end
- # When processing large numbers of records, it's often a good idea to do so in batches to prevent memory ballooning.
+ # When processing large numbers of records, it's often a good idea to do
+ # so in batches to prevent memory ballooning.
module ClassMethods
- # Yields each record that was found by the find +options+. The find is performed by find_in_batches
- # with a batch size of 1000 (or as specified by the +batch_size+ option).
+ # Yields each record that was found by the find +options+. The find is
+ # performed by find_in_batches with a batch size of 1000 (or as
+ # specified by the <tt>:batch_size</tt> option).
#
# Example:
#
@@ -15,9 +17,10 @@ module ClassMethods
# person.party_all_night!
# end
#
- # Note: This method is only intended to use for batch processing of large amounts of records that wouldn't fit in
- # memory all at once. If you just need to loop over less than 1000 records, it's probably better just to use the
- # regular find methods.
+ # Note: This method is only intended to use for batch processing of
+ # large amounts of records that wouldn't fit in memory all at once. If
+ # you just need to loop over less than 1000 records, it's probably
+ # better just to use the regular find methods.
def find_each(options = {})
find_in_batches(options) do |records|
records.each { |record| yield record }
@@ -26,17 +29,22 @@ def find_each(options = {})
self
end
- # Yields each batch of records that was found by the find +options+ as an array. The size of each batch is
- # set by the +batch_size+ option; the default is 1000.
+ # Yields each batch of records that was found by the find +options+ as
+ # an array. The size of each batch is set by the <tt>:batch_size</tt>
+ # option; the default is 1000.
#
- # You can control the starting point for the batch processing by supplying the +start+ option. This is especially
- # useful if you want multiple workers dealing with the same processing queue. You can make worker 1 handle all the
- # records between id 0 and 10,000 and worker 2 handle from 10,000 and beyond (by setting the +start+ option on that
- # worker).
+ # You can control the starting point for the batch processing by
+ # supplying the <tt>:start</tt> option. This is especially useful if you
+ # want multiple workers dealing with the same processing queue. You can
+ # make worker 1 handle all the records between id 0 and 10,000 and
+ # worker 2 handle from 10,000 and beyond (by setting the <tt>:start</tt>
+ # option on that worker).
#
- # It's not possible to set the order. That is automatically set to ascending on the primary key ("id ASC")
- # to make the batch ordering work. This also mean that this method only works with integer-based primary keys.
- # You can't set the limit either, that's used to control the the batch sizes.
+ # It's not possible to set the order. That is automatically set to
+ # ascending on the primary key ("id ASC") to make the batch ordering
+ # work. This also mean that this method only works with integer-based
+ # primary keys. You can't set the limit either, that's used to control
+ # the the batch sizes.
#
# Example:
#
View
55 activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -72,6 +72,18 @@ def binary_to_string(value)
#
# * <tt>:database</tt> - Path to the database file.
class SQLiteAdapter < AbstractAdapter
+ class Version
+ include Comparable
+
+ def initialize(version_string)
+ @version = version_string.split('.').map(&:to_i)
+ end
+
+ def <=>(version_string)
+ @version <=> version_string.split('.').map(&:to_i)
+ end
+ end
+
def initialize(connection, logger, config)
super(connection, logger)
@config = config
@@ -81,6 +93,10 @@ def adapter_name #:nodoc:
'SQLite'
end
+ def supports_ddl_transactions?
+ sqlite_version >= '2.0.0'
+ end
+
def supports_migrations? #:nodoc:
true
end
@@ -88,6 +104,10 @@ def supports_migrations? #:nodoc:
def requires_reloading?
true
end
+
+ def supports_add_column?
+ sqlite_version >= '3.1.6'
+ end
def disconnect!
super
@@ -169,7 +189,6 @@ def rollback_db_transaction #:nodoc:
catch_schema_changes { @connection.rollback }
end
-
# SELECT ... FOR UPDATE is redundant since the table is locked.
def add_lock!(sql, options) #:nodoc:
sql
@@ -218,14 +237,20 @@ def rename_table(name, new_name)
execute "ALTER TABLE #{name} RENAME TO #{new_name}"
end
+ # See: http://www.sqlite.org/lang_altertable.html
+ # SQLite has an additional restriction on the ALTER TABLE statement
+ def valid_alter_table_options( type, options)
+ type.to_sym != :primary_key
+ end
+
def add_column(table_name, column_name, type, options = {}) #:nodoc:
- if @connection.respond_to?(:transaction_active?) && @connection.transaction_active?
- raise StatementInvalid, 'Cannot add columns to a SQLite database while inside a transaction'
+ if supports_add_column? && valid_alter_table_options( type, options )
+ super(table_name, column_name, type, options)
+ else
+ alter_table(table_name) do |definition|
+ definition.column(column_name, type, options)
+ end
end
-
- super(table_name, column_name, type, options)
- # See last paragraph on http://www.sqlite.org/lang_altertable.html
- execute "VACUUM"
end
def remove_column(table_name, *column_names) #:nodoc:
@@ -385,7 +410,7 @@ def catch_schema_changes
end
def sqlite_version
- @sqlite_version ||= select_value('select sqlite_version(*)')
+ @sqlite_version ||= SQLiteAdapter::Version.new(select_value('select sqlite_version(*)'))
end
def default_primary_key_type
@@ -398,23 +423,9 @@ def default_primary_key_type
end
class SQLite2Adapter < SQLiteAdapter # :nodoc:
- def supports_count_distinct? #:nodoc:
- false
- end
-
def rename_table(name, new_name)
move_table(name, new_name)
end
-
- def add_column(table_name, column_name, type, options = {}) #:nodoc:
- if @connection.respond_to?(:transaction_active?) && @connection.transaction_active?
- raise StatementInvalid, 'Cannot add columns to a SQLite database while inside a transaction'
- end
-
- alter_table(table_name) do |definition|
- definition.column(column_name, type, options)
- end
- end
end
class DeprecatedSQLiteAdapter < SQLite2Adapter # :nodoc:
View
2  activerecord/lib/active_record/validations.rb
@@ -802,7 +802,7 @@ def validates_format_of(*attr_names)
# Validates whether the value of the specified attribute is available in a particular enumerable object.
#
# class Person < ActiveRecord::Base
- # validates_inclusion_of :gender, :in => %w( m f ), :message => "woah! what are you then!??!!"
+ # validates_inclusion_of :gender, :in => %w( m f )
# validates_inclusion_of :age, :in => 0..99
# validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension {{value}} is not included in the list"
# end
View
2  activerecord/lib/active_record/version.rb
@@ -2,7 +2,7 @@ module ActiveRecord
module VERSION #:nodoc:
MAJOR = 2
MINOR = 3
- TINY = 1
+ TINY = 2
STRING = [MAJOR, MINOR, TINY].join('.')
end
View
26 activerecord/test/cases/migration_test.rb
@@ -93,6 +93,30 @@ def test_add_index
end
end
+ def testing_table_with_only_foo_attribute
+ Person.connection.create_table :testings, :id => false do |t|
+ t.column :foo, :string
+ end
+
+ yield Person.connection
+ ensure
+ Person.connection.drop_table :testings rescue nil
+ end
+ protected :testing_table_with_only_foo_attribute
+
+ def test_create_table_without_id
+ testing_table_with_only_foo_attribute do |connection|
+ assert_equal connection.columns(:testings).size, 1
+ end
+ end
+
+ def test_add_column_with_primary_key_attribute
+ testing_table_with_only_foo_attribute do |connection|
+ assert_nothing_raised { connection.add_column :testings, :id, :primary_key }
+ assert_equal connection.columns(:testings).size, 2
+ end
+ end
+
def test_create_table_adds_id
Person.connection.create_table :testings do |t|
t.column :foo, :string
@@ -928,7 +952,7 @@ def test_migrator_double_down
assert_equal(0, ActiveRecord::Migrator.current_version)
end
- if current_adapter?(:PostgreSQLAdapter)
+ if ActiveRecord::Base.connection.supports_ddl_transactions?
def test_migrator_one_up_with_exception_and_rollback
assert !Person.column_methods_hash.include?(:last_name)
View
15 activerecord/test/cases/transactions_test.rb
@@ -349,7 +349,7 @@ def test_open_transactions_count_is_reset_to_zero_if_no_transaction_active
end
end
- def test_sqlite_add_column_in_transaction_raises_statement_invalid
+ def test_sqlite_add_column_in_transaction
return true unless current_adapter?(:SQLite3Adapter, :SQLiteAdapter)
# Test first if column creation/deletion works correctly when no
@@ -368,10 +368,15 @@ def test_sqlite_add_column_in_transaction_raises_statement_invalid
assert !Topic.column_names.include?('stuff')
end
- # Test now inside a transaction: add_column should raise a StatementInvalid
- Topic.transaction do
- assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.add_column('topics', 'stuff', :string) }
- raise ActiveRecord::Rollback
+ if Topic.connection.supports_ddl_transactions?
+ assert_nothing_raised do
+ Topic.transaction { Topic.connection.add_column('topics', 'stuff', :string) }
+ end
+ else
+ Topic.transaction do
+ assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.add_column('topics', 'stuff', :string) }
+ raise ActiveRecord::Rollback
+ end
end
end
View
9 activeresource/CHANGELOG
@@ -1,11 +1,6 @@
-*2.3.1 [RC2] (March 5, 2009)*
+*2.3.2 [Final] (March 15, 2009)*
-* Nothing new, just included in 2.3.1
-
-
-*2.3.0 [RC1] (February 1st, 2009)*
-
-* Nothing new, just included in 2.3.0
+* Nothing new, just included in 2.3.2
*2.2.1 [RC2] (November 14th, 2008)*
View
2  activeresource/Rakefile
@@ -67,7 +67,7 @@ spec = Gem::Specification.new do |s|
s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
end
- s.add_dependency('activesupport', '= 2.3.1' + PKG_BUILD)
+ s.add_dependency('activesupport', '= 2.3.2' + PKG_BUILD)
s.require_path = 'lib'
s.autorequire = 'active_resource'
View
2  activeresource/lib/active_resource/version.rb
@@ -2,7 +2,7 @@ module ActiveResource
module VERSION #:nodoc:
MAJOR = 2
MINOR = 3
- TINY = 1
+ TINY = 2
STRING = [MAJOR, MINOR, TINY].join('.')
end
View
8 activesupport/CHANGELOG
@@ -1,11 +1,8 @@
-*Edge*
+*2.3.2 [Final] (March 15, 2009)*
* XmlMini supports LibXML and Nokogiri backends. #2084, #2190 [Bart ten Brinke, Aaron Patterson]
Example: XmlMini.backend = 'Nokogiri'
-
-*2.3.1 [RC2] (March 5, 2009)*
-
* Vendorize i18n 0.1.3 gem (fixes issues with incompatible character encodings in Ruby 1.9) #2038 [Akira Matsuda]
* Update bundled memcache-client from 1.5.0.5 to 1.6.4.99. See http://www.mikeperham.com/2009/02/15/memcache-client-performance/ [Mike Perham]
@@ -18,9 +15,6 @@
* Introduce Array.wrap(foo) to wrap the argument in an array unless it's already an array. Wraps nil as an empty array. Use instead of Array(foo) and foo.to_a since they treat String as Enumerable. [Jeremy Kemper]
-
-*2.3.0 [RC1] (February 1st, 2009)*
-
* TimeWithZone#xmlschema accepts optional fraction_digits argument [#1725 state:resolved] [Nicholas Dainty]
* Object#tap shim for Ruby < 1.8.7. Similar to Object#returning, tap yields self then returns self. [Jeremy Kemper]
View
2  activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -1,7 +1,7 @@
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Date #:nodoc:
- # Enables the use of time calculations within Time itself
+ # Enables the use of time calculations within Date itself
module Calculations
def self.included(base) #:nodoc:
base.extend ClassMethods
View
2  activesupport/lib/active_support/version.rb
@@ -2,7 +2,7 @@ module ActiveSupport
module VERSION #:nodoc:
MAJOR = 2
MINOR = 3
- TINY = 1
+ TINY = 2
STRING = [MAJOR, MINOR, TINY].join('.')
end
View
5 railties/CHANGELOG
@@ -1,10 +1,7 @@
-*2.3.1 [RC2] (March 5, 2009)*
+*2.3.2 [Final] (March 15, 2009)*
* Allow metal to live in plugins #2045 [Matthew Rudy]
-
-*2.3.0 [RC1] (February 1st, 2009)*
-
* Added metal [Josh Peek]
* Remove script/performance/request in favour of the performance integration tests. [Pratik Naik]
View
10 railties/Rakefile
@@ -311,11 +311,11 @@ spec = Gem::Specification.new do |s|
EOF
s.add_dependency('rake', '>= 0.8.3')
- s.add_dependency('activesupport', '= 2.3.1' + PKG_BUILD)
- s.add_dependency('activerecord', '= 2.3.1' + PKG_BUILD)
- s.add_dependency('actionpack', '= 2.3.1' + PKG_BUILD)
- s.add_dependency('actionmailer', '= 2.3.1' + PKG_BUILD)
- s.add_dependency('activeresource', '= 2.3.1' + PKG_BUILD)
+ s.add_dependency('activesupport', '= 2.3.2' + PKG_BUILD)
+ s.add_dependency('activerecord', '= 2.3.2' + PKG_BUILD)
+ s.add_dependency('actionpack', '= 2.3.2' + PKG_BUILD)
+ s.add_dependency('actionmailer', '= 2.3.2' + PKG_BUILD)
+ s.add_dependency('activeresource', '= 2.3.2' + PKG_BUILD)
s.rdoc_options << '--exclude' << '.'
s.has_rdoc = false
View
4 railties/builtin/rails_info/rails/info.rb
@@ -85,6 +85,10 @@ def git_info
Gem::RubyGemsVersion
end
+ property 'Rack version' do
+ ::Rack.release
+ end
+
# The Rails version.
property 'Rails version' do
Rails::VERSION::STRING
View
1  railties/environments/boot.rb
@@ -44,6 +44,7 @@ class VendorBoot < Boot
def load_initializer
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
Rails::Initializer.run(:install_gem_spec_stubs)
+ Rails::GemDependency.add_frozen_gem_path
end
end
View
16 railties/guides/files/stylesheets/main.css
@@ -337,7 +337,7 @@ h6 {
margin-top: 0.25em;
}
-#mainCol dd.warning, #subCol dd.warning {
+#mainCol div.warning, #subCol dd.warning {
background: #f9d9d8 url(../../images/tab_red.gif) no-repeat left top;
border: none;
padding: 1.25em 1.25em 1.25em 48px;
@@ -426,4 +426,16 @@ code {
.clearfix {display: inline-block;}
* html .clearfix {height: 1%;}
.clearfix {display: block;}
-.clear { clear:both; }
+.clear { clear:both; }
+
+/* Same bottom margin for special boxes than for regular paragraphs, this way
+intermediate whitespace looks uniform. */
+div.code_container, div.important, div.caution, div.warning, div.note, div.info {
+ margin-bottom: 1.5em;
+}
+
+/* Remove bottom margin of paragraphs in special boxes, otherwise they get a
+spurious blank area below with the box background. */
+div.important p, div.caution p, div.warning p, div.note p, div.info p {
+ margin-bottom: 0px;
+}
View
BIN  railties/guides/images/error_messages.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  railties/guides/images/fxn.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  railties/guides/images/i18n/demo_localized_pirate.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  railties/guides/images/i18n/demo_translated_en.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  railties/guides/images/i18n/demo_translated_pirate.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  railties/guides/images/i18n/demo_translation_missing.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  railties/guides/images/i18n/demo_untranslated.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
27 railties/guides/rails_guides.rb
@@ -1,17 +1,28 @@
pwd = File.dirname(__FILE__)
$: << pwd
-$: << File.join(pwd, "../../activesupport/lib")
-$: << File.join(pwd, "../../actionpack/lib")
-require "action_controller"
-require "action_view"
+begin
+ as_lib = File.join(pwd, "../../activesupport/lib")
+ ap_lib = File.join(pwd, "../../actionpack/lib")
+
+ $: << as_lib if File.directory?(as_lib)
+ $: << ap_lib if File.directory?(ap_lib)
+
+ require "action_controller"
+ require "action_view"
+rescue LoadError
+ require 'rubygems'
+ gem "actionpack", '>= 2.3'
+
+ require "action_controller"
+ require "action_view"
+end
-# Require rubygems after loading Action View
-require 'rubygems'
begin
- gem 'RedCloth', '>= 4.1.1'# Need exactly 4.1.1
+ require 'rubygems'
+ gem 'RedCloth', '>= 4.1.1'
rescue Gem::LoadError
- $stderr.puts %(Missing the RedCloth 4.1.1 gem.\nPlease `gem install -v=4.1.1 RedCloth` to generate the guides.)
+ $stderr.puts %(Generating Guides requires RedCloth 4.1.1+)
exit 1
end
View
26 railties/guides/rails_guides/generator.rb
@@ -57,7 +57,6 @@ def generate_guide(guide)
result = view.render(:layout => 'layout', :text => textile(body))
f.write result
- warn_about_broken_links(result)
end
end
end
@@ -109,8 +108,8 @@ def set_index(body, view)
end
def textile(body)
- # If the issue with nontextile is fixed just remove the wrapper.
- with_workaround_for_nontextile(body) do |body|
+ # If the issue with notextile is fixed just remove the wrapper.
+ with_workaround_for_notextile(body) do |body|
t = RedCloth.new(body)
t.hard_breaks = false
t.to_html(:notestuff, :plusplus, :code, :tip)
@@ -120,35 +119,20 @@ def textile(body)
# For some reason the notextile tag does not always turn off textile. See
# LH ticket of the security guide (#7). As a temporary workaround we deal
# with code blocks by hand.
- def with_workaround_for_nontextile(body)
+ def with_workaround_for_notextile(body)
code_blocks = []
body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)</\1>}m) do |m|
es = ERB::Util.h($2)
css_class = ['erb', 'shell'].include?($1) ? 'html' : $1
code_blocks << %{<div class="code_container"><code class="#{css_class}">#{es}</code></div>}
- "dirty_workaround_for_nontextile_#{code_blocks.size - 1}"
+ "\ndirty_workaround_for_notextile_#{code_blocks.size - 1}\n"
end
body = yield body
- body.gsub(%r{<p>dirty_workaround_for_nontextile_(\d+)</p>}) do |_|
+ body.gsub(%r{<p>dirty_workaround_for_notextile_(\d+)</p>}) do |_|
code_blocks[$1.to_i]
end
end
-
- def warn_about_broken_links(html)
- # Textile generates headers with IDs computed from titles.
- anchors = Set.new(html.scan(/<h\d\s+id="([^"]+)/).flatten)
- # Also, footnotes are rendered as paragraphs this way.
- anchors += Set.new(html.scan(/<p\s+class="footnote"\s+id="([^"]+)/).flatten)
-
- # Check fragment identifiers.
- html.scan(/<a\s+href="#([^"]+)/).flatten.each do |fragment_identifier|
- next if fragment_identifier == 'mainCol' # in layout, jumps to some DIV
- unless anchors.member?(fragment_identifier)
- puts "BROKEN LINK: ##{fragment_identifier}"
- end
- end
- end
end
end
View
2  railties/guides/rails_guides/indexer.rb
@@ -29,7 +29,7 @@ def process(string, current_level= 3, counters = [1])
return level_hash
elsif level == current_level
index = counters.join(".")
- bookmark = '#' + title.gsub(/[^a-z0-9\-_]+/i, '').underscore.dasherize
+ bookmark = '#' + title.strip.downcase.gsub(/\s+|_/, '-').delete('^a-z0-9-')
raise "Parsing Fail" unless @result.sub!(matched, "h#{level}(#{bookmark}). #{index}#{title}")
View
115 railties/guides/source/2_3_release_notes.textile
@@ -1,7 +1,5 @@
h2. Ruby on Rails 2.3 Release Notes
-NOTE: These release notes refer to RC2 of Rails 2.3. This is a release candidate, and not the final version of Rails 2.3. It's intended to be a stable testing release, and we urge you to test your own applications and report any issues to the "Rails Lighthouse":http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/overview.
-
Rails 2.3 delivers a variety of new and improved features, including pervasive Rack integration, refreshed support for Rails Engines, nested transactions for Active Record, dynamic and default scopes, unified rendering, more efficient routing, application templates, and quiet backtraces. This list covers the major upgrades, but doesn't include every little bug fix and change. If you want to see everything, check out the "list of commits":http://github.com/rails/rails/commits/master in the main Rails repository on GitHub or review the +CHANGELOG+ files for the individual Rails components.
endprologue.
@@ -22,24 +20,25 @@ Rails has now broken with its CGI past, and uses Rack everywhere. This required
Here's a summary of the rack-related changes:
* +script/server+ has been switched to use Rack, which means it supports any Rack compatible server. +script/server+ will also pick up a rackup configuration file if one exists. By default, it will look for a +config.ru+ file, but you can override this with the +-c+ switch.
-* The FCGI handler goes through Rack
-* +ActionController::Dispatcher+ maintains its own default middleware stack. Middlewares can be injected in, reordered, and removed. The stack is compiled into a chain on boot. You can configure the middleware stack in +environment.rb+
+* The FCGI handler goes through Rack.
+* +ActionController::Dispatcher+ maintains its own default middleware stack. Middlewares can be injected in, reordered, and removed. The stack is compiled into a chain on boot. You can configure the middleware stack in +environment.rb+.
* The +rake middleware+ task has been added to inspect the middleware stack. This is useful for debugging the order of the middleware stack.
* The integration test runner has been modified to execute the entire middleware and application stack. This makes integration tests perfect for testing Rack middleware.
* +ActionController::CGIHandler+ is a backwards compatible CGI wrapper around Rack. The +CGIHandler+ is meant to take an old CGI object and convert its environment information into a Rack compatible form.
-* +CgiRequest+ and +CgiResponse+ have been removed
+* +CgiRequest+ and +CgiResponse+ have been removed.
* Session stores are now lazy loaded. If you never access the session object during a request, it will never attempt to load the session data (parse the cookie, load the data from memcache, or lookup an Active Record object).
-* +CGI::Session::CookieStore+ has been replaced by +ActionController::Session::CookieStore+
-* +CGI::Session::MemCacheStore+ has been replaced by +ActionController::Session::MemCacheStore+
-* +CGI::Session::ActiveRecordStore+ has been replaced by +ActiveRecord::SessionStore+
-* You can still change your session store with +ActionController::Base.session_store = :active_record_store+
-* Default sessions options are still set with +ActionController::Base.session = { :key => "..." }+
-* The mutex that normally wraps your entire request has been moved into middleware, +ActionController::Lock+
+* You no longer need to use +CGI::Cookie.new+ in your tests for setting a cookie value. Assigning a +String+ value to request.cookies["foo"] now sets the cookie as expected.
+* +CGI::Session::CookieStore+ has been replaced by +ActionController::Session::CookieStore+.
+* +CGI::Session::MemCacheStore+ has been replaced by +ActionController::Session::MemCacheStore+.
+* +CGI::Session::ActiveRecordStore+ has been replaced by +ActiveRecord::SessionStore+.
+* You can still change your session store with +ActionController::Base.session_store = :active_record_store+.
+* Default sessions options are still set with +ActionController::Base.session = { :key => "..." }+.
+* The mutex that normally wraps your entire request has been moved into middleware, +ActionController::Lock+.
* +ActionController::AbstractRequest+ and +ActionController::Request+ have been unified. The new +ActionController::Request+ inherits from +Rack::Request+. This affects access to +response.headers['type']+ in test requests. Use +response.content_type+ instead.
* +ActiveRecord::QueryCache+ middleware is automatically inserted onto the middleware stack if +ActiveRecord+ has been loaded. This middleware sets up and flushes the per-request Active Record query cache.
* The Rails router and controller classes follow the Rack spec. You can call a controller directly with +SomeController.call(env)+. The router stores the routing parameters in +rack.routing_args+.
-* +ActionController::Request+ inherits from +Rack::Request+
-* Instead of +config.action_controller.session = { :session_key => 'foo', ...+ use +config.action_controller.session = { :key => 'foo', ...+
+* +ActionController::Request+ inherits from +Rack::Request+.
+* Instead of +config.action_controller.session = { :session_key => 'foo', ...+ use +config.action_controller.session = { :key => 'foo', ...+.
* Using the +ParamsParser+ middleware preprocesses any XML, JSON, or YAML requests so they can be read normally with any +Rack::Request+ object after it.
h4. Renewed Support for Rails Engines
@@ -50,7 +49,7 @@ h3. Documentation
The "Ruby on Rails guides":http://guides.rubyonrails.org/ project has published several additional guides for Rails 2.3. In addition, a "separate site":http://guides.rails.info/ maintains updated copies of the Guides for Edge Rails. Other documentation efforts include a relaunch of the "Rails wiki":http://newwiki.rubyonrails.org/ and early planning for a Rails Book.
-* More Information: "Rails Documentation Projects":http://weblog.rubyonrails.org/2009/1/15/rails-documentation-projects
+* More Information: "Rails Documentation Projects":http://weblog.rubyonrails.org/2009/1/15/rails-documentation-projects.
h3. Ruby 1.9.1 Support
@@ -140,19 +139,19 @@ end
You can pass most of the +find+ options into +find_in_batches+. However, you cannot specify the order that records will be returned in (they will always be returned in ascending order of primary key, which must be an integer), or use the +:limit+ option. Instead, use the +:batch_size+ option, which defaults to 1000, to set the number of records that will be returned in each batch.
-The new +each+ method provides a wrapper around +find_in_batches+ that returns individual records, with the find itself being done in batches (of 1000 by default):
+The new +find_each+ method provides a wrapper around +find_in_batches+ that returns individual records, with the find itself being done in batches (of 1000 by default):
<ruby>
-Customer.each do |customer|
+Customer.find_each do |customer|
customer.update_account_balance!
end
</ruby>
Note that you should only use this method for batch processing: for small numbers of records (less than 1000), you should just use the regular find methods with your own loop.
-* More Information:
- - "Rails 2.3: Batch Finding":http://afreshcup.com/2009/02/23/rails-23-batch-finding/
- - "What's New in Edge Rails: Batched Find":http://ryandaigle.com/articles/2009/2/23/what-s-new-in-edge-rails-batched-find
+* More Information (at that point the convenience method was called just +each+):
+** "Rails 2.3: Batch Finding":http://afreshcup.com/2009/02/23/rails-23-batch-finding/
+** "What's New in Edge Rails: Batched Find":http://ryandaigle.com/articles/2009/2/23/what-s-new-in-edge-rails-batched-find
h4. Multiple Conditions for Callbacks
@@ -175,18 +174,6 @@ developers = Developer.find(:all, :group => "salary",
* Lead Contributor: "Emilio Tagua":http://github.com/miloops
-h4. Hash Conditions for has_many relationships
-
-You can once again use a hash in conditions for a +has_many+ relationship:
-
-<ruby>
-has_many :orders, :conditions => {:status => 'confirmed'}
-</ruby>
-
-That worked in Rails 2.1, fails in Rails 2.2, and will now work again in Rails 2.3 (if you're dealing with this issue in Rails 2.2, you can use a string rather than a hash to specify conditions).
-
-* Lead Contributor: "Frederick Cheung":http://www.spacevatican.org/
-
h4. Reconnecting MySQL Connections
MySQL supports a reconnect flag in its connections - if set to true, then the client will try reconnecting to the server before giving up in case of a lost connection. You can now set +reconnect = true+ for your MySQL connections in +database.yml+ to get this behavior from a Rails application. The default is +false+, so the behavior of existing applications doesn't change.
@@ -198,15 +185,17 @@ MySQL supports a reconnect flag in its connections - if set to true, then the cl
h4. Other Active Record Changes
-* An extra +AS+ was removed from the generated SQL for has_and_belongs_to_many preloading, making it work better for some databases.
+* An extra +AS+ was removed from the generated SQL for +has_and_belongs_to_many+ preloading, making it work better for some databases.
* +ActiveRecord::Base#new_record?+ now returns +false+ rather than +nil+ when confronted with an existing record.
* A bug in quoting table names in some +has_many :through+ associations was fixed.
* You can now specify a particular timestamp for +updated_at+ timestamps: +cust = Customer.create(:name => "ABC Industries", :updated_at => 1.day.ago)+
* Better error messages on failed +find_by_attribute!+ calls.
* Active Record's +to_xml+ support gets just a little bit more flexible with the addition of a +:camelize+ option.
-* A bug in canceling callbacks from +before_update+ or +before_create_ was fixed.
+* A bug in canceling callbacks from +before_update+ or +before_create+ was fixed.
* Rake tasks for testing databases via JDBC have been added.
-* +validates_length_of+ will use a custom error message with the +:in+ or +:within+ options (if one is supplied)
+* +validates_length_of+ will use a custom error message with the +:in+ or +:within+ options (if one is supplied).
+* Counts on scoped selects now work properly, so you can do things like +Account.scoped(:select => "DISTINCT credit_limit").count+.
+* +ActiveRecord::Base#invalid?+ now works as the opposite of +ActiveRecord::Base#valid?+.
h3. Action Controller
@@ -299,7 +288,7 @@ In some of the first fruits of the Rails-Merb team merger, Rails 2.3 includes so
h4. Improved Caching Performance
-Rails now keeps a per-request local cache of requests, cutting down on unnecessary reads and leading to better site performance. While this work was originally limited to +MemCacheStore+, it is available to any remote store than implements the required methods.
+Rails now keeps a per-request local cache of read from the remote cache stores, cutting down on unnecessary reads and leading to better site performance. While this work was originally limited to +MemCacheStore+, it is available to any remote store than implements the required methods.
* Lead Contributor: "Nahum Wild":http://www.motionstandingstill.com/
@@ -307,6 +296,8 @@ h4. Localized Views
Rails can now provide localized views, depending on the locale that you have set. For example, suppose you have a +Posts+ controller with a +show+ action. By default, this will render +app/views/posts/show.html.erb+. But if you set +I18n.locale = :da+, it will render +app/views/posts/show.da.html.erb+. If the localized template isn't present, the undecorated version will be used. Rails also includes +I18n#available_locales+ and +I18n::SimpleBackend#available_locales+, which return an array of the translations that are available in the current Rails project.
+In addition, you can use the same scheme to localize the rescue files in the +public+ directory: +public/500.da.html+ or +public/404.en.html+ work, for example.
+
h4. Partial Scoping for Translations
A change to the translation API makes things easier and less repetitive to write key translations within partials. If you call +translate(".foo")+ from the +people/index.html.erb+ template, you'll actually be calling +I18n.translate("people.index.foo")+ If you don't prepend the key with a period, then the API doesn't scope, just as before.
@@ -321,6 +312,9 @@ h4. Other Action Controller Changes
* The +:only+ and +:except+ options for +map.resources+ are no longer inherited by nested resources.
* The bundled memcached client has been updated to version 1.6.4.99.
* The +expires_in+, +stale?+, and +fresh_when+ methods now accept a +:public+ option to make them work well with proxy caching.
+* The +:requirements+ option now works properly with additional RESTful member routes.
+* Shallow routes now properly respect namespaces.
+* +polymorphic_url+ does a better job of handling objects with irregular plural names.
h3. Action View
@@ -439,6 +433,34 @@ returns
</optgroup>
</ruby>
+h4. Disabled Option Tags for Form Select Helpers
+
+The form select helpers (such as +select+ and +options_for_select+) now support a +:disabled+ option, which can take a single value or an array of values to be disabled in the resulting tags:
+
+<ruby>
+select(:post, :category, Post::CATEGORIES, :disabled => ‘private‘)
+</ruby>
+
+returns
+
+<ruby>
+<select name=“post[category]“>
+<option>story</option>
+<option>joke</option>
+<option>poem</option>
+<option disabled=“disabled“>private</option>
+</select>
+</ruby>
+
+You can also use an anonymous function to determine at runtime which options from collections will be selected and/or disabled:
+
+<ruby>
+options_from_collection_for_select(@product.sizes, :name, :id, :disabled => lambda{|size| size.out_of_stock?})
+</ruby>
+
+* Lead Contributor: "Tekin Suleyman":http://tekin.co.uk/
+* More Information: "New in rails 2.3 - disabled option tags and lambdas for selecting and disabling options from collections":http://tekin.co.uk/2009/03/new-in-rails-23-disabled-option-tags-and-lambdas-for-selecting-and-disabling-options-from-collections/
+
h4. A Note About Template Loading
Rails 2.3 includes the ability to enable or disable cached templates for any particular environment. Cached templates give you a speed boost because they don't check for a new template file when they're rendered - but they also mean that you can't replace a template "on the fly" without restarting the server.
@@ -472,6 +494,17 @@ h4. Object#tap Backport
+Object#tap+ is an addition to "Ruby 1.9":http://www.ruby-doc.org/core-1.9/classes/Object.html#M000309 and 1.8.7 that is similar to the +returning+ method that Rails has had for a while: it yields to a block, and then returns the object that was yielded. Rails now includes code to make this available under older versions of Ruby as well.
+h4. Swappable Parsers for XMLmini
+
+The support for XML parsing in ActiveSupport has been made more flexible by allowing you to swap in different parsers. By default, it uses the standard REXML implementation, but you can easily specify the faster LibXML or Nokogiri implementations for your own applications, provided you have the appropriate gems installed:
+
+<ruby>
+XmlMini.backend = 'LibXML'
+</ruby>
+
+* Lead Contributor: "Bart ten Brinke":http://www.movesonrails.com/
+* Lead Contributor: "Aaron Patterson":http://tenderlovemaking.com/
+
h4. Fractional seconds for TimeWithZone
The +Time+ and +TimeWithZone+ classes include an +xmlschema+ method to return the time in an XML-friendly string. As of Rails 2.3, +TimeWithZone+ supports the same argument for specifying the number of digits in the fractional second part of the returned string that +Time+ does:
@@ -494,6 +527,10 @@ h4. Other Active Support Changes
* +ActiveSupport::OrderedHash+: now implements +each_key+ and +each_value+.
* +ActiveSupport::MessageEncryptor+ provides a simple way to encrypt information for storage in an untrusted location (like cookies).
* Active Support's +from_xml+ no longer depends on XmlSimple. Instead, Rails now includes its own XmlMini implementation, with just the functionality that it requires. This lets Rails dispense with the bundled copy of XmlSimple that it's been carting around.
+* If you memoize a private method, the result will now be private.
+* +String#parameterize+ accepts an optional separator: +"Quick Brown Fox".parameterize('_') => "quick_brown_fox"+.
+* +number_to_phone+ accepts 7-digit phone numbers now.
+* +ActiveSupport::Json.decode+ now handles +\u0000+ style escape sequences.
h3. Railties
@@ -532,6 +569,12 @@ Quite a bit of work was done to make sure that bits of Rails (and its dependenci
You can also specify (by using the new +preload_frameworks+ option) whether the core libraries should be autoloaded at startup. This defaults to +false+ so that Rails autoloads itself piece-by-piece, but there are some circumstances where you still need to bring in everything at once - Passenger and JRuby both want to see all of Rails loaded together.
+h4. rake gem Task Rewrite
+
+The internals of the various <code>rake gem</code> tasks have been substantially revised, to make the system work better for a variety of cases. The gem system now knows the difference between development and runtime dependencies, has a more robust unpacking system, gives better information when querying for the status of gems, and is less prone to "chicken and egg" dependency issues when you're bringing things up from scratch. There are also fixes for using gem commands under JRuby and for dependencies that try to bring in external copies of gems that are already vendored.
+
+* Lead Contributor: "David Dollar":http://www.workingwithrails.com/person/12240-david-dollar
+
h4. Other Railties Changes
* The instructions for updating a CI server to build Rails have been updated and expanded.
@@ -543,6 +586,8 @@ h4. Other Railties Changes
* Rails Guides have been converted from AsciiDoc to Textile markup.
* Scaffolded views and controllers have been cleaned up a bit.
* +script/server+ now accepts a <tt>--path</tt> argument to mount a Rails application from a specific path.
+* If any configured gems are missing, the gem rake tasks will skip loading much of the environment. This should solve many of the "chicken-and-egg" problems where rake gems:install couldn't run because gems were missing.
+* Gems are now unpacked exactly once. This fixes issues with gems (hoe, for instance) which are packed with read-only permissions on the files.
h3. Deprecated
View
32 railties/guides/source/action_controller_overview.textile
@@ -20,7 +20,7 @@ For most conventional RESTful applications, the controller will receive the requ
A controller can thus be thought of as a middle man between models and views. It makes the model data available to the view so it can display that data to the user, and it saves or updates data from the user to the model.
-NOTE: For more details on the routing process, see "Rails Routing from the Outside In":routing_outside_in.html.
+NOTE: For more details on the routing process, see "Rails Routing from the Outside In":routing.html.
h3. Methods and Actions
@@ -83,7 +83,7 @@ class ClientsController < ActionController::Base
end
</ruby>
-h4. Hash and array parameters
+h4. Hash and Array Parameters
The +params+ hash is not limited to one-dimensional keys and values. It can contain arrays and (nested) hashes. To send an array of values, append an empty pair of square brackets "[]" to the key name:
@@ -123,7 +123,7 @@ map.connect "/clients/:status",
In this case, when a user opens the URL +/clients/active+, +params[:status]+ will be set to "active". When this route is used, +params[:foo]+ will also be set to "bar" just like it was passed in the query string. In the same way +params[:action]+ will contain "index".
-h4. default_url_options
+h4. +default_url_options+
You can set global default parameters that will be used when generating URLs with +default_url_options+. To do this, define a method with that name in your controller:
@@ -180,7 +180,7 @@ ActionController::Base.session = {
NOTE: Changing the secret when using the CookieStore will invalidate all existing sessions.
-h4. Accessing the session
+h4. Accessing the Session
In your controller you can access the session through the +session+ instance method.
@@ -235,7 +235,7 @@ end
To reset the entire session, use +reset_session+.
-h4. The flash
+h4. The Flash
The flash is a special part of the session which is cleared with each request. This means that values stored there will only be available in the next request, which is useful for storing error messages etc. It is accessed in much the same way as the session, like a hash. Let's use the act of logging out as an example. The controller can send a message which will be displayed to the user on the next request:
@@ -288,7 +288,7 @@ class MainController < ApplicationController
end
</ruby>
-h5. flash.now
+h5. +flash.now+
By default, adding values to the flash will make them available to the next request, but sometimes you may want to access those values in the same request. For example, if the +create+ action fails to save a resource and you render the +new+ template directly, that's not going to result in a new request, but you may still want to display a message using the flash. To do this, you can use +flash.now+ in the same way you use the normal +flash+:
@@ -381,7 +381,7 @@ end
Now, the +LoginsController+'s +new+ and +create+ actions will work as before without requiring the user to be logged in. The +:only+ option is used to only skip this filter for these actions, and there is also an +:except+ option which works the other way. These options can be used when adding filters too, so you can add a filter which only runs for selected actions in the first place.
-h4. After filters and around filters
+h4. After Filters and Around Filters
In addition to before filters, you can run filters after an action has run or both before and after. The after filter is similar to the before filter, but because the action has already been run it has access to the response data that's about to be sent to the client. Obviously, after filters can not stop the action from running.
@@ -403,7 +403,7 @@ private
end
</ruby>
-h4. Other ways to use filters
+h4. Other Ways to Use Filters
While the most common way to use filters is by creating private methods and using *_filter to add them, there are two other ways to do the same thing.
@@ -517,7 +517,7 @@ h3. The Request and Response Objects
In every controller there are two accessor methods pointing to the request and the response objects associated with the request cycle that is currently in execution. The +request+ method contains an instance of +AbstractRequest+ and the +response+ method returns a response object representing what is going to be sent back to the client.
-h4. The +request+ object
+h4. The +request+ Object
The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the "API documentation":http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html. Among the properties that you can access on this object are:
@@ -538,7 +538,7 @@ h5. +path_parameters+, +query_parameters+, and +request_parameters+
Rails collects all of the parameters sent along with the request in the +params+ hash, whether they are sent as part of the query string or the post body. The request object has three accessors that give you access to these parameters depending on where they came from. The +query_parameters+ hash contains parameters that were sent as part of the query string while the +request_parameters+ hash contains parameters sent as part of the post body. The +path_parameters+ hash contains parameters that were recognized by the routing as being part of the path leading to this particular controller and action.
-h4. The response object
+h4. The +response+ Object
The response object is not usually used directly, but is built up during the execution of the action and rendering of the data that is being sent back to the user, but sometimes - like in an after filter - it can be useful to access the response directly. Some of these accessor methods also have setters, allowing you to change their values.
@@ -550,7 +550,7 @@ The response object is not usually used directly, but is built up during the exe
|charset|The character set being used for the response. Default is "utf-8".|
|headers|Headers used for the response.|
-h5. Setting custom headers
+h5. Setting Custom Headers
If you want to set custom headers for a response then +response.headers+ is the place to do it. The headers attribute is a hash which maps header names to their values, and Rails will set some of them automatically. If you want to add or change a header, just assign it to +response.headers+ this way:
@@ -565,7 +565,7 @@ Rails comes with two built-in HTTP authentication mechanisms:
* Basic Authentication
* Digest Authentication
-h4. HTTP basic authentication
+h4. HTTP Basic Authentication
HTTP basic authentication is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider an administration section which will only be available by entering a username and a password into the browser's HTTP basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, +authenticate_or_request_with_http_basic+.
@@ -587,7 +587,7 @@ end
With this in place, you can create namespaced controllers that inherit from +AdminController+. The before filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication.
-h4. HTTP digest authentication
+h4. HTTP Digest Authentication
HTTP digest authentication is superior to the basic authentication as it does not require the client to send an unencrypted password over the network (though HTTP basic authentication is safe over HTTPS). Using digest authentication with Rails is quite easy and only requires using one method, +authenticate_or_request_with_http_digest+.
@@ -640,7 +640,7 @@ end
The +download_pdf+ action in the example above will call a private method which actually generates the PDF document and returns it as a string. This string will then be streamed to the client as a file download and a filename will be suggested to the user. Sometimes when streaming files to the user, you may not want them to download the file. Take images, for example, which can be embedded into HTML pages. To tell the browser a file is not meant to be downloaded, you can set the +:disposition+ option to "inline". The opposite and default value for this option is "attachment".
-h4. Sending files
+h4. Sending Files
If you want to send a file that already exists on disk, use the +send_file+ method.
@@ -662,7 +662,7 @@ WARNING: Be careful when using data coming from the client (params, cookies, etc
TIP: It is not recommended that you stream static files through Rails if you can instead keep them in a public folder on your web server. It is much more efficient to let the user download the file directly using Apache or another web server, keeping the request from unnecessarily going through the whole Rails stack. Although if you do need the request to go through Rails for some reason, you can set the +:x_sendfile+ option to true, and Rails will let the web server handle sending the file to the user, freeing up the Rails process to do other things. Note that your web server needs to support the +X-Sendfile+ header for this to work.
-h4. RESTful downloads
+h4. RESTful Downloads
While +send_data+ works just fine, if you are creating a RESTful application having separate actions for file downloads is usually not necessary. In REST terminology, the PDF file from the example above can be considered just another representation of the client resource. Rails provides an easy and quite sleek way of doing "RESTful downloads". Here's how you can rewrite the example so that the PDF download is a part of the +show+ action, without any streaming:
@@ -712,7 +712,7 @@ Most likely your application is going to contain bugs or otherwise throw an exce
Rails' default exception handling displays a "500 Server Error" message for all exceptions. If the request was made locally, a nice traceback and some added information gets displayed so you can figure out what went wrong and deal with it. If the request was remote Rails will just display a simple "500 Server Error" message to the user, or a "404 Not Found" if there was a routing error or a record could not be found. Sometimes you might want to customize how these errors are caught and how they're displayed to the user. There are several levels of exception handling available in a Rails application:
-h4. The default 500 and 404 templates
+h4. The Default 500 and 404 Templates
By default a production application will render either a 404 or a 500 error message. These messages are contained in static HTML files in the +public+ folder, in +404.html+ and +500.html+ respectively. You can customize these files to add some extra information and layout, but remember that they are static; i.e. you can't use RHTML or layouts in them, just plain HTML.
View
60 railties/guides/source/action_mailer_basics.textile
@@ -12,9 +12,9 @@ h3. Sending Emails
This section will provide a step-by-step guide to creating a mailer and its views.
-h4. Walkthrough to generating a mailer
+h4. Walkthrough to Generating a Mailer
-h5. Create the mailer:
+h5. Create the Mailer
<shell>
./script/generate mailer UserMailer
@@ -28,7 +28,7 @@ create test/unit/user_mailer_test.rb
So we got the model, the fixtures, and the tests.
-h5. Edit the model:
+h5. Edit the Model
+app/models/user_mailer.rb+ contains an empty mailer:
@@ -60,7 +60,7 @@ Here is a quick explanation of the options presented in the preceding method. Fo
The keys of the hash passed to +body+ become instance variables in the view. Thus, in our example the mailer view will have a +@user+ and a +@url+ instance variables available.
-h5. Create a mailer view
+h5. Create a Mailer View
Create a file called +welcome_email.text.html.erb+ in +app/views/user_mailer/+. This will be the template used for the email, formatted in HTML:
@@ -83,7 +83,7 @@ Create a file called +welcome_email.text.html.erb+ in +app/views/user_mailer/+.
Had we wanted to send text-only emails, the file would have been called +welcome_email.text.plain.erb+. Rails sets the content type of the email to be the one in the filename.
-h5. Wire it up so that the system sends the email when a user signs up
+h5. Wire It Up So That the System Sends the Email When a User Signs Up
There are three ways to achieve this. One is to send the email from the controller that sends the email, another is to put it in a +before_create+ callback in the user model, and the last one is to use an observer on the user model. Whether you use the second or third methods is up to you, but staying away from the first is recommended. Not because it's wrong, but because it keeps your controller clean, and keeps all logic related to the user model within the user model. This way, whichever way a user is created (from a web form, or from an API call, for example), we are guaranteed that the email will be sent.
@@ -112,7 +112,7 @@ end
Notice how we call +deliver_welcome_email+? In Action Mailer we send emails by calling +deliver_&lt;method_name&gt;+. In UserMailer, we defined a method called +welcome_email+, and so we deliver the email by calling +deliver_welcome_email+. The next section will go through how Action Mailer achieves this.
-h4. Action Mailer and dynamic deliver_&lt;method_name&gt; methods
+h4. Action Mailer and Dynamic +deliver_&lt;method_name&gt;+ methods