aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--actionpack/CHANGELOG.md7
-rw-r--r--actionpack/lib/abstract_controller/base.rb28
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb2
-rw-r--r--actionpack/test/controller/new_base/render_implicit_action_test.rb17
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb31
-rw-r--r--actionview/test/actionpack/abstract/render_test.rb16
-rw-r--r--actionview/test/actionpack/controller/render_test.rb6
-rw-r--r--activerecord/lib/active_record/associations/association_scope.rb9
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb10
-rw-r--r--activerecord/lib/active_record/associations/has_many_through_association.rb2
-rw-r--r--activerecord/lib/active_record/reflection.rb5
-rw-r--r--activesupport/CHANGELOG.md12
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb38
-rw-r--r--activesupport/test/inflector_test_cases.rb8
-rw-r--r--guides/rails_guides.rb4
-rw-r--r--guides/rails_guides/helpers.rb2
-rw-r--r--guides/rails_guides/markdown.rb10
-rw-r--r--guides/rails_guides/markdown/renderer.rb2
-rw-r--r--guides/source/2_3_release_notes.md4
-rw-r--r--guides/source/3_0_release_notes.md2
-rw-r--r--guides/source/active_record_postgresql.md338
-rw-r--r--guides/source/active_support_core_extensions.md29
-rw-r--r--guides/source/active_support_instrumentation.md2
-rw-r--r--guides/source/index.html.erb1
-rw-r--r--guides/source/layout.html.erb4
-rw-r--r--guides/w3c_validator.rb2
-rw-r--r--railties/lib/rails/commands/dbconsole.rb2
28 files changed, 521 insertions, 74 deletions
diff --git a/Gemfile b/Gemfile
index e7bc2585a7..0e7c6dc755 100644
--- a/Gemfile
+++ b/Gemfile
@@ -25,7 +25,7 @@ gem 'uglifier', '>= 1.3.0', require: false
group :doc do
gem 'sdoc', '~> 0.4.0'
- gem 'redcarpet', '~> 2.2.2', platforms: :ruby
+ gem 'redcarpet', '~> 3.1.0', platforms: :ruby
gem 'w3c_validators'
gem 'kindlerb'
end
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 7427fba5e2..d52ccd3d5e 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,10 @@
+* Moved `params[request_forgery_protection_token]` into its own method
+ and improved tests.
+
+ Fixes #11316.
+
+ *Tom Kadwill*
+
* Added verification of route constraints given as a Proc or an object responding
to `:matches?`. Previously, when given an non-complying object, it would just
silently fail to enforce the constraint. It will now raise an `ArgumentError`
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index de14b59f8e..6d200a0333 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -127,7 +127,7 @@ module AbstractController
def process(action, *args)
@_action_name = action.to_s
- unless action_name = method_for_action(@_action_name)
+ unless action_name = _find_action_name(@_action_name)
raise ActionNotFound, "The action '#{action}' could not be found for #{self.class.name}"
end
@@ -160,7 +160,7 @@ module AbstractController
# ==== Returns
# * <tt>TrueClass</tt>, <tt>FalseClass</tt>
def available_action?(action_name)
- method_for_action(action_name).present?
+ _find_action_name(action_name).present?
end
private
@@ -204,6 +204,23 @@ module AbstractController
end
# Takes an action name and returns the name of the method that will
+ # handle the action.
+ #
+ # It checks if the action name is valid and returns false otherwise.
+ #
+ # See method_for_action for more information.
+ #
+ # ==== Parameters
+ # * <tt>action_name</tt> - An action name to find a method name for
+ #
+ # ==== Returns
+ # * <tt>string</tt> - The name of the method that handles the action
+ # * false - No valid method name could be found. Raise ActionNotFound.
+ def _find_action_name(action_name)
+ _valid_action_name?(action_name) && method_for_action(action_name)
+ end
+
+ # Takes an action name and returns the name of the method that will
# handle the action. In normal cases, this method returns the same
# name as it receives. By default, if #method_for_action receives
# a name that is not an action, it will look for an #action_missing
@@ -225,7 +242,7 @@ module AbstractController
#
# ==== Returns
# * <tt>string</tt> - The name of the method that handles the action
- # * <tt>nil</tt> - No method name could be found. Raise ActionNotFound.
+ # * <tt>nil</tt> - No method name could be found.
def method_for_action(action_name)
if action_method?(action_name)
action_name
@@ -233,5 +250,10 @@ module AbstractController
"_handle_action_missing"
end
end
+
+ # Checks if the action name is valid and returns false otherwise.
+ def _valid_action_name?(action_name)
+ action_name.to_s !~ Regexp.new(File::SEPARATOR)
+ end
end
end
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index e3b1f5ae7c..1355fe87d0 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -247,7 +247,7 @@ module ActionController #:nodoc:
# * Does the X-CSRF-Token header match the form_authenticity_token
def verified_request?
!protect_against_forgery? || request.get? || request.head? ||
- form_authenticity_token == params[request_forgery_protection_token] ||
+ form_authenticity_token == form_authenticity_param ||
form_authenticity_token == request.headers['X-CSRF-Token']
end
diff --git a/actionpack/test/controller/new_base/render_implicit_action_test.rb b/actionpack/test/controller/new_base/render_implicit_action_test.rb
index 1e2191d417..5b4885f7e0 100644
--- a/actionpack/test/controller/new_base/render_implicit_action_test.rb
+++ b/actionpack/test/controller/new_base/render_implicit_action_test.rb
@@ -6,7 +6,7 @@ module RenderImplicitAction
"render_implicit_action/simple/hello_world.html.erb" => "Hello world!",
"render_implicit_action/simple/hyphen-ated.html.erb" => "Hello hyphen-ated!",
"render_implicit_action/simple/not_implemented.html.erb" => "Not Implemented"
- )]
+ ), ActionView::FileSystemResolver.new(File.expand_path('../../../controller', __FILE__))]
def hello_world() end
end
@@ -33,10 +33,25 @@ module RenderImplicitAction
assert_status 200
end
+ test "render does not traverse the file system" do
+ assert_raises(AbstractController::ActionNotFound) do
+ action_name = %w(.. .. fixtures shared).join(File::SEPARATOR)
+ SimpleController.action(action_name).call(Rack::MockRequest.env_for("/"))
+ end
+ end
+
test "available_action? returns true for implicit actions" do
assert SimpleController.new.available_action?(:hello_world)
assert SimpleController.new.available_action?(:"hyphen-ated")
assert SimpleController.new.available_action?(:not_implemented)
end
+
+ test "available_action? does not allow File::SEPARATOR on the name" do
+ action_name = %w(evil .. .. path).join(File::SEPARATOR)
+ assert_equal false, SimpleController.new.available_action?(action_name.to_sym)
+
+ action_name = %w(evil path).join(File::SEPARATOR)
+ assert_equal false, SimpleController.new.available_action?(action_name.to_sym)
+ end
end
end
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index 5ab5141966..07c2115832 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -462,16 +462,37 @@ end
class CustomAuthenticityParamControllerTest < ActionController::TestCase
def setup
super
- ActionController::Base.request_forgery_protection_token = :custom_token_name
+ @old_logger = ActionController::Base.logger
+ @logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
+ @token = "foobar"
+ ActionController::Base.request_forgery_protection_token = @token
end
def teardown
- ActionController::Base.request_forgery_protection_token = :authenticity_token
+ ActionController::Base.request_forgery_protection_token = nil
super
end
- def test_should_allow_custom_token
- post :index, :custom_token_name => 'foobar'
- assert_response :ok
+ def test_should_not_warn_if_form_authenticity_param_matches_form_authenticity_token
+ ActionController::Base.logger = @logger
+ SecureRandom.stubs(:base64).returns(@token)
+
+ begin
+ post :index, :custom_token_name => 'foobar'
+ assert_equal 0, @logger.logged(:warn).size
+ ensure
+ ActionController::Base.logger = @old_logger
+ end
+ end
+
+ def test_should_warn_if_form_authenticity_param_does_not_match_form_authenticity_token
+ ActionController::Base.logger = @logger
+
+ begin
+ post :index, :custom_token_name => 'bazqux'
+ assert_equal 1, @logger.logged(:warn).size
+ ensure
+ ActionController::Base.logger = @old_logger
+ end
end
end
diff --git a/actionview/test/actionpack/abstract/render_test.rb b/actionview/test/actionpack/abstract/render_test.rb
index f9d8c916d9..d09f91c1e2 100644
--- a/actionview/test/actionpack/abstract/render_test.rb
+++ b/actionview/test/actionpack/abstract/render_test.rb
@@ -60,42 +60,42 @@ module AbstractController
end
def test_render_template
- @controller.process(:template)
+ assert_equal "With Template", @controller.process(:template)
assert_equal "With Template", @controller.response_body
end
def test_render_file
- @controller.process(:file)
+ assert_equal "With File", @controller.process(:file)
assert_equal "With File", @controller.response_body
end
def test_render_inline
- @controller.process(:inline)
+ assert_equal "With Inline", @controller.process(:inline)
assert_equal "With Inline", @controller.response_body
end
def test_render_text
- @controller.process(:text)
+ assert_equal "With Text", @controller.process(:text)
assert_equal "With Text", @controller.response_body
end
def test_render_default
- @controller.process(:default)
+ assert_equal "With Default", @controller.process(:default)
assert_equal "With Default", @controller.response_body
end
def test_render_string
- @controller.process(:string)
+ assert_equal "With String", @controller.process(:string)
assert_equal "With String", @controller.response_body
end
def test_render_symbol
- @controller.process(:symbol)
+ assert_equal "With Symbol", @controller.process(:symbol)
assert_equal "With Symbol", @controller.response_body
end
def test_render_string_with_path
- @controller.process(:string_with_path)
+ assert_equal "With String With Path", @controller.process(:string_with_path)
assert_equal "With String With Path", @controller.response_body
end
end
diff --git a/actionview/test/actionpack/controller/render_test.rb b/actionview/test/actionpack/controller/render_test.rb
index 45b8049b83..ab7b961ed2 100644
--- a/actionview/test/actionpack/controller/render_test.rb
+++ b/actionview/test/actionpack/controller/render_test.rb
@@ -720,6 +720,11 @@ class RenderTest < ActionController::TestCase
assert_equal "Elastica", @response.body
end
+ def test_render_process
+ get :render_action_hello_world_as_string
+ assert_equal ["Hello world!"], @controller.process(:render_action_hello_world_as_string)
+ end
+
# :ported:
def test_render_from_variable
get :render_hello_world_from_variable
@@ -1332,4 +1337,3 @@ class RenderTest < ActionController::TestCase
assert_equal "Before (Anthony)\nInside from partial (Anthony)\nAfter\nBefore (David)\nInside from partial (David)\nAfter\nBefore (Ramm)\nInside from partial (Ramm)\nAfter", @response.body
end
end
-
diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb
index f1a3b23d5a..572f556999 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -47,15 +47,8 @@ module ActiveRecord
def self.get_bind_values(owner, chain)
bvs = []
chain.each_with_index do |reflection, i|
- if reflection.source_macro == :belongs_to
- foreign_key = reflection.foreign_key
- else
- foreign_key = reflection.active_record_primary_key
- end
-
if reflection == chain.last
- bvs << owner[foreign_key]
-
+ bvs << reflection.join_id_for(owner)
if reflection.type
bvs << owner.class.base_class.name
end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 1c84973920..48628230c7 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -194,7 +194,7 @@ module ActiveRecord
options[:dependent]
end
- delete_all_with_dependency(dependent).tap do
+ delete_records(:all, dependent).tap do
reset
loaded!
end
@@ -251,14 +251,6 @@ module ActiveRecord
delete_or_destroy(records, dependent)
end
- def delete_all_with_dependency(dependent)
- if dependent == :destroy
- delete_or_destroy(load_target, dependent)
- else
- delete_records(:all, dependent)
- end
- end
-
# Deletes the +records+ and removes them from this association calling
# +before_remove+ , +after_remove+ , +before_destroy+ and +after_destroy+ callbacks.
#
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index f3af8605cd..cdabf02b95 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -72,7 +72,7 @@ module ActiveRecord
@through_association ||= owner.association(through_reflection.name)
end
- # We temporarily cache through record that has been build, because if we build a
+ # We temporarily cache through record that has been built, because if we build a
# through record in build_record and then subsequently call insert_record, then we
# want to use the exact same object.
#
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 95485ddada..7f4d77849a 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -278,6 +278,11 @@ module ActiveRecord
end
end
+ def join_id_for(owner) #:nodoc:
+ key = (source_macro == :belongs_to) ? foreign_key : active_record_primary_key
+ owner[key]
+ end
+
def through_reflection
nil
end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 36955e5ca6..8e63273271 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,15 @@
+* `humanize` strips leading underscores, if any.
+
+ Before:
+
+ '_id'.humanize # => ""
+
+ After:
+
+ '_id'.humanize # => "Id"
+
+ *Xavier Noria*
+
* Fixed backward compatibility isues introduced in 326e652.
Empty Hash or Array should not present in serialization result.
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
index 69f77453e7..51720d0192 100644
--- a/activesupport/lib/active_support/inflector/methods.rb
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -99,26 +99,46 @@ module ActiveSupport
word
end
- # Capitalizes the first word, turns underscores into spaces, and strips a
- # trailing '_id' if present.
- # Like +titleize+, this is meant for creating pretty output.
+ # Tweaks an attribute name for display to end users.
+ #
+ # Specifically, +humanize+ performs these transformations:
+ #
+ # * Applies human inflection rules to the argument.
+ # * Deletes leading underscores, if any.
+ # * Removes a "_id" suffix if present.
+ # * Replaces underscores with spaces, if any.
+ # * Downcases all words except acronyms.
+ # * Capitalizes the first word.
#
# The capitalization of the first word can be turned off by setting the
- # optional parameter +capitalize+ to false.
- # By default, this parameter is true.
+ # +:capitalize+ option to false (default is true).
#
# humanize('employee_salary') # => "Employee salary"
# humanize('author_id') # => "Author"
# humanize('author_id', capitalize: false) # => "author"
+ # humanize('_id') # => "Id"
+ #
+ # If "SSL" was defined to be an acronym:
+ #
+ # humanize('ssl_error') # => "SSL error"
+ #
def humanize(lower_case_and_underscored_word, options = {})
result = lower_case_and_underscored_word.to_s.dup
+
inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
- result.gsub!(/_id$/, "")
+
+ result.sub!(/\A_+/, '')
+ result.sub!(/_id\z/, '')
result.tr!('_', ' ')
- result.gsub!(/([a-z\d]*)/i) { |match|
+
+ result.gsub!(/([a-z\d]*)/i) do |match|
"#{inflections.acronyms[match] || match.downcase}"
- }
- result.gsub!(/^\w/) { |match| match.upcase } if options.fetch(:capitalize, true)
+ end
+
+ if options.fetch(:capitalize, true)
+ result.sub!(/\A\w/) { |match| match.upcase }
+ end
+
result
end
diff --git a/activesupport/test/inflector_test_cases.rb b/activesupport/test/inflector_test_cases.rb
index dd03a61176..b556da0046 100644
--- a/activesupport/test/inflector_test_cases.rb
+++ b/activesupport/test/inflector_test_cases.rb
@@ -208,9 +208,11 @@ module InflectorTestCases
}
UnderscoreToHuman = {
- "employee_salary" => "Employee salary",
- "employee_id" => "Employee",
- "underground" => "Underground"
+ 'employee_salary' => 'Employee salary',
+ 'employee_id' => 'Employee',
+ 'underground' => 'Underground',
+ '_id' => 'Id',
+ '_external_id' => 'External'
}
UnderscoreToHumanWithoutCapitalize = {
diff --git a/guides/rails_guides.rb b/guides/rails_guides.rb
index 9d488a8a15..1bdeef2947 100644
--- a/guides/rails_guides.rb
+++ b/guides/rails_guides.rb
@@ -24,11 +24,11 @@ begin
require 'redcarpet'
rescue LoadError
# This can happen if doc:guides is executed in an application.
- $stderr.puts('Generating guides requires Redcarpet 2.1.1+.')
+ $stderr.puts('Generating guides requires Redcarpet 3.1.0+.')
$stderr.puts(<<ERROR) if bundler?
Please add
- gem 'redcarpet', '~> 2.1.1'
+ gem 'redcarpet', '~> 3.1.0'
to the Gemfile, run
diff --git a/guides/rails_guides/helpers.rb b/guides/rails_guides/helpers.rb
index 169453400f..a78c2e9fca 100644
--- a/guides/rails_guides/helpers.rb
+++ b/guides/rails_guides/helpers.rb
@@ -39,7 +39,7 @@ module RailsGuides
def author(name, nick, image = 'credits_pic_blank.gif', &block)
image = "images/#{image}"
- result = content_tag(:img, nil, :src => image, :class => 'left pic', :alt => name, :width => 91, :height => 91)
+ result = tag(:img, :src => image, :class => 'left pic', :alt => name, :width => 91, :height => 91)
result << content_tag(:h3, name)
result << content_tag(:p, capture(&block))
content_tag(:div, result, :class => 'clearfix', :id => nick)
diff --git a/guides/rails_guides/markdown.rb b/guides/rails_guides/markdown.rb
index 547c6d2c15..dbf7ff311d 100644
--- a/guides/rails_guides/markdown.rb
+++ b/guides/rails_guides/markdown.rb
@@ -79,10 +79,10 @@ module RailsGuides
def generate_structure
@headings_for_index = []
if @body.present?
- @body = Nokogiri::HTML(@body).tap do |doc|
+ @body = Nokogiri::HTML.fragment(@body).tap do |doc|
hierarchy = []
- doc.at('body').children.each do |node|
+ doc.children.each do |node|
if node.name =~ /^h[3-6]$/
case node.name
when 'h3'
@@ -116,7 +116,7 @@ module RailsGuides
end
end
- @index = Nokogiri::HTML(engine.render(raw_index)).tap do |doc|
+ @index = Nokogiri::HTML.fragment(engine.render(raw_index)).tap do |doc|
doc.at('ol')[:class] = 'chapters'
end.to_html
@@ -130,8 +130,8 @@ module RailsGuides
end
def generate_title
- if heading = Nokogiri::HTML(@header).at(:h2)
- @title = "#{heading.text} — Ruby on Rails Guides".html_safe
+ if heading = Nokogiri::HTML.fragment(@header).at(:h2)
+ @title = "#{heading.text} — Ruby on Rails Guides"
else
@title = "Ruby on Rails Guides"
end
diff --git a/guides/rails_guides/markdown/renderer.rb b/guides/rails_guides/markdown/renderer.rb
index 2eb7ca17a3..3791ed6fd5 100644
--- a/guides/rails_guides/markdown/renderer.rb
+++ b/guides/rails_guides/markdown/renderer.rb
@@ -15,7 +15,7 @@ module RailsGuides
HTML
end
- def header(text, header_level)
+ def header(text, header_level, anchor)
# Always increase the heading level by, so we can use h1, h2 heading in the document
header_level += 1
diff --git a/guides/source/2_3_release_notes.md b/guides/source/2_3_release_notes.md
index 8c633fa169..2302a618b6 100644
--- a/guides/source/2_3_release_notes.md
+++ b/guides/source/2_3_release_notes.md
@@ -594,7 +594,7 @@ The internals of the various <code>rake gem</code> tasks have been substantially
* Various files in /public that deal with CGI and FCGI dispatching are no longer generated in every Rails application by default (you can still get them if you need them by adding `--with-dispatchers` when you run the `rails` command, or add them later with `rake rails:update:generate_dispatchers`).
* 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.
+* `script/server` now accepts a `--path` 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.
@@ -618,4 +618,4 @@ A few pieces of older code are deprecated in this release:
Credits
-------
-Release notes compiled by [Mike Gunderloy](http://afreshcup.com.) This version of the Rails 2.3 release notes was compiled based on RC2 of Rails 2.3.
+Release notes compiled by [Mike Gunderloy](http://afreshcup.com). This version of the Rails 2.3 release notes was compiled based on RC2 of Rails 2.3.
diff --git a/guides/source/3_0_release_notes.md b/guides/source/3_0_release_notes.md
index 2d4be0cda7..db34fa401f 100644
--- a/guides/source/3_0_release_notes.md
+++ b/guides/source/3_0_release_notes.md
@@ -608,4 +608,4 @@ Credits
See the [full list of contributors to Rails](http://contributors.rubyonrails.org/) for the many people who spent many hours making Rails 3. Kudos to all of them.
-Rails 3.0 Release Notes were compiled by [Mikel Lindsaar](http://lindsaar.net.)
+Rails 3.0 Release Notes were compiled by [Mikel Lindsaar](http://lindsaar.net).
diff --git a/guides/source/active_record_postgresql.md b/guides/source/active_record_postgresql.md
new file mode 100644
index 0000000000..c0cc3bc69d
--- /dev/null
+++ b/guides/source/active_record_postgresql.md
@@ -0,0 +1,338 @@
+Active Record and PostgreSQL
+============================
+
+This guide covers PostgreSQL specific usage of Active Record.
+
+In order to use the PostgreSQL adapter you need to have at least version 8.2
+installed. Older versions are not supported.
+
+To get started with PostgreSQL have a look at the
+[configuring Rails guide](configuring.html#configuring-a-postgresql-database).
+It describes how to properly setup Active Record for PostgreSQL.
+
+Datatypes
+---------
+
+PostgreSQL offers a number of specific datatypes. Following is a list of types,
+that are supported by the PostgreSQL adapter.
+
+### Bytea
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/datatype-binary.html)
+* [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-binarystring.html)
+
+```ruby
+# db/migrate/20140207133952_create_documents.rb
+create_table :documents do |t|
+ t.binary 'payload'
+end
+
+# app/models/document.rb
+class Document < ActiveRecord::Base
+end
+
+# Usage
+data = File.read(Rails.root + "tmp/output.pdf")
+Document.create payload: data
+```
+
+### Array
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/arrays.html)
+* [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-array.html)
+
+```ruby
+# db/migrate/20140207133952_create_books.rb
+create_table :book do |t|
+ t.string 'title'
+ t.string 'tags', array: true
+ t.integer 'ratings', array: true
+end
+
+# app/models/book.rb
+class Book < ActiveRecord::Base
+end
+
+# Usage
+Book.create title: "Brave New World",
+ tags: ["fantasy", "fiction"],
+ ratings: [4, 5]
+
+## Books for a single tag
+Book.where("'fantasy' = ANY (tags)")
+
+## Books for multiple tags
+Book.where("tags @> ARRAY[?]::varchar[]", ["fantasy", "fiction"])
+
+## Books with 3 or more ratings
+Book.where("array_length(ratings, 1) >= 3")
+```
+
+### Hstore
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/hstore.html)
+
+```ruby
+# db/migrate/20131009135255_create_profiles.rb
+ActiveRecord::Schema.define do
+ create_table :profiles do |t|
+ t.hstore 'settings'
+ end
+end
+
+# app/models/profile.rb
+class Profile < ActiveRecord::Base
+end
+
+# Usage
+Profile.create(settings: { "color" => "blue", "resolution" => "800x600" })
+
+profile = Profile.first
+profile.settings # => {"color"=>"blue", "resolution"=>"800x600"}
+
+profile.settings = {"color" => "yellow", "resulution" => "1280x1024"}
+profile.save!
+
+## you need to call _will_change! if you are editing the store in place
+profile.settings["color"] = "green"
+profile.settings_will_change!
+profile.save!
+```
+
+### Json
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/datatype-json.html)
+* [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-json.html)
+
+```ruby
+# db/migrate/20131220144913_create_events.rb
+create_table :events do |t|
+ t.json 'payload'
+end
+
+# app/models/event.rb
+class Event < ActiveRecord::Base
+end
+
+# Usage
+Event.create(payload: { kind: "user_renamed", change: ["jack", "john"]})
+
+event = Event.first
+event.payload # => {"kind"=>"user_renamed", "change"=>["jack", "john"]}
+
+## Query based on JSON document
+Event.where("payload->'kind' = ?", "user_renamed")
+```
+
+### Range Types
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/rangetypes.html)
+* [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-range.html)
+
+This type is mapped to Ruby [`Range`]() objects.
+
+```ruby
+# db/migrate/20130923065404_create_events.rb
+create_table :events do |t|
+ t.daterange 'duration'
+end
+
+# app/models/event.rb
+class Event < ActiveRecord::Base
+end
+
+# Usage
+Event.create(duration: Date.new(2014, 2, 11)..Date.new(2014, 2, 12))
+
+event = Event.first
+event.duration # => Tue, 11 Feb 2014...Thu, 13 Feb 2014
+
+## All Events on a given date
+Event.where("duration @> ?::date", Date.new(2014, 2, 12))
+
+## Working with range bounds
+event = Event.
+ select("lower(duration) AS starts_at").
+ select("upper(duration) AS ends_at").first
+
+event.starts_at # => Tue, 11 Feb 2014
+event.ends_at # => Thu, 13 Feb 2014
+```
+
+### Composite Types
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/rowtypes.html)
+
+Currently there is no special support for composite types. They are mapped to as
+normal text columns:
+
+```sql
+CREATE TYPE full_address AS
+(
+ city VARCHAR(90),
+ street VARCHAR(90)
+);
+```
+
+```ruby
+# db/migrate/20140207133952_create_contacts.rb
+execute <<-SQL
+ CREATE TYPE full_address AS
+ (
+ city VARCHAR(90),
+ street VARCHAR(90)
+ );
+SQL
+create_table :contacts do |t|
+ t.column :address, :full_address
+end
+
+# app/models/contact.rb
+class Contact < ActiveRecord::Base
+end
+
+# Usage
+Contact.create address: "(Paris,Champs-Élysées)"
+contact = Contact.first
+contact.address # => "(Paris,Champs-Élysées)"
+contact.address = "(Paris,Rue Basse)"
+contact.save!
+```
+
+### Enumerated Types
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/datatype-enum.html)
+
+Currently there is no special support for enumerated types. They are mapped as
+normal text columns:
+
+```ruby
+# db/migrate/20131220144913_create_events.rb
+execute <<-SQL
+ CREATE TYPE article_status AS ENUM ('draft', 'published');
+SQL
+create_table :articles do |t|
+ t.column :status, :article_status
+end
+
+# app/models/article.rb
+class Article < ActiveRecord::Base
+end
+
+# Usage
+Article.create status: "draft"
+article = Article.first
+article.status # => "draft"
+
+article.status = "published"
+article.save!
+```
+
+### UUID
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/datatype-uuid.html)
+* [generator functions](http://www.postgresql.org/docs/9.3/static/uuid-ossp.html)
+
+
+```ruby
+# db/migrate/20131220144913_create_revisions.rb
+create_table :revisions do |t|
+ t.column :identifier, :uuid
+end
+
+# app/models/revision.rb
+class Revision < ActiveRecord::Base
+end
+
+# Usage
+Revision.create identifier: "A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11"
+
+revision = Revision.first
+revision.identifier # => "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11"
+```
+
+### Bit String Types
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/datatype-bit.html)
+* [functions and operators](http://www.postgresql.org/docs/9.3/static/functions-bitstring.html)
+
+```ruby
+# db/migrate/20131220144913_create_users.rb
+create_table :users, force: true do |t|
+ t.column :settings, "bit(8)"
+end
+
+# app/models/device.rb
+class User < ActiveRecord::Base
+end
+
+# Usage
+User.create settings: "01010011"
+user = User.first
+user.settings # => "(Paris,Champs-Élysées)"
+user.settings = "0xAF"
+user.settings # => 10101111
+user.save!
+```
+
+### Network Address Types
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/datatype-net-types.html)
+
+The types `inet` and `cidr` are mapped to Ruby [`IPAddr`]() objects. The
+`macaddr` type is mapped to normal text.
+
+### Geometric Types
+
+* [type definition](http://www.postgresql.org/docs/9.3/static/datatype-geometric.html)
+
+All geometric types are mapped to normal text.
+
+
+UUID Primary Keys
+-----------------
+
+NOTE: you need to enable the `uuid-ossp` extension to generate UUIDs.
+
+```ruby
+# db/migrate/20131220144913_create_devices.rb
+enable_extension 'uuid-ossp' unless extension_enabled?('uuid-ossp')
+create_table :devices, id: :uuid, default: 'uuid_generate_v4()' do |t|
+ t.string :kind
+end
+
+# app/models/device.rb
+class Device < ActiveRecord::Base
+end
+
+# Usage
+device = Device.create
+device.id # => "814865cd-5a1d-4771-9306-4268f188fe9e"
+```
+
+Full Text Search
+----------------
+
+```ruby
+# db/migrate/20131220144913_create_documents.rb
+create_table :documents do |t|
+ t.string 'title'
+ t.string 'body'
+end
+
+execute "CREATE INDEX documents_idx ON documents USING gin(to_tsvector('english', title || ' ' || body));"
+
+# app/models/document.rb
+class Document < ActiveRecord::Base
+end
+
+# Usage
+Document.create(title: "Cats and Dogs", body: "are nice!")
+
+## all documents matching 'cat & dog'
+Document.where("to_tsvector('english', title || ' ' || body) @@ to_tsquery(?)",
+ "cat & dog")
+```
+
+Views
+-----
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 5a4e15cfa9..1ac7ecc78f 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -1768,21 +1768,36 @@ NOTE: Defined in `active_support/core_ext/string/inflections.rb`.
#### `humanize`
-The method `humanize` gives you a sensible name for display out of an attribute name. To do so it replaces underscores with spaces, removes any "_id" suffix, and capitalizes the first word:
+The method `humanize` tqweaks an attribute name for display to end users.
+
+Specifically performs these transformations:
+
+ * Applies human inflection rules to the argument.
+ * Deletes leading underscores, if any.
+ * Removes a "_id" suffix if present.
+ * Replaces underscores with spaces, if any.
+ * Downcases all words except acronyms.
+ * Capitalizes the first word.
+
+The capitalization of the first word can be turned off by setting the
++:capitalize+ option to false (default is true).
```ruby
-"name".humanize # => "Name"
-"author_id".humanize # => "Author"
-"comments_count".humanize # => "Comments count"
+"name".humanize # => "Name"
+"author_id".humanize # => "Author"
+"author_id".humanize(capitalize: false) # => "author"
+"comments_count".humanize # => "Comments count"
+"_id".humanize # => "Id"
```
-The capitalization of the first word can be turned off by setting the optional parameter `capitalize` to false:
+If "SSL" was defined to be an acronym:
```ruby
-"author_id".humanize(capitalize: false) # => "author"
+'ssl_error'.humanize # => "SSL error"
```
-The helper method `full_messages` uses `humanize` as a fallback to include attribute names:
+The helper method `full_messages` uses `humanize` as a fallback to include
+attribute names:
```ruby
def full_messages
diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md
index 121cdc0199..d947c5d9d5 100644
--- a/guides/source/active_support_instrumentation.md
+++ b/guides/source/active_support_instrumentation.md
@@ -17,7 +17,7 @@ After reading this guide, you will know:
Introduction to instrumentation
-------------------------------
-The instrumentation API provided by Active Support allows developers to provide hooks which other developers may hook into. There are several of these within the Rails framework, as described below in <TODO: link to section detailing each hook point>. With this API, developers can choose to be notified when certain events occur inside their application or another piece of Ruby code.
+The instrumentation API provided by Active Support allows developers to provide hooks which other developers may hook into. There are several of these within the Rails framework, as described below in (TODO: link to section detailing each hook point). With this API, developers can choose to be notified when certain events occur inside their application or another piece of Ruby code.
For example, there is a hook provided within Active Record that is called every time Active Record uses an SQL query on a database. This hook could be **subscribed** to, and used to track the number of queries during a certain action. There's another hook around the processing of an action of a controller. This could be used, for instance, to track how long a specific action has taken.
diff --git a/guides/source/index.html.erb b/guides/source/index.html.erb
index 57c224c165..2fdf18a2e9 100644
--- a/guides/source/index.html.erb
+++ b/guides/source/index.html.erb
@@ -9,6 +9,7 @@ Ruby on Rails Guides
<% content_for :index_section do %>
<div id="subCol">
<dl>
+ <dt></dt>
<dd class="kindle">Rails Guides are also available for <%= link_to 'Kindle', @mobi %>.</dd>
<dd class="work-in-progress">Guides marked with this icon are currently being worked on and will not be available in the Guides Index menu. While still useful, they may contain incomplete information and even errors. You can help by reviewing them and posting your comments and corrections.</dd>
</dl>
diff --git a/guides/source/layout.html.erb b/guides/source/layout.html.erb
index 1ac4e7f40c..1d375f806c 100644
--- a/guides/source/layout.html.erb
+++ b/guides/source/layout.html.erb
@@ -1,5 +1,4 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
@@ -78,7 +77,6 @@
</select>
</li>
</ul>
- </div>
</div>
</div>
<hr class="hide" />
diff --git a/guides/w3c_validator.rb b/guides/w3c_validator.rb
index 6ef3df45a9..71f044b9c4 100644
--- a/guides/w3c_validator.rb
+++ b/guides/w3c_validator.rb
@@ -60,6 +60,8 @@ module RailsGuides
def guides_to_validate
guides = Dir["./output/*.html"]
guides.delete("./output/layout.html")
+ guides.delete("./output/_license.html")
+ guides.delete("./output/_welcome.html")
ENV.key?('ONLY') ? select_only(guides) : guides
end
diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb
index f6d8aec30d..1a2613a8d0 100644
--- a/railties/lib/rails/commands/dbconsole.rb
+++ b/railties/lib/rails/commands/dbconsole.rb
@@ -20,7 +20,7 @@ module Rails
ENV['RAILS_ENV'] = options[:environment] || environment
case config["adapter"]
- when /^mysql/
+ when /^(jdbc)?mysql/
args = {
'host' => '--host',
'port' => '--port',