aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Gemfile1
-rw-r--r--Rakefile91
-rw-r--r--actionmailer/README.rdoc4
-rw-r--r--actionmailer/test/asset_host_test.rb1
-rw-r--r--actionmailer/test/url_test.rb9
-rw-r--r--actionpack/CHANGELOG.md10
-rw-r--r--actionpack/lib/abstract_controller/base.rb2
-rw-r--r--actionpack/lib/abstract_controller/helpers.rb2
-rw-r--r--actionpack/lib/abstract_controller/rendering.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/upload.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing.rb92
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb2
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb16
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb2
-rw-r--r--actionpack/lib/action_view/template/resolver.rb2
-rw-r--r--actionpack/lib/action_view/vendor/html-scanner/html/selector.rb16
-rw-r--r--actionpack/test/abstract/layouts_test.rb4
-rw-r--r--actionpack/test/abstract_unit.rb2
-rw-r--r--actionpack/test/controller/layout_test.rb2
-rw-r--r--actionpack/test/controller/new_base/render_partial_test.rb22
-rw-r--r--actionpack/test/controller/new_base/render_test.rb24
-rw-r--r--actionpack/test/controller/routing_test.rb8
-rw-r--r--actionpack/test/controller/show_exceptions_test.rb16
-rw-r--r--actionpack/test/template/url_helper_test.rb8
-rw-r--r--activemodel/CHANGELOG.md15
-rw-r--r--activemodel/README.rdoc2
-rw-r--r--activemodel/lib/active_model/errors.rb2
-rw-r--r--activemodel/test/cases/errors_test.rb90
-rw-r--r--activerecord/CHANGELOG.md26
-rw-r--r--activerecord/README.rdoc4
-rw-r--r--activerecord/examples/associations.pngbin40623 -> 0 bytes
-rw-r--r--activerecord/lib/active_record/associations.rb8
-rw-r--r--activerecord/lib/active_record/associations/association.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb45
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb9
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb10
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb16
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb8
-rw-r--r--activerecord/lib/active_record/connection_handling.rb10
-rw-r--r--activerecord/lib/active_record/core.rb4
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb58
-rw-r--r--activerecord/lib/active_record/persistence.rb2
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb2
-rw-r--r--activerecord/lib/active_record/schema_dumper.rb4
-rw-r--r--activerecord/test/cases/adapter_test.rb4
-rw-r--r--activerecord/test/cases/adapters/mysql/active_schema_test.rb11
-rw-r--r--activerecord/test/cases/adapters/mysql/schema_test.rb29
-rw-r--r--activerecord/test/cases/adapters/mysql2/active_schema_test.rb11
-rw-r--r--activerecord/test/cases/adapters/mysql2/schema_test.rb25
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb4
-rw-r--r--activerecord/test/cases/autosave_association_test.rb4
-rw-r--r--activerecord/test/cases/base_test.rb2
-rw-r--r--activerecord/test/cases/batches_test.rb4
-rw-r--r--activerecord/test/cases/dup_test.rb2
-rw-r--r--activerecord/test/cases/migration/columns_test.rb6
-rw-r--r--activerecord/test/cases/persistence_test.rb36
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb16
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb (renamed from activerecord/test/cases/relation_scoping_test.rb)330
-rw-r--r--activerecord/test/cases/scoping/named_scoping_test.rb (renamed from activerecord/test/cases/named_scope_test.rb)2
-rw-r--r--activerecord/test/cases/scoping/relation_scoping_test.rb331
-rw-r--r--activerecord/test/schema/mysql2_specific_schema.rb10
-rw-r--r--activerecord/test/schema/mysql_specific_schema.rb10
-rw-r--r--activerecord/test/schema/schema.rb1
-rw-r--r--activesupport/CHANGELOG.md6
-rw-r--r--activesupport/lib/active_support/callbacks.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/indent.rb2
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb2
-rw-r--r--activesupport/lib/active_support/notifications/instrumenter.rb2
-rw-r--r--activesupport/lib/active_support/testing/constant_lookup.rb2
-rw-r--r--activesupport/test/descendants_tracker_with_autoloading_test.rb6
-rw-r--r--activesupport/test/ordered_options_test.rb20
-rw-r--r--activesupport/test/testing/constant_lookup_test.rb10
-rw-r--r--guides/code/getting_started/Gemfile24
-rw-r--r--guides/code/getting_started/config/application.rb5
-rw-r--r--guides/source/action_controller_overview.md34
-rw-r--r--guides/source/action_view_overview.md2
-rw-r--r--guides/source/active_record_querying.md14
-rw-r--r--guides/source/active_record_validations.md41
-rw-r--r--guides/source/active_support_core_extensions.md4
-rw-r--r--guides/source/active_support_instrumentation.md10
-rw-r--r--guides/source/asset_pipeline.md32
-rw-r--r--guides/source/association_basics.md2
-rw-r--r--guides/source/command_line.md10
-rw-r--r--guides/source/configuring.md4
-rw-r--r--guides/source/contributing_to_ruby_on_rails.md31
-rw-r--r--guides/source/debugging_rails_applications.md28
-rw-r--r--guides/source/form_helpers.md2
-rw-r--r--guides/source/generators.md4
-rw-r--r--guides/source/getting_started.md2
-rw-r--r--guides/source/layouts_and_rendering.md2
-rw-r--r--guides/source/migrations.md4
-rw-r--r--guides/source/routing.md4
-rw-r--r--guides/source/ruby_on_rails_guides_guidelines.md2
-rw-r--r--guides/source/security.md2
-rw-r--r--guides/source/testing.md13
-rw-r--r--guides/source/upgrading_ruby_on_rails.md8
-rw-r--r--guides/source/working_with_javascript_in_rails.md1
-rw-r--r--rails.gemspec4
-rw-r--r--railties/CHANGELOG.md73
-rw-r--r--railties/RDOC_MAIN.rdoc73
-rw-r--r--railties/lib/rails/api/task.rb157
-rw-r--r--railties/lib/rails/engine.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb42
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/application.rb5
-rw-r--r--railties/lib/rails/tasks/documentation.rake48
-rw-r--r--railties/railties.gemspec5
-rw-r--r--railties/test/application/console_test.rb7
-rw-r--r--railties/test/generators/app_generator_test.rb5
-rw-r--r--railties/test/generators_test.rb2
-rw-r--r--railties/test/railties/engine_test.rb2
-rw-r--r--railties/test/railties/railtie_test.rb2
117 files changed, 1306 insertions, 978 deletions
diff --git a/.gitignore b/.gitignore
index 4c2c8de10c..7236e395a2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,4 +20,3 @@ pkg
/railties/doc
/railties/tmp
/guides/output
-/RDOC_MAIN.rdoc
diff --git a/Gemfile b/Gemfile
index 9abc8a5d66..45deca8315 100644
--- a/Gemfile
+++ b/Gemfile
@@ -8,7 +8,6 @@ gem 'bcrypt-ruby', '~> 3.0.0'
gem 'jquery-rails', github: 'rails/jquery-rails'
gem 'turbolinks'
gem 'coffee-rails', '~> 4.0.0.beta1'
-gem 'thor', github: 'wycats/thor'
# This needs to be with require false to avoid
# it being automatically loaded by sprockets
diff --git a/Rakefile b/Rakefile
index e577c079df..177765f348 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,9 +1,9 @@
-require 'rdoc/task'
require 'sdoc'
require 'net/http'
$:.unshift File.expand_path('..', __FILE__)
require "tasks/release"
+require 'railties/lib/rails/api/task'
desc "Build gem files for all projects"
task :build => "all:build"
@@ -47,94 +47,7 @@ task :install => :gem do
end
desc "Generate documentation for the Rails framework"
-RDoc::Task.new do |rdoc|
- RDOC_MAIN = 'RDOC_MAIN.rdoc'
-
- # This is a hack.
- #
- # Backslashes are needed to prevent RDoc from autolinking "Rails" to the
- # documentation of the Rails module. On the other hand, as of this
- # writing README.rdoc is displayed in the front page of the project in
- # GitHub, where backslashes are shown and look weird.
- #
- # The temporary solution is to have a README.rdoc without backslashes for
- # GitHub, and gsub it to generate the main page of the API.
- #
- # Also, relative links in GitHub have to point to blobs, whereas in the API
- # they need to point to files.
- #
- # The idea for the future is to have totally different files, since the
- # API is no longer a generic entry point to Rails and deserves a
- # dedicated main page specifically thought as an API entry point.
- rdoc.before_running_rdoc do
- rdoc_main = File.read('README.rdoc')
-
- # The ^(?=\S) assertion prevents code blocks from being processed,
- # since no autolinking happens there and RDoc displays the backslash
- # otherwise.
- rdoc_main.gsub!(/^(?=\S).*?\b(?=Rails)\b/) { "#$&\\" }
- rdoc_main.gsub!(%r{link:/rails/rails/blob/master/(\w+)/README\.rdoc}, "link:files/\\1/README_rdoc.html")
-
- # Remove Travis and Gemnasium status images from API pages. Only the GitHub
- # README page gets these images. Travis's HTTPS build image is used to
- # avoid GitHub caching: http://about.travis-ci.org/docs/user/status-images
- rdoc_main.gsub!(/^== Code Status(\n(?!==).*)*/, '')
-
- File.open(RDOC_MAIN, 'w') do |f|
- f.write(rdoc_main)
- end
-
- rdoc.rdoc_files.include(RDOC_MAIN)
- end
-
- rdoc.rdoc_dir = 'doc/rdoc'
- rdoc.title = "Ruby on Rails Documentation"
-
- rdoc.options << '-f' << 'sdoc'
- rdoc.options << '-T' << 'rails'
- rdoc.options << '-e' << 'UTF-8'
- rdoc.options << '-g' # SDoc flag, link methods to GitHub
- rdoc.options << '-m' << RDOC_MAIN
-
- rdoc.rdoc_files.include('railties/CHANGELOG.md')
- rdoc.rdoc_files.include('railties/MIT-LICENSE')
- rdoc.rdoc_files.include('railties/README.rdoc')
- rdoc.rdoc_files.include('railties/lib/**/*.rb')
- rdoc.rdoc_files.exclude('railties/lib/rails/generators/**/templates/**/*.rb')
-
- rdoc.rdoc_files.include('activerecord/README.rdoc')
- rdoc.rdoc_files.include('activerecord/CHANGELOG.md')
- rdoc.rdoc_files.include('activerecord/lib/active_record/**/*.rb')
- rdoc.rdoc_files.exclude('activerecord/lib/active_record/vendor/*')
-
- rdoc.rdoc_files.include('actionpack/README.rdoc')
- rdoc.rdoc_files.include('actionpack/CHANGELOG.md')
- rdoc.rdoc_files.include('actionpack/lib/abstract_controller/**/*.rb')
- rdoc.rdoc_files.include('actionpack/lib/action_controller/**/*.rb')
- rdoc.rdoc_files.include('actionpack/lib/action_dispatch/**/*.rb')
- rdoc.rdoc_files.include('actionpack/lib/action_view/**/*.rb')
- rdoc.rdoc_files.exclude('actionpack/lib/action_controller/vendor/*')
-
- rdoc.rdoc_files.include('actionmailer/README.rdoc')
- rdoc.rdoc_files.include('actionmailer/CHANGELOG.md')
- rdoc.rdoc_files.include('actionmailer/lib/action_mailer/**/*.rb')
- rdoc.rdoc_files.exclude('actionmailer/lib/action_mailer/vendor/*')
-
- rdoc.rdoc_files.include('activesupport/README.rdoc')
- rdoc.rdoc_files.include('activesupport/CHANGELOG.md')
- rdoc.rdoc_files.include('activesupport/lib/active_support/**/*.rb')
- rdoc.rdoc_files.exclude('activesupport/lib/active_support/vendor/*')
-
- rdoc.rdoc_files.include('activemodel/README.rdoc')
- rdoc.rdoc_files.include('activemodel/CHANGELOG.md')
- rdoc.rdoc_files.include('activemodel/lib/active_model/**/*.rb')
-end
-
-# Enhance rdoc task to copy referenced images also
-task :rdoc do
- FileUtils.mkdir_p "doc/rdoc/files/examples/"
- FileUtils.copy "activerecord/examples/associations.png", "doc/rdoc/files/examples/associations.png"
-end
+Rails::API::RepoTask.new('rdoc')
desc 'Bump all versions to match version.rb'
task :update_versions do
diff --git a/actionmailer/README.rdoc b/actionmailer/README.rdoc
index 9feb2add5b..4d78d6142a 100644
--- a/actionmailer/README.rdoc
+++ b/actionmailer/README.rdoc
@@ -1,6 +1,6 @@
= Action Mailer -- Easy email delivery and testing
-Action Mailer is a framework for designing email-service layers. These layers
+Action Mailer is a framework for designing email service layers. These layers
are used to consolidate code for sending out forgotten passwords, welcome
wishes on signup, invoices for billing, and any other use case that requires
a written notification to either a person or another system.
@@ -78,7 +78,7 @@ Or you can just chain the methods together like:
It is possible to set default values that will be used in every method in your Action Mailer class. To implement this functionality, you just call the public class method <tt>default</tt> which you get for free from ActionMailer::Base. This method accepts a Hash as the parameter. You can use any of the headers e-mail messages has, like <tt>:from</tt> as the key. You can also pass in a string as the key, like "Content-Type", but Action Mailer does this out of the box for you, so you won't need to worry about that. Finally, it is also possible to pass in a Proc that will get evaluated when it is needed.
-Note that every value you set with this method will get over written if you use the same key in your mailer method.
+Note that every value you set with this method will get overwritten if you use the same key in your mailer method.
Example:
diff --git a/actionmailer/test/asset_host_test.rb b/actionmailer/test/asset_host_test.rb
index 32ae76a7c5..00f1348a53 100644
--- a/actionmailer/test/asset_host_test.rb
+++ b/actionmailer/test/asset_host_test.rb
@@ -16,7 +16,6 @@ class AssetHostTest < ActiveSupport::TestCase
ActionMailer::Base.deliveries.clear
AssetHostMailer.configure do |c|
c.asset_host = "http://www.example.com"
- c.assets_dir = ''
end
end
diff --git a/actionmailer/test/url_test.rb b/actionmailer/test/url_test.rb
index dcd80f46b5..589944fa69 100644
--- a/actionmailer/test/url_test.rb
+++ b/actionmailer/test/url_test.rb
@@ -41,18 +41,9 @@ class ActionMailerUrlTest < ActionMailer::TestCase
end
def setup
- set_delivery_method :test
- ActionMailer::Base.perform_deliveries = true
- ActionMailer::Base.deliveries.clear
- ActiveSupport::Deprecation.silenced = false
-
@recipient = 'test@localhost'
end
- def teardown
- restore_delivery_method
- end
-
def test_signed_up_with_url
UrlTestMailer.delivery_method = :test
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 058a69dcb6..85f943814e 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,22 +1,22 @@
## Rails 4.0.0 (unreleased) ##
* Ensure consistent fallback to the default layout lookup for layouts set
- using symbols or procs that return nil.
+ using symbols or procs that return `nil`.
All of the following layouts will result in the default layout lookup:
layout nil
- layout proc { |c| nil }
+ layout proc { nil }
layout :returns_nil
-
def returns_nil
nil
end
- Previously symbols and procs which returned nil resulted in no layout which
- differed from the `layout nil` behavior.
+ Previously symbols and procs which returned `nil` resulted in no layout which
+ differed from the `layout nil` behavior. To get the "no layout" behavior just
+ return `false` instead of `nil` for `layout`.
*Chris Nicola*
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index 56dc9ab7a1..af5de815bb 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -35,7 +35,7 @@ module AbstractController
end
def inherited(klass) # :nodoc:
- # define the abstract ivar on subclasses so that we don't get
+ # Define the abstract ivar on subclasses so that we don't get
# uninitialized ivar warnings
unless klass.instance_variable_defined?(:@abstract)
klass.instance_variable_set(:@abstract, false)
diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb
index 812a35735f..bb701184e8 100644
--- a/actionpack/lib/abstract_controller/helpers.rb
+++ b/actionpack/lib/abstract_controller/helpers.rb
@@ -59,7 +59,7 @@ module AbstractController
# The +helper+ class method can take a series of helper module names, a block, or both.
#
# ==== Options
- # * <tt>*args</tt> - Module, Symbol, String, :all
+ # * <tt>*args</tt> - Module, Symbol, String
# * <tt>block</tt> - A block defining helper methods
#
# When the argument is a module it will be included directly in the template class.
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
index f8e4cb4384..3f34add790 100644
--- a/actionpack/lib/abstract_controller/rendering.rb
+++ b/actionpack/lib/abstract_controller/rendering.rb
@@ -105,8 +105,8 @@ module AbstractController
#
# If a component extends the semantics of response_body
# (as Action Controller extends it to be anything that
- # responds to the method each), this method needs to
- # overriden in order to still return a string.
+ # responds to the method each), this method needs to be
+ # overridden in order to still return a string.
# :api: plugin
def render_to_string(*args, &block)
options = _normalize_render(*args, &block)
diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb
index 319d0197d1..b57c84dec8 100644
--- a/actionpack/lib/action_dispatch/http/upload.rb
+++ b/actionpack/lib/action_dispatch/http/upload.rb
@@ -6,7 +6,7 @@ module ActionDispatch
# of its interface is available directly for convenience.
#
# Uploaded files are temporary files whose lifespan is one request. When
- # the object is finalized Ruby unlinks the file, so there is not need to
+ # the object is finalized Ruby unlinks the file, so there is no need to
# clean them with a separate maintenance task.
class UploadedFile
# The basename of the file in the client.
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index d55eb8109a..550c7d0e7b 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -69,6 +69,22 @@ module ActionDispatch
# <tt>Routing::Mapper::Scoping#namespace</tt>, and
# <tt>Routing::Mapper::Scoping#scope</tt>.
#
+ # == Non-resourceful routes
+ #
+ # For routes that don't fit the <tt>resources</tt> mold, you can use the HTTP helper
+ # methods <tt>get</tt>, <tt>post</tt>, <tt>patch</tt>, <tt>put</tt> and <tt>delete</tt>.
+ #
+ # get 'post/:id' => 'posts#show'
+ # post 'post/:id' => 'posts#create_comment'
+ #
+ # If your route needs to respond to more than one HTTP method (or all methods) then using the
+ # <tt>:via</tt> option on <tt>match</tt> is preferable.
+ #
+ # match 'post/:id' => 'posts#show', via: [:get, :post]
+ #
+ # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
+ # URL will route to the <tt>show</tt> action.
+ #
# == Named routes
#
# Routes can be named by passing an <tt>:as</tt> option,
@@ -78,7 +94,7 @@ module ActionDispatch
# Example:
#
# # In routes.rb
- # match '/login' => 'accounts#login', as: 'login'
+ # get '/login' => 'accounts#login', as: 'login'
#
# # With render, redirect_to, tests, etc.
# redirect_to login_url
@@ -104,9 +120,9 @@ module ActionDispatch
#
# # In routes.rb
# controller :blog do
- # match 'blog/show' => :list
- # match 'blog/delete' => :delete
- # match 'blog/edit/:id' => :edit
+ # get 'blog/show' => :list
+ # get 'blog/delete' => :delete
+ # get 'blog/edit/:id' => :edit
# end
#
# # provides named routes for show, delete, and edit
@@ -116,7 +132,7 @@ module ActionDispatch
#
# Routes can generate pretty URLs. For example:
#
- # match '/articles/:year/:month/:day' => 'articles#find_by_id', constraints: {
+ # get '/articles/:year/:month/:day' => 'articles#find_by_id', constraints: {
# year: /\d{4}/,
# month: /\d{1,2}/,
# day: /\d{1,2}/
@@ -131,7 +147,7 @@ module ActionDispatch
# You can specify a regular expression to define a format for a parameter.
#
# controller 'geocode' do
- # match 'geocode/:postalcode' => :show, constraints: {
+ # get 'geocode/:postalcode' => :show, constraints: {
# postalcode: /\d{5}(-\d{4})?/
# }
#
@@ -139,13 +155,13 @@ module ActionDispatch
# expression modifiers:
#
# controller 'geocode' do
- # match 'geocode/:postalcode' => :show, constraints: {
+ # get 'geocode/:postalcode' => :show, constraints: {
# postalcode: /hx\d\d\s\d[a-z]{2}/i
# }
# end
#
# controller 'geocode' do
- # match 'geocode/:postalcode' => :show, constraints: {
+ # get 'geocode/:postalcode' => :show, constraints: {
# postalcode: /# Postcode format
# \d{5} #Prefix
# (-\d{4})? #Suffix
@@ -153,73 +169,21 @@ module ActionDispatch
# }
# end
#
- # Using the multiline match modifier will raise an +ArgumentError+.
+ # Using the multiline modifier will raise an +ArgumentError+.
# Encoding regular expression modifiers are silently ignored. The
# match will always use the default encoding or ASCII.
#
- # == Default route
- #
- # Consider the following route, which you will find commented out at the
- # bottom of your generated <tt>config/routes.rb</tt>:
- #
- # match ':controller(/:action(/:id))(.:format)'
- #
- # This route states that it expects requests to consist of a
- # <tt>:controller</tt> followed optionally by an <tt>:action</tt> that in
- # turn is followed optionally by an <tt>:id</tt>, which in turn is followed
- # optionally by a <tt>:format</tt>.
- #
- # Suppose you get an incoming request for <tt>/blog/edit/22</tt>, you'll end
- # up with:
- #
- # params = { controller: 'blog',
- # action: 'edit',
- # id: '22'
- # }
- #
- # By not relying on default routes, you improve the security of your
- # application since not all controller actions, which includes actions you
- # might add at a later time, are exposed by default.
- #
- # == HTTP Methods
- #
- # Using the <tt>:via</tt> option when specifying a route allows you to
- # restrict it to a specific HTTP method. Possible values are <tt>:post</tt>,
- # <tt>:get</tt>, <tt>:patch</tt>, <tt>:put</tt>, <tt>:delete</tt> and
- # <tt>:any</tt>. If your route needs to respond to more than one method you
- # can use an array, e.g. <tt>[ :get, :post ]</tt>. The default value is
- # <tt>:any</tt> which means that the route will respond to any of the HTTP
- # methods.
- #
- # match 'post/:id' => 'posts#show', via: :get
- # match 'post/:id' => 'posts#create_comment', via: :post
- #
- # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
- # URL will route to the <tt>show</tt> action.
- #
- # === HTTP helper methods
- #
- # An alternative method of specifying which HTTP method a route should respond to is to use the helper
- # methods <tt>get</tt>, <tt>post</tt>, <tt>patch</tt>, <tt>put</tt> and <tt>delete</tt>.
- #
- # get 'post/:id' => 'posts#show'
- # post 'post/:id' => 'posts#create_comment'
- #
- # This syntax is less verbose and the intention is more apparent to someone else reading your code,
- # however if your route needs to respond to more than one HTTP method (or all methods) then using the
- # <tt>:via</tt> option on <tt>match</tt> is preferable.
- #
# == External redirects
#
# You can redirect any path to another path using the redirect helper in your router:
#
- # match "/stories" => redirect("/posts")
+ # get "/stories" => redirect("/posts")
#
# == Unicode character routes
#
# You can specify unicode character routes in your router:
#
- # match "こんにちは" => "welcome#index"
+ # get "こんにちは" => "welcome#index"
#
# == Routing to Rack Applications
#
@@ -227,7 +191,7 @@ module ActionDispatch
# index action in the PostsController, you can specify any Rack application
# as the endpoint for a matcher:
#
- # match "/application.js" => Sprockets
+ # get "/application.js" => Sprockets
#
# == Reloading routes
#
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 7fb4719fa0..07203428d4 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -405,7 +405,7 @@ module ActionDispatch
if name && named_routes[name]
raise ArgumentError, "Invalid route name, already in use: '#{name}' \n" \
- "You may have defined two routes with the same name using the `:as` option, or "
+ "You may have defined two routes with the same name using the `:as` option, or " \
"you may be overriding a route already defined by a resource with the same naming. " \
"For the latter, you can restrict the routes created with `resources` as explained here: \n" \
"http://guides.rubyonrails.org/routing.html#restricting-the-routes-created"
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 6b6a7edc1d..36cfb7fca7 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -655,14 +655,6 @@ module ActionView
# ...
# <% end %>
#
- # When projects is already an association on Person you can use
- # +accepts_nested_attributes_for+ to define the writer method for you:
- #
- # class Person < ActiveRecord::Base
- # has_many :projects
- # accepts_nested_attributes_for :projects
- # end
- #
# If you want to destroy any of the associated models through the
# form, you have to enable it first using the <tt>:allow_destroy</tt>
# option for +accepts_nested_attributes_for+:
@@ -1425,14 +1417,6 @@ module ActionView
# ...
# <% end %>
#
- # When projects is already an association on Person you can use
- # +accepts_nested_attributes_for+ to define the writer method for you:
- #
- # class Person < ActiveRecord::Base
- # has_many :projects
- # accepts_nested_attributes_for :projects
- # end
- #
# If you want to destroy any of the associated models through the
# form, you have to enable it first using the <tt>:allow_destroy</tt>
# option for +accepts_nested_attributes_for+:
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index c7edf3dd7e..7e65ebb4e4 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -752,7 +752,7 @@ module ActionView
end
def prompt_text(prompt)
- prompt = prompt.kind_of?(String) ? prompt : I18n.translate('helpers.select.prompt', :default => 'Please select')
+ prompt.kind_of?(String) ? prompt : I18n.translate('helpers.select.prompt', :default => 'Please select')
end
end
diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb
index 47bd011d5e..6b9b0a826b 100644
--- a/actionpack/lib/action_view/template/resolver.rb
+++ b/actionpack/lib/action_view/template/resolver.rb
@@ -255,7 +255,7 @@ module ActionView
#
# FileSystemResolver.new("/path/to/views", ":prefix/:action{.:locale,}{.:formats,}{.:handlers,}")
#
- # This one allows you to keep files with different formats in seperated subdirectories,
+ # This one allows you to keep files with different formats in separate subdirectories,
# eg. `users/new.html` will be loaded from `users/html/new.erb` or `users/new.html.erb`,
# `users/new.js` from `users/js/new.erb` or `users/new.js.erb`, etc.
#
diff --git a/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb b/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb
index 60b6783b19..7f8609c408 100644
--- a/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb
+++ b/actionpack/lib/action_view/vendor/html-scanner/html/selector.rb
@@ -537,7 +537,7 @@ module HTML
# Get identifier, class, attribute name, pseudo or negation.
while true
# Element identifier.
- next if statement.sub!(/^#(\?|[\w\-]+)/) do |match|
+ next if statement.sub!(/^#(\?|[\w\-]+)/) do
id = $1
if id == "?"
id = values.shift
@@ -549,7 +549,7 @@ module HTML
end
# Class name.
- next if statement.sub!(/^\.([\w\-]+)/) do |match|
+ next if statement.sub!(/^\.([\w\-]+)/) do
class_name = $1
@source << ".#{class_name}"
class_name = Regexp.new("(^|\s)#{Regexp.escape(class_name)}($|\s)") unless class_name.is_a?(Regexp)
@@ -558,7 +558,7 @@ module HTML
end
# Attribute value.
- next if statement.sub!(/^\[\s*([[:alpha:]][\w\-:]*)\s*((?:[~|^$*])?=)?\s*('[^']*'|"[^*]"|[^\]]*)\s*\]/) do |match|
+ next if statement.sub!(/^\[\s*([[:alpha:]][\w\-:]*)\s*((?:[~|^$*])?=)?\s*('[^']*'|"[^*]"|[^\]]*)\s*\]/) do
name, equality, value = $1, $2, $3
if value == "?"
value = values.shift
@@ -575,7 +575,7 @@ module HTML
end
# Root element only.
- next if statement.sub!(/^:root/) do |match|
+ next if statement.sub!(/^:root/) do
pseudo << lambda do |element|
element.parent.nil? || !element.parent.tag?
end
@@ -611,7 +611,7 @@ module HTML
"" # Remove
end
# First/last child (of type).
- next if statement.sub!(/^:(first|last)-(child|of-type)/) do |match|
+ next if statement.sub!(/^:(first|last)-(child|of-type)/) do
reverse = $1 == "last"
of_type = $2 == "of-type"
pseudo << nth_child(0, 1, of_type, reverse)
@@ -619,7 +619,7 @@ module HTML
"" # Remove
end
# Only child (of type).
- next if statement.sub!(/^:only-(child|of-type)/) do |match|
+ next if statement.sub!(/^:only-(child|of-type)/) do
of_type = $1 == "of-type"
pseudo << only_child(of_type)
@source << ":only-#{$1}"
@@ -628,7 +628,7 @@ module HTML
# Empty: no child elements or meaningful content (whitespaces
# are ignored).
- next if statement.sub!(/^:empty/) do |match|
+ next if statement.sub!(/^:empty/) do
pseudo << lambda do |element|
empty = true
for child in element.children
@@ -644,7 +644,7 @@ module HTML
end
# Content: match the text content of the element, stripping
# leading and trailing spaces.
- next if statement.sub!(/^:content\(\s*(\?|'[^']*'|"[^"]*"|[^)]*)\s*\)/) do |match|
+ next if statement.sub!(/^:content\(\s*(\?|'[^']*'|"[^"]*"|[^)]*)\s*\)/) do
content = $1
if content == "?"
content = values.shift
diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb
index 70688d7267..92baad4523 100644
--- a/actionpack/test/abstract/layouts_test.rb
+++ b/actionpack/test/abstract/layouts_test.rb
@@ -72,7 +72,7 @@ module AbstractControllerTests
end
class WithProc < Base
- layout proc { |c| "overwrite" }
+ layout proc { "overwrite" }
def index
render :template => ActionView::Template::Text.new("Hello proc!")
@@ -80,7 +80,7 @@ module AbstractControllerTests
end
class WithProcReturningNil < Base
- layout proc { |c| nil }
+ layout proc { nil }
def index
render template: ActionView::Template::Text.new("Hello nil!")
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 7157bccfb3..8213997f4e 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -332,7 +332,7 @@ end
module ActionDispatch
module RoutingVerbs
- def get(uri_or_host, path = nil, port = nil)
+ def get(uri_or_host, path = nil)
host = uri_or_host.host unless path
path ||= uri_or_host.path
diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb
index a61a1fe99d..34304cf640 100644
--- a/actionpack/test/controller/layout_test.rb
+++ b/actionpack/test/controller/layout_test.rb
@@ -103,7 +103,7 @@ class HasNilLayoutSymbol < LayoutTest
end
class HasNilLayoutProc < LayoutTest
- layout proc { |c| nil }
+ layout proc { nil }
end
class PrependsViewPathController < LayoutTest
diff --git a/actionpack/test/controller/new_base/render_partial_test.rb b/actionpack/test/controller/new_base/render_partial_test.rb
index 2f1aa22208..9e5022c9f4 100644
--- a/actionpack/test/controller/new_base/render_partial_test.rb
+++ b/actionpack/test/controller/new_base/render_partial_test.rb
@@ -5,14 +5,14 @@ module RenderPartial
class BasicController < ActionController::Base
self.view_paths = [ActionView::FixtureResolver.new(
- "render_partial/basic/_basic.html.erb" => "BasicPartial!",
- "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>",
- "render_partial/basic/with_json.html.erb" => "<%= render :partial => 'with_json', :formats => [:json] %>",
- "render_partial/basic/_with_json.json.erb" => "<%= render :partial => 'final', :formats => [:json] %>",
- "render_partial/basic/_final.json.erb" => "{ final: json }",
- "render_partial/basic/overriden.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'overriden' %><%= @test_unchanged %>",
- "render_partial/basic/_overriden.html.erb" => "ParentPartial!",
- "render_partial/child/_overriden.html.erb" => "OverridenPartial!"
+ "render_partial/basic/_basic.html.erb" => "BasicPartial!",
+ "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>",
+ "render_partial/basic/with_json.html.erb" => "<%= render :partial => 'with_json', :formats => [:json] %>",
+ "render_partial/basic/_with_json.json.erb" => "<%= render :partial => 'final', :formats => [:json] %>",
+ "render_partial/basic/_final.json.erb" => "{ final: json }",
+ "render_partial/basic/overridden.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'overridden' %><%= @test_unchanged %>",
+ "render_partial/basic/_overridden.html.erb" => "ParentPartial!",
+ "render_partial/child/_overridden.html.erb" => "OverriddenPartial!"
)]
def html_with_json_inside_json
@@ -24,7 +24,7 @@ module RenderPartial
render :action => "basic"
end
- def overriden
+ def overridden
@test_unchanged = 'hello'
end
end
@@ -55,8 +55,8 @@ module RenderPartial
end
test "partial from child controller gets picked" do
- get :overriden
- assert_response("goodbyeOverridenPartial!goodbye")
+ get :overridden
+ assert_response("goodbyeOverriddenPartial!goodbye")
end
end
diff --git a/actionpack/test/controller/new_base/render_test.rb b/actionpack/test/controller/new_base/render_test.rb
index cc7f12ac6d..5635e16234 100644
--- a/actionpack/test/controller/new_base/render_test.rb
+++ b/actionpack/test/controller/new_base/render_test.rb
@@ -7,10 +7,10 @@ module Render
"render/blank_render/access_request.html.erb" => "The request: <%= request.method.to_s.upcase %>",
"render/blank_render/access_action_name.html.erb" => "Action Name: <%= action_name %>",
"render/blank_render/access_controller_name.html.erb" => "Controller Name: <%= controller_name %>",
- "render/blank_render/overriden_with_own_view_paths_appended.html.erb" => "parent content",
- "render/blank_render/overriden_with_own_view_paths_prepended.html.erb" => "parent content",
- "render/blank_render/overriden.html.erb" => "parent content",
- "render/child_render/overriden.html.erb" => "child content"
+ "render/blank_render/overridden_with_own_view_paths_appended.html.erb" => "parent content",
+ "render/blank_render/overridden_with_own_view_paths_prepended.html.erb" => "parent content",
+ "render/blank_render/overridden.html.erb" => "parent content",
+ "render/child_render/overridden.html.erb" => "child content"
)]
def index
@@ -25,13 +25,13 @@ module Render
render :action => "access_action_name"
end
- def overriden_with_own_view_paths_appended
+ def overridden_with_own_view_paths_appended
end
- def overriden_with_own_view_paths_prepended
+ def overridden_with_own_view_paths_prepended
end
- def overriden
+ def overridden
end
private
@@ -49,8 +49,8 @@ module Render
end
class ChildRenderController < BlankRenderController
- append_view_path ActionView::FixtureResolver.new("render/child_render/overriden_with_own_view_paths_appended.html.erb" => "child content")
- prepend_view_path ActionView::FixtureResolver.new("render/child_render/overriden_with_own_view_paths_prepended.html.erb" => "child content")
+ append_view_path ActionView::FixtureResolver.new("render/child_render/overridden_with_own_view_paths_appended.html.erb" => "child content")
+ prepend_view_path ActionView::FixtureResolver.new("render/child_render/overridden_with_own_view_paths_prepended.html.erb" => "child content")
end
class RenderTest < Rack::TestCase
@@ -114,17 +114,17 @@ module Render
class TestViewInheritance < Rack::TestCase
test "Template from child controller gets picked over parent one" do
- get "/render/child_render/overriden"
+ get "/render/child_render/overridden"
assert_body "child content"
end
test "Template from child controller with custom view_paths prepended gets picked over parent one" do
- get "/render/child_render/overriden_with_own_view_paths_prepended"
+ get "/render/child_render/overridden_with_own_view_paths_prepended"
assert_body "child content"
end
test "Template from child controller with custom view_paths appended gets picked over parent one" do
- get "/render/child_render/overriden_with_own_view_paths_appended"
+ get "/render/child_render/overridden_with_own_view_paths_appended"
assert_body "child content"
end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 978c5aa7ac..f735564305 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -715,17 +715,13 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
def setup_request_method_routes_for(method)
rs.draw do
- match '/match' => 'books#get', :via => :get
- match '/match' => 'books#post', :via => :post
- match '/match' => 'books#put', :via => :put
- match '/match' => 'books#patch', :via => :patch
- match '/match' => 'books#delete', :via => :delete
+ match '/match' => "books##{method}", :via => method.to_sym
end
end
%w(GET PATCH POST PUT DELETE).each do |request_method|
define_method("test_request_method_recognized_with_#{request_method}") do
- setup_request_method_routes_for(request_method)
+ setup_request_method_routes_for(request_method.downcase)
params = rs.recognize_path("/match", :method => request_method)
assert_equal request_method.downcase, params[:action]
end
diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb
index 888791b874..69bf4b7720 100644
--- a/actionpack/test/controller/show_exceptions_test.rb
+++ b/actionpack/test/controller/show_exceptions_test.rb
@@ -47,7 +47,7 @@ module ShowExceptions
end
end
- class ShowExceptionsOverridenController < ShowExceptionsController
+ class ShowExceptionsOverriddenController < ShowExceptionsController
private
def show_detailed_exceptions?
@@ -55,15 +55,15 @@ module ShowExceptions
end
end
- class ShowExceptionsOverridenTest < ActionDispatch::IntegrationTest
+ class ShowExceptionsOverriddenTest < ActionDispatch::IntegrationTest
test 'show error page' do
- @app = ShowExceptionsOverridenController.action(:boom)
+ @app = ShowExceptionsOverriddenController.action(:boom)
get '/', {'detailed' => '0'}
assert_equal "500 error fixture\n", body
end
test 'show diagnostics message' do
- @app = ShowExceptionsOverridenController.action(:boom)
+ @app = ShowExceptionsOverriddenController.action(:boom)
get '/', {'detailed' => '1'}
assert_match(/boom/, body)
end
@@ -71,7 +71,7 @@ module ShowExceptions
class ShowExceptionsFormatsTest < ActionDispatch::IntegrationTest
def test_render_json_exception
- @app = ShowExceptionsOverridenController.action(:boom)
+ @app = ShowExceptionsOverriddenController.action(:boom)
get "/", {}, 'HTTP_ACCEPT' => 'application/json'
assert_response :internal_server_error
assert_equal 'application/json', response.content_type.to_s
@@ -79,7 +79,7 @@ module ShowExceptions
end
def test_render_xml_exception
- @app = ShowExceptionsOverridenController.action(:boom)
+ @app = ShowExceptionsOverriddenController.action(:boom)
get "/", {}, 'HTTP_ACCEPT' => 'application/xml'
assert_response :internal_server_error
assert_equal 'application/xml', response.content_type.to_s
@@ -87,7 +87,7 @@ module ShowExceptions
end
def test_render_fallback_exception
- @app = ShowExceptionsOverridenController.action(:boom)
+ @app = ShowExceptionsOverriddenController.action(:boom)
get "/", {}, 'HTTP_ACCEPT' => 'text/csv'
assert_response :internal_server_error
assert_equal 'text/html', response.content_type.to_s
@@ -96,7 +96,7 @@ module ShowExceptions
class ShowFailsafeExceptionsTest < ActionDispatch::IntegrationTest
def test_render_failsafe_exception
- @app = ShowExceptionsOverridenController.action(:boom)
+ @app = ShowExceptionsOverriddenController.action(:boom)
@exceptions_app = @app.instance_variable_get(:@exceptions_app)
@app.instance_variable_set(:@exceptions_app, nil)
$stderr = StringIO.new
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index e359f47975..88c4b72ad7 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -596,7 +596,7 @@ class UrlHelperControllerTest < ActionController::TestCase
render inline: "<%= url_for controller: 'url_helper_controller_test/url_helper', action: 'show_url_for' %>"
end
- def show_overriden_url_for
+ def show_overridden_url_for
render inline: "<%= url_for params.merge(controller: 'url_helper_controller_test/url_helper', action: 'show_url_for') %>"
end
@@ -633,8 +633,8 @@ class UrlHelperControllerTest < ActionController::TestCase
assert_equal '/url_helper_controller_test/url_helper/show_url_for', @response.body
end
- def test_overriden_url_for_shows_only_path
- get :show_overriden_url_for
+ def test_overridden_url_for_shows_only_path
+ get :show_overridden_url_for
assert_equal '/url_helper_controller_test/url_helper/show_url_for', @response.body
end
@@ -684,7 +684,7 @@ class UrlHelperControllerTest < ActionController::TestCase
assert_equal 'ok', @response.body
end
- def test_url_helper_can_be_overriden
+ def test_url_helper_can_be_overridden
get :override_url_helper
assert_equal '/url_helper_controller_test/url_helper/override_url_helper/override', @response.body
end
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index e4c80b1bf8..9aee47bd52 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,7 +1,18 @@
## Rails 4.0.0 (unreleased) ##
-* Add ActiveModel::Errors#full_messages_for, a method that returns all the error
- messages for a given attribute.
+* Add `ActiveModel::Errors#full_messages_for`, to return all the error messages
+ for a given attribute.
+
+ class Person
+ include ActiveModel::Validations
+
+ attr_reader :name, :email
+ validates_presence_of :name, :email
+ end
+
+ person = Person.new
+ person.valid? # => false
+ person.errors.full_messages_for(:name) # => ["Name can't be blank"]
*Volodymyr Shatsky*
diff --git a/activemodel/README.rdoc b/activemodel/README.rdoc
index 1b1fe2fa2b..a66225319d 100644
--- a/activemodel/README.rdoc
+++ b/activemodel/README.rdoc
@@ -2,7 +2,7 @@
Active Model provides a known set of interfaces for usage in model classes.
They allow for Action Pack helpers to interact with non-Active Record models,
-for example. Active Model also helps building custom ORMs for use outside of
+for example. Active Model also helps with building custom ORMs for use outside of
the Rails framework.
Prior to Rails 3.0, if a plugin or gem developer wanted to have an object
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 485eb1a40a..b60458b3c6 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -12,7 +12,6 @@ module ActiveModel
# A minimal implementation could be:
#
# class Person
- #
# # Required dependency for ActiveModel::Errors
# extend ActiveModel::Naming
#
@@ -40,7 +39,6 @@ module ActiveModel
# def Person.lookup_ancestors
# [self]
# end
- #
# end
#
# The last three methods are required in your object for Errors to be
diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb
index 139fb6795a..80ff97d03b 100644
--- a/activemodel/test/cases/errors_test.rb
+++ b/activemodel/test/cases/errors_test.rb
@@ -54,7 +54,7 @@ class ErrorsTest < ActiveModel::TestCase
assert errors.has_key?(:foo), 'errors should have key :foo'
end
- test "should be able to clear the errors" do
+ test "clear errors" do
person = Person.new
person.validate!
@@ -63,7 +63,7 @@ class ErrorsTest < ActiveModel::TestCase
assert person.errors.empty?
end
- test "get returns the error by the provided key" do
+ test "get returns the errors for the provided key" do
errors = ActiveModel::Errors.new(self)
errors[:foo] = "omg"
@@ -93,21 +93,7 @@ class ErrorsTest < ActiveModel::TestCase
assert_equal [:foo, :baz], errors.keys
end
- test "as_json returns a json formatted representation of the errors hash" do
- person = Person.new
- person.validate!
-
- assert_equal({ name: ["can not be nil"] }, person.errors.as_json)
- end
-
- test "as_json with :full_messages option" do
- person = Person.new
- person.validate!
-
- assert_equal({ name: ["name can not be nil"] }, person.errors.as_json(full_messages: true))
- end
-
- test "should return true if no errors" do
+ test "detecting whether there are errors with empty?, blank?, include?" do
person = Person.new
person.errors[:foo]
assert person.errors.empty?
@@ -115,160 +101,154 @@ class ErrorsTest < ActiveModel::TestCase
assert !person.errors.include?(:foo)
end
- test "method validate! should work" do
+ test "adding errors using conditionals with Person#validate!" do
person = Person.new
person.validate!
assert_equal ["name can not be nil"], person.errors.full_messages
assert_equal ["can not be nil"], person.errors[:name]
end
- test 'should be able to assign error' do
+ test "assign error" do
person = Person.new
person.errors[:name] = 'should not be nil'
assert_equal ["should not be nil"], person.errors[:name]
end
- test 'should be able to add an error on an attribute' do
+ test "add an error message on a specific attribute" do
person = Person.new
person.errors.add(:name, "can not be blank")
assert_equal ["can not be blank"], person.errors[:name]
end
- test "should be able to add an error with a symbol" do
+ test "add an error with a symbol" do
person = Person.new
person.errors.add(:name, :blank)
message = person.errors.generate_message(:name, :blank)
assert_equal [message], person.errors[:name]
end
- test "should be able to add an error with a proc" do
+ test "add an error with a proc" do
person = Person.new
message = Proc.new { "can not be blank" }
person.errors.add(:name, message)
assert_equal ["can not be blank"], person.errors[:name]
end
- test "added? should be true if that error was added" do
+ test "added? detects if a specific error was added to the object" do
person = Person.new
person.errors.add(:name, "can not be blank")
assert person.errors.added?(:name, "can not be blank")
end
- test "added? should handle when message is a symbol" do
+ test "added? handles symbol message" do
person = Person.new
person.errors.add(:name, :blank)
assert person.errors.added?(:name, :blank)
end
- test "added? should handle when message is a proc" do
+ test "added? handles proc messages" do
person = Person.new
message = Proc.new { "can not be blank" }
person.errors.add(:name, message)
assert person.errors.added?(:name, message)
end
- test "added? should default message to :invalid" do
+ test "added? defaults message to :invalid" do
person = Person.new
person.errors.add(:name)
assert person.errors.added?(:name)
end
- test "added? should be true when several errors are present, and we ask for one of them" do
+ test "added? matches the given message when several errors are present for the same attribute" do
person = Person.new
person.errors.add(:name, "can not be blank")
person.errors.add(:name, "is invalid")
assert person.errors.added?(:name, "can not be blank")
end
- test "added? should be false if no errors are present" do
+ test "added? returns false when no errors are present" do
person = Person.new
assert !person.errors.added?(:name)
end
- test "added? should be false when an error is present, but we check for another error" do
+ test "added? returns false when checking a nonexisting error and other errors are present for the given attribute" do
person = Person.new
person.errors.add(:name, "is invalid")
assert !person.errors.added?(:name, "can not be blank")
end
- test 'should respond to size' do
+ test "size calculates the number of error messages" do
person = Person.new
person.errors.add(:name, "can not be blank")
assert_equal 1, person.errors.size
end
- test 'to_a should return an array' do
+ test "to_a returns the list of errors with complete messages containing the attribute names" do
person = Person.new
person.errors.add(:name, "can not be blank")
person.errors.add(:name, "can not be nil")
assert_equal ["name can not be blank", "name can not be nil"], person.errors.to_a
end
- test 'to_hash should return a hash' do
+ test "to_hash returns the error messages hash" do
person = Person.new
person.errors.add(:name, "can not be blank")
- assert_instance_of ::Hash, person.errors.to_hash
+ assert_equal({ name: ["can not be blank"] }, person.errors.to_hash)
end
- test 'full_messages should return an array of error messages, with the attribute name included' do
+ test "full_messages creates a list of error messages with the attribute name included" do
person = Person.new
person.errors.add(:name, "can not be blank")
person.errors.add(:name, "can not be nil")
assert_equal ["name can not be blank", "name can not be nil"], person.errors.full_messages
end
-
- test 'full_messages_for should contain all the messages for a given attribute' do
+
+ test "full_messages_for contains all the error messages for the given attribute" do
person = Person.new
person.errors.add(:name, "can not be blank")
person.errors.add(:name, "can not be nil")
assert_equal ["name can not be blank", "name can not be nil"], person.errors.full_messages_for(:name)
end
- test 'full_messages_for should not contain messages for another attributes' do
+ test "full_messages_for does not contain error messages from other attributes" do
person = Person.new
person.errors.add(:name, "can not be blank")
person.errors.add(:email, "can not be blank")
assert_equal ["name can not be blank"], person.errors.full_messages_for(:name)
end
- test "full_messages_for should return an empty array in case if errors hash doesn't contain a given attribute" do
+ test "full_messages_for returns an empty list in case there are no errors for the given attribute" do
person = Person.new
person.errors.add(:name, "can not be blank")
assert_equal [], person.errors.full_messages_for(:email)
end
- test 'full_message should return the given message if attribute equals :base' do
+ test "full_message returns the given message when attribute is :base" do
person = Person.new
assert_equal "press the button", person.errors.full_message(:base, "press the button")
end
- test 'full_message should return the given message with the attribute name included' do
+ test "full_message returns the given message with the attribute name included" do
person = Person.new
assert_equal "name can not be blank", person.errors.full_message(:name, "can not be blank")
assert_equal "name_test can not be blank", person.errors.full_message(:name_test, "can not be blank")
end
- test 'should return a JSON hash representation of the errors' do
+ test "as_json creates a json formatted representation of the errors hash" do
person = Person.new
- person.errors.add(:name, "can not be blank")
- person.errors.add(:name, "can not be nil")
- person.errors.add(:email, "is invalid")
- hash = person.errors.as_json
- assert_equal ["can not be blank", "can not be nil"], hash[:name]
- assert_equal ["is invalid"], hash[:email]
+ person.validate!
+
+ assert_equal({ name: ["can not be nil"] }, person.errors.as_json)
end
- test 'should return a JSON hash representation of the errors with full messages' do
+ test "as_json with :full_messages option creates a json formatted representation of the errors containing complete messages" do
person = Person.new
- person.errors.add(:name, "can not be blank")
- person.errors.add(:name, "can not be nil")
- person.errors.add(:email, "is invalid")
- hash = person.errors.as_json(:full_messages => true)
- assert_equal ["name can not be blank", "name can not be nil"], hash[:name]
- assert_equal ["email is invalid"], hash[:email]
+ person.validate!
+
+ assert_equal({ name: ["name can not be nil"] }, person.errors.as_json(full_messages: true))
end
- test "generate_message should work without i18n_scope" do
+ test "generate_message works without i18n_scope" do
person = Person.new
assert !Person.respond_to?(:i18n_scope)
assert_nothing_raised {
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 3fe8d7ec2e..526cc874e9 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,33 +1,41 @@
## Rails 4.0.0 (unreleased) ##
-* Allow ActiveRecord::Base.connection_handler to have thread affinity and be
- settable, this effectively allows ActiveRecord to be used in a multi threaded
+* Allow `ActiveRecord::Base.connection_handler` to have thread affinity and be
+ settable, this effectively allows Active Record to be used in a multi threaded
setup with multiple connections to multiple dbs.
*Sam Saffron*
-* `rename_column` preserves auto_increment in mysql migrations.
+* `rename_column` preserves `auto_increment` in MySQL migrations.
Fixes #3493.
*Vipul A M*
-* PostgreSQL geometric type point is supported by ActiveRecord. Fixes #7324.
+* PostgreSQL geometric type point is now supported by Active Record. Fixes #7324.
*Martin Schuerrer*
-* Add suport for concurrent indexing in PostgreSQL adapter via the
- `algorithm: :concurrently` option
+* Add support for concurrent indexing in PostgreSQL adapter via the
+ `algorithm: :concurrently` option.
add_index(:people, :last_name, algorithm: :concurrently)
- Also adds support for MySQL index algorithms (`COPY`, `INPLACE`,
- `DEFAULT`) via the `algorithm: :copy` option
+ Also add support for MySQL index algorithms (`COPY`, `INPLACE`,
+ `DEFAULT`) via the `:algorithm` option.
add_index(:people, :last_name, algorithm: :copy) # or :inplace/:default
*Dan McClain*
-* Add an `add_index` override in Postgresql adapter and MySQL adapter
+* Add support for fulltext and spatial indexes on MySQL tables with MyISAM database
+ engine via the `type: 'FULLTEXT'` / `type: 'SPATIAL'` option.
+
+ add_index(:people, :last_name, type: 'FULLTEXT')
+ add_index(:people, :last_name, type: 'SPATIAL')
+
+ *Ken Mazaika*
+
+* Add an `add_index` override in PostgreSQL adapter and MySQL adapter
to allow custom index type support. Fixes #6101.
add_index(:wikis, :body, :using => 'gin')
diff --git a/activerecord/README.rdoc b/activerecord/README.rdoc
index ed1e171d58..822e460918 100644
--- a/activerecord/README.rdoc
+++ b/activerecord/README.rdoc
@@ -190,7 +190,7 @@ The latest version of Active Record can be installed with RubyGems:
% [sudo] gem install activerecord
-Source code can be downloaded as part of the Rails project on GitHub
+Source code can be downloaded as part of the Rails project on GitHub:
* https://github.com/rails/rails/tree/master/activerecord
@@ -204,7 +204,7 @@ Active Record is released under the MIT license:
== Support
-API documentation is at
+API documentation is at:
* http://api.rubyonrails.org
diff --git a/activerecord/examples/associations.png b/activerecord/examples/associations.png
deleted file mode 100644
index 661c7a8bbc..0000000000
--- a/activerecord/examples/associations.png
+++ /dev/null
Binary files differ
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index eb08f72286..4fd817bd8c 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1115,11 +1115,11 @@ module ActiveRecord
# similar callbacks may affect the :dependent behavior, and the
# :dependent behavior may affect other callbacks.
#
- # * <tt>:destroy</tt> causes all the associated objects to also be destroyed
- # * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not execute)
+ # * <tt>:destroy</tt> causes all the associated objects to also be destroyed.
+ # * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
# * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Callbacks are not executed.
- # * <tt>:restrict_with_exception</tt> causes an exception to be raised if there are any associated records
- # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects
+ # * <tt>:restrict_with_exception</tt> causes an exception to be raised if there are any associated records.
+ # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
#
# If using with the <tt>:through</tt> option, the association on the join model must be
# a +belongs_to+, and the records which get deleted are the join records, rather than
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index 4c4b0f08e5..f3f4792eaa 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -92,7 +92,7 @@ module ActiveRecord
# The scope for this association.
#
# Note that the association_scope is merged into the target_scope only when the
- # scoped method is called. This is because at that point the call may be surrounded
+ # scope method is called. This is because at that point the call may be surrounded
# by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
# actually gets built.
def association_scope
@@ -113,7 +113,7 @@ module ActiveRecord
end
end
- # This class of the target. belongs_to polymorphic overrides this to look at the
+ # Returns the class of the target. belongs_to polymorphic overrides this to look at the
# polymorphic_type field on the owner.
def klass
reflection.klass
@@ -217,7 +217,8 @@ module ActiveRecord
reflection.inverse_of
end
- # Is this association invertible? Can be redefined by subclasses.
+ # Returns true if inverse association on the given record needs to be set.
+ # This method is redefined by subclasses.
def invertible_for?(record)
inverse_reflection_for(record)
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 2f17e47b7c..eb974e4a6e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -8,7 +8,7 @@ module ActiveRecord
# Abstract representation of an index definition on a table. Instances of
# this type are typically created and returned by methods in database
# adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :using) #:nodoc:
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using) #:nodoc:
end
# Abstract representation of a column definition. Instances of this type
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index e95e97e4a8..9c0c4e3ef0 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -443,7 +443,7 @@ module ActiveRecord
#
# add_index(:suppliers, :name)
#
- # generates
+ # generates:
#
# CREATE INDEX suppliers_name_index ON suppliers(name)
#
@@ -451,7 +451,7 @@ module ActiveRecord
#
# add_index(:accounts, [:branch_id, :party_id], unique: true)
#
- # generates
+ # generates:
#
# CREATE UNIQUE INDEX accounts_branch_id_party_id_index ON accounts(branch_id, party_id)
#
@@ -459,7 +459,7 @@ module ActiveRecord
#
# add_index(:accounts, [:branch_id, :party_id], unique: true, name: 'by_branch_party')
#
- # generates
+ # generates:
#
# CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
#
@@ -467,13 +467,13 @@ module ActiveRecord
#
# add_index(:accounts, :name, name: 'by_name', length: 10)
#
- # generates
+ # generates:
#
# CREATE INDEX by_name ON accounts(name(10))
#
# add_index(:accounts, [:name, :surname], name: 'by_name_surname', length: {name: 10, surname: 15})
#
- # generates
+ # generates:
#
# CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
#
@@ -483,7 +483,7 @@ module ActiveRecord
#
# add_index(:accounts, [:branch_id, :party_id, :surname], order: {branch_id: :desc, party_id: :asc})
#
- # generates
+ # generates:
#
# CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
#
@@ -493,18 +493,30 @@ module ActiveRecord
#
# add_index(:accounts, [:branch_id, :party_id], unique: true, where: "active")
#
- # generates
+ # generates:
#
# CREATE UNIQUE INDEX index_accounts_on_branch_id_and_party_id ON accounts(branch_id, party_id) WHERE active
#
# ====== Creating an index with a specific method
- # add_index(:developers, :name, :using => 'btree')
- # generates
- # CREATE INDEX index_developers_on_name ON developers USING btree (name) -- PostgreSQL
- # CREATE INDEX index_developers_on_name USING btree ON developers (name) -- MySQL
+ #
+ # add_index(:developers, :name, using: 'btree')
+ #
+ # generates:
+ #
+ # CREATE INDEX index_developers_on_name ON developers USING btree (name) -- PostgreSQL
+ # CREATE INDEX index_developers_on_name USING btree ON developers (name) -- MySQL
#
# Note: only supported by PostgreSQL and MySQL
#
+ # ====== Creating an index with a specific type
+ #
+ # add_index(:developers, :name, type: :fulltext)
+ #
+ # generates:
+ #
+ # CREATE FULLTEXT INDEX index_developers_on_name ON developers (name) -- MySQL
+ #
+ # Note: only supported by MySQL. Supported: <tt>:fulltext</tt> and <tt>:spatial</tt> on MyISAM tables.
def add_index(table_name, column_name, options = {})
index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})#{index_options}"
@@ -755,16 +767,17 @@ module ActiveRecord
index_name = index_name(table_name, column: column_names)
if Hash === options # legacy support, since this param was a string
- options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm)
+ options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type)
index_type = options[:unique] ? "UNIQUE" : ""
+ index_type = options[:type].to_s if options.key?(:type)
index_name = options[:name].to_s if options.key?(:name)
max_index_length = options.fetch(:internal, false) ? index_name_length : allowed_index_name_length
- if index_algorithms.key?(options[:algorithm])
- algorithm = index_algorithms[options[:algorithm]]
- elsif options[:algorithm].present?
- raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}")
+ if options.key?(:algorithm)
+ algorithm = index_algorithms.fetch(options[:algorithm]) {
+ raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}")
+ }
end
using = "USING #{options[:using]}" if options[:using].present?
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 1915c444ef..1138b10a1b 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -101,6 +101,10 @@ module ActiveRecord
@visitor = nil
end
+ def valid_type?(type)
+ true
+ end
+
class SchemaCreation
def initialize(conn)
@conn = conn
@@ -282,9 +286,8 @@ module ActiveRecord
[]
end
- # A list of index algorithms, to be filled by adapters that
- # support them. MySQL and PostgreSQL has support for them right
- # now.
+ # A list of index algorithms, to be filled by adapters that support them.
+ # MySQL and PostgreSQL have support for them right now.
def index_algorithms
{}
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index cc5e6ac44d..b0b160f9b4 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -151,6 +151,9 @@ module ActiveRecord
:boolean => { :name => "tinyint", :limit => 1 }
}
+ INDEX_TYPES = [:fulltext, :spatial]
+ INDEX_USINGS = [:btree, :hash]
+
class BindSubstitution < Arel::Visitors::MySQL # :nodoc:
include Arel::Visitors::BindVisitor
end
@@ -435,8 +438,11 @@ module ActiveRecord
if current_index != row[:Key_name]
next if row[:Key_name] == 'PRIMARY' # skip the primary key
current_index = row[:Key_name]
- indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], [])
- indexes.last.using = row[:Index_type].downcase.to_sym
+
+ mysql_index_type = row[:Index_type].downcase.to_sym
+ index_type = INDEX_TYPES.include?(mysql_index_type) ? mysql_index_type : nil
+ index_using = INDEX_USINGS.include?(mysql_index_type) ? mysql_index_type : nil
+ indexes << IndexDefinition.new(row[:Table], row[:Key_name], row[:Non_unique].to_i == 0, [], [], nil, nil, index_type, index_using)
end
indexes.last.columns << row[:Column_name]
diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
index 6b319fed88..530a27d099 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
@@ -4,7 +4,7 @@ gem 'mysql2', '~> 0.3.10'
require 'mysql2'
module ActiveRecord
- module ConnectionHandling
+ module ConnectionHandling # :nodoc:
# Establishes a connection to the database that's used by all Active Record objects.
def mysql2_connection(config)
config = config.symbolize_keys
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 0e01fe0fdb..09ba2e0d4a 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -16,9 +16,9 @@ class Mysql
end
module ActiveRecord
- module ConnectionHandling
+ module ConnectionHandling # :nodoc:
# Establishes a connection to the database that's used by all Active Record objects.
- def mysql_connection(config) # :nodoc:
+ def mysql_connection(config)
config = config.symbolize_keys
host = config[:host]
port = config[:port]
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 0e1afbae8d..d9b807bba4 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -156,13 +156,15 @@ module ActiveRecord
column_names = columns.values_at(*indkey).compact
- # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
- desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
- orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
- where = inddef.scan(/WHERE (.+)$/).flatten[0]
- type = inddef.scan(/USING (.+?) /).flatten[0].to_sym
-
- column_names.empty? ? nil : IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, type)
+ unless column_names.empty?
+ # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
+ desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
+ orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
+ where = inddef.scan(/WHERE (.+)$/).flatten[0]
+ using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
+
+ IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, nil, using)
+ end
end.compact
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 46e41e6b48..e34e1fc10c 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -16,7 +16,7 @@ require 'pg'
require 'ipaddr'
module ActiveRecord
- module ConnectionHandling
+ module ConnectionHandling # :nodoc:
VALID_CONN_PARAMS = [:host, :hostaddr, :port, :dbname, :user, :password, :connect_timeout,
:client_encoding, :options, :application_name, :fallback_application_name,
:keepalives, :keepalives_idle, :keepalives_interval, :keepalives_count,
@@ -24,7 +24,7 @@ module ActiveRecord
:requirepeer, :krbsrvname, :gsslib, :service]
# Establishes a connection to the database that's used by all Active Record objects
- def postgresql_connection(config) # :nodoc:
+ def postgresql_connection(config)
conn_params = config.symbolize_keys
conn_params.delete_if { |_, v| v.nil? }
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index c3bebf7a5e..7d940fe1c9 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -6,9 +6,9 @@ gem 'sqlite3', '~> 1.3.6'
require 'sqlite3'
module ActiveRecord
- module ConnectionHandling
+ module ConnectionHandling # :nodoc:
# sqlite3 adapter reuses sqlite_connection.
- def sqlite3_connection(config) # :nodoc:
+ def sqlite3_connection(config)
# Require database.
unless config[:database]
raise ArgumentError, "No database file specified. Missing argument: database"
@@ -499,10 +499,6 @@ module ActiveRecord
rename_column_indexes(table_name, column_name, new_column_name)
end
- def valid_type?(type)
- true
- end
-
protected
def select(sql, name = nil, binds = []) #:nodoc:
exec_query(sql, name, binds)
diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb
index d6d998c7be..1e03414c29 100644
--- a/activerecord/lib/active_record/connection_handling.rb
+++ b/activerecord/lib/active_record/connection_handling.rb
@@ -15,15 +15,15 @@ module ActiveRecord
# Example for SQLite database:
#
# ActiveRecord::Base.establish_connection(
- # adapter: "sqlite",
- # database: "path/to/dbfile"
+ # adapter: "sqlite",
+ # database: "path/to/dbfile"
# )
#
# Also accepts keys as strings (for parsing from YAML for example):
#
# ActiveRecord::Base.establish_connection(
- # "adapter" => "sqlite",
- # "database" => "path/to/dbfile"
+ # "adapter" => "sqlite",
+ # "database" => "path/to/dbfile"
# )
#
# Or a URL:
@@ -79,7 +79,7 @@ module ActiveRecord
connection_handler.retrieve_connection(self)
end
- # Returns true if Active Record is connected.
+ # Returns +true+ if Active Record is connected.
def connected?
connection_handler.connected?(self)
end
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 1ed05c1bd4..db5e7b82ca 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -78,7 +78,7 @@ module ActiveRecord
self.disable_implicit_join_references = false
class_attribute :default_connection_handler, instance_writer: false
-
+
def self.connection_handler
Thread.current[:active_record_connection_handler] || self.default_connection_handler
end
@@ -444,7 +444,7 @@ module ActiveRecord
end
def init_changed_attributes
- # Intentionally avoid using #column_defaults since overriden defaults (as is done in
+ # Intentionally avoid using #column_defaults since overridden defaults (as is done in
# optimistic locking) won't get written unless they get marked as changed
self.class.columns.each do |c|
attr, orig_value = c.name, c.default
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index 602ab9e2f4..f0c29bbf73 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -90,8 +90,9 @@ module ActiveRecord
# accepts_nested_attributes_for :posts
# end
#
- # You can now set or update attributes on an associated post model through
- # the attribute hash.
+ # You can now set or update attributes on the associated posts through
+ # an attribute hash for a member: include the key +:posts_attributes+
+ # with an array of hashes of post attributes as a value.
#
# For each hash that does _not_ have an <tt>id</tt> key a new record will
# be instantiated, unless the hash also contains a <tt>_destroy</tt> key
@@ -114,10 +115,10 @@ module ActiveRecord
# hashes if they fail to pass your criteria. For example, the previous
# example could be rewritten as:
#
- # class Member < ActiveRecord::Base
- # has_many :posts
- # accepts_nested_attributes_for :posts, reject_if: proc { |attributes| attributes['title'].blank? }
- # end
+ # class Member < ActiveRecord::Base
+ # has_many :posts
+ # accepts_nested_attributes_for :posts, reject_if: proc { |attributes| attributes['title'].blank? }
+ # end
#
# params = { member: {
# name: 'joe', posts_attributes: [
@@ -134,19 +135,19 @@ module ActiveRecord
#
# Alternatively, :reject_if also accepts a symbol for using methods:
#
- # class Member < ActiveRecord::Base
- # has_many :posts
- # accepts_nested_attributes_for :posts, reject_if: :new_record?
- # end
+ # class Member < ActiveRecord::Base
+ # has_many :posts
+ # accepts_nested_attributes_for :posts, reject_if: :new_record?
+ # end
#
- # class Member < ActiveRecord::Base
- # has_many :posts
- # accepts_nested_attributes_for :posts, reject_if: :reject_posts
+ # class Member < ActiveRecord::Base
+ # has_many :posts
+ # accepts_nested_attributes_for :posts, reject_if: :reject_posts
#
- # def reject_posts(attributed)
- # attributed['title'].blank?
- # end
- # end
+ # def reject_posts(attributed)
+ # attributed['title'].blank?
+ # end
+ # end
#
# If the hash contains an <tt>id</tt> key that matches an already
# associated record, the matching record will be modified:
@@ -183,6 +184,29 @@ module ActiveRecord
# member.save
# member.reload.posts.length # => 1
#
+ # Nested attributes for an associated collection can also be passed in
+ # the form of a hash of hashes instead of an array of hashes:
+ #
+ # Member.create(name: 'joe',
+ # posts_attributes: { first: { title: 'Foo' },
+ # second: { title: 'Bar' } })
+ #
+ # has the same effect as
+ #
+ # Member.create(name: 'joe',
+ # posts_attributes: [ { title: 'Foo' },
+ # { title: 'Bar' } ])
+ #
+ # The keys of the hash which is the value for +:posts_attributes+ are
+ # ignored in this case.
+ # However, it is not allowed to use +'id'+ or +:id+ for one of
+ # such keys, otherwise the hash will be wrapped in an array and
+ # interpreted as an attribute hash for a single post.
+ #
+ # Passing attributes for an associated collection in the form of a hash
+ # of hashes can be used with hashes generated from HTTP/HTML parameters,
+ # where there maybe no natural way to submit an array of hashes.
+ #
# === Saving
#
# All changes to models, including the destruction of those marked for
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index f881778591..42cece3ad0 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -443,7 +443,7 @@ module ActiveRecord
real_column = db_columns_with_values[i].first
bind_attrs[column] = klass.connection.substitute_at(real_column, i)
end
- stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id_was)).arel.compile_update(bind_attrs)
+ stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id_was || id)).arel.compile_update(bind_attrs)
klass.connection.update stmt, 'SQL', db_columns_with_values
end
end
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index be011b22af..4f60704790 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -135,7 +135,7 @@ module ActiveRecord
# # SELECT people.id, people.name FROM people
# # => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]
#
- # Person.uniq.pluck(:role)
+ # Person.pluck('DISTINCT role')
# # SELECT DISTINCT role FROM people
# # => ['admin', 'member', 'guest']
#
diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb
index fa9de926c5..10c6d272cd 100644
--- a/activerecord/lib/active_record/schema_dumper.rb
+++ b/activerecord/lib/active_record/schema_dumper.rb
@@ -185,6 +185,10 @@ HEADER
statement_parts << ('where: ' + index.where.inspect) if index.where
+ statement_parts << ('using: ' + index.using.inspect) if index.using
+
+ statement_parts << ('type: ' + index.type.inspect) if index.type
+
' ' + statement_parts.join(', ')
end
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index 0af7cbf74f..e28bb7b6ca 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -114,7 +114,7 @@ module ActiveRecord
end
end
- # test resetting sequences in odd tables in postgreSQL
+ # test resetting sequences in odd tables in PostgreSQL
if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!)
require 'models/movie'
require 'models/subscriber'
@@ -167,7 +167,7 @@ module ActiveRecord
else
@connection.execute "INSERT INTO fk_test_has_fk (fk_id) VALUES (0)"
end
- # should deleted created record as otherwise disable_referential_integrity will try to enable contraints after executed block
+ # should delete created record as otherwise disable_referential_integrity will try to enable constraints after executed block
# and will fail (at least on Oracle)
@connection.execute "DELETE FROM fk_test_has_fk"
end
diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
index 9050ae3fe3..e6d0183b11 100644
--- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
@@ -36,9 +36,14 @@ class ActiveSchemaTest < ActiveRecord::TestCase
expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(10)) "
assert_equal expected, add_index(:people, [:last_name, :first_name], :length => {:last_name => 15, :first_name => 10})
- %w(btree hash).each do |type|
- expected = "CREATE INDEX `index_people_on_last_name` USING #{type} ON `people` (`last_name`) "
- assert_equal expected, add_index(:people, :last_name, :using => type)
+ %w(SPATIAL FULLTEXT UNIQUE).each do |type|
+ expected = "CREATE #{type} INDEX `index_people_on_last_name` ON `people` (`last_name`) "
+ assert_equal expected, add_index(:people, :last_name, :type => type)
+ end
+
+ %w(btree hash).each do |using|
+ expected = "CREATE INDEX `index_people_on_last_name` USING #{using} ON `people` (`last_name`) "
+ assert_equal expected, add_index(:people, :last_name, :using => using)
end
expected = "CREATE INDEX `index_people_on_last_name` USING btree ON `people` (`last_name`(10)) "
diff --git a/activerecord/test/cases/adapters/mysql/schema_test.rb b/activerecord/test/cases/adapters/mysql/schema_test.rb
index e6e54bf20a..807a7a155e 100644
--- a/activerecord/test/cases/adapters/mysql/schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql/schema_test.rb
@@ -37,22 +37,25 @@ module ActiveRecord
end
def test_dump_indexes
- index_a_name = 'index_post_title'
- index_b_name = 'index_post_body'
+ index_a_name = 'index_key_tests_on_snack'
+ index_b_name = 'index_key_tests_on_pizza'
+ index_c_name = 'index_key_tests_on_awesome'
- table = Post.table_name
-
- @connection.execute "CREATE INDEX `#{index_a_name}` ON `#{table}` (`title`);"
- @connection.execute "CREATE INDEX `#{index_b_name}` USING btree ON `#{table}` (`body`(10));"
+ table = 'key_tests'
indexes = @connection.indexes(table).sort_by {|i| i.name}
- assert_equal 2,indexes.size
-
- assert_equal :btree, indexes.select{|i| i.name == index_a_name}[0].using
- assert_equal :btree, indexes.select{|i| i.name == index_b_name}[0].using
-
- @connection.execute "DROP INDEX `#{index_a_name}` ON `#{table}`;"
- @connection.execute "DROP INDEX `#{index_b_name}` ON `#{table}`;"
+ assert_equal 3,indexes.size
+
+ index_a = indexes.select{|i| i.name == index_a_name}[0]
+ index_b = indexes.select{|i| i.name == index_b_name}[0]
+ index_c = indexes.select{|i| i.name == index_c_name}[0]
+ assert_equal :btree, index_a.using
+ assert_nil index_a.type
+ assert_equal :btree, index_b.using
+ assert_nil index_b.type
+
+ assert_nil index_c.using
+ assert_equal :fulltext, index_c.type
end
end
end
diff --git a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
index 48d63aeef5..8a2a7ef269 100644
--- a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb
@@ -36,9 +36,14 @@ class ActiveSchemaTest < ActiveRecord::TestCase
expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(10)) "
assert_equal expected, add_index(:people, [:last_name, :first_name], :length => {:last_name => 15, :first_name => 10})
- %w(btree hash).each do |type|
- expected = "CREATE INDEX `index_people_on_last_name` USING #{type} ON `people` (`last_name`) "
- assert_equal expected, add_index(:people, :last_name, :using => type)
+ %w(SPATIAL FULLTEXT UNIQUE).each do |type|
+ expected = "CREATE #{type} INDEX `index_people_on_last_name` ON `people` (`last_name`) "
+ assert_equal expected, add_index(:people, :last_name, :type => type)
+ end
+
+ %w(btree hash).each do |using|
+ expected = "CREATE INDEX `index_people_on_last_name` USING #{using} ON `people` (`last_name`) "
+ assert_equal expected, add_index(:people, :last_name, :using => using)
end
expected = "CREATE INDEX `index_people_on_last_name` USING btree ON `people` (`last_name`(10)) "
diff --git a/activerecord/test/cases/adapters/mysql2/schema_test.rb b/activerecord/test/cases/adapters/mysql2/schema_test.rb
index 78f754d2ce..5db60ff8a0 100644
--- a/activerecord/test/cases/adapters/mysql2/schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/schema_test.rb
@@ -45,22 +45,25 @@ module ActiveRecord
end
def test_dump_indexes
- index_a_name = 'index_post_title'
- index_b_name = 'index_post_body'
+ index_a_name = 'index_key_tests_on_snack'
+ index_b_name = 'index_key_tests_on_pizza'
+ index_c_name = 'index_key_tests_on_awesome'
- table = Post.table_name
-
- @connection.execute "CREATE INDEX `#{index_a_name}` ON `#{table}` (`title`);"
- @connection.execute "CREATE INDEX `#{index_b_name}` USING btree ON `#{table}` (`body`(10));"
+ table = 'key_tests'
indexes = @connection.indexes(table).sort_by {|i| i.name}
- assert_equal 2,indexes.size
+ assert_equal 3,indexes.size
- assert_equal :btree, indexes.select{|i| i.name == index_a_name}[0].using
- assert_equal :btree, indexes.select{|i| i.name == index_b_name}[0].using
+ index_a = indexes.select{|i| i.name == index_a_name}[0]
+ index_b = indexes.select{|i| i.name == index_b_name}[0]
+ index_c = indexes.select{|i| i.name == index_c_name}[0]
+ assert_equal :btree, index_a.using
+ assert_nil index_a.type
+ assert_equal :btree, index_b.using
+ assert_nil index_b.type
- @connection.execute "DROP INDEX `#{index_a_name}` ON `#{table}`;"
- @connection.execute "DROP INDEX `#{index_b_name}` ON `#{table}`;"
+ assert_nil index_c.using
+ assert_equal :fulltext, index_c.type
end
end
end
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index dcbec24acf..d51d425c3c 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -30,6 +30,10 @@ module ActiveRecord
assert @conn.valid_type?(column.type)
end
+ # sqlite databses should be able to support any type and not
+ # just the ones mentioned in the native_database_types.
+ # Therefore test_invalid column should always return true
+ # even if the type is not valid.
def test_invalid_column
assert @conn.valid_type?(:foobar)
end
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index e5cb4f8f7a..536ff4882c 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -439,7 +439,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
end
def test_assign_ids_for_through_a_belongs_to
- post = Post.new(:title => "Assigning IDs works!", :body => "You heared it here first, folks!")
+ post = Post.new(:title => "Assigning IDs works!", :body => "You heard it here first, folks!")
post.person_ids = [people(:david).id, people(:michael).id]
post.save
post.reload
@@ -1335,7 +1335,7 @@ class TestAutosaveAssociationValidationsOnAHasOneAssociation < ActiveRecord::Tes
assert !@pirate.valid?
end
- test "should not automatically asd validate associations without :validate => true" do
+ test "should not automatically add validate associations without :validate => true" do
assert @pirate.valid?
@pirate.non_validated_ship.name = ''
assert @pirate.valid?
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 69eef500f5..08223902c7 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1579,7 +1579,7 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal ['foo'], klass.all.merge!(select: 'foo').select_values
end
- test "connection_handler can be overriden" do
+ test "connection_handler can be overridden" do
klass = Class.new(ActiveRecord::Base)
orig_handler = klass.connection_handler
new_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb
index 87559925e7..ba6b0b1362 100644
--- a/activerecord/test/cases/batches_test.rb
+++ b/activerecord/test/cases/batches_test.rb
@@ -19,7 +19,7 @@ class EachTest < ActiveRecord::TestCase
end
end
- def test_each_should_not_return_query_chain_and_execcute_only_one_query
+ def test_each_should_not_return_query_chain_and_execute_only_one_query
assert_queries(1) do
result = Post.find_each(:batch_size => 100000){ }
assert_nil result
@@ -68,7 +68,7 @@ class EachTest < ActiveRecord::TestCase
end
end
- def test_find_in_batches_shouldnt_excute_query_unless_needed
+ def test_find_in_batches_shouldnt_execute_query_unless_needed
post_count = Post.count
assert_queries(2) do
diff --git a/activerecord/test/cases/dup_test.rb b/activerecord/test/cases/dup_test.rb
index dbf6005a67..f73e449610 100644
--- a/activerecord/test/cases/dup_test.rb
+++ b/activerecord/test/cases/dup_test.rb
@@ -128,7 +128,7 @@ module ActiveRecord
prev_default_scopes = Topic.default_scopes
Topic.default_scopes = [Topic.where(:approved => true)]
topic = Topic.new(:approved => false)
- assert !topic.dup.approved?, "should not be overriden by default scopes"
+ assert !topic.dup.approved?, "should not be overridden by default scopes"
ensure
Topic.default_scopes = prev_default_scopes
end
diff --git a/activerecord/test/cases/migration/columns_test.rb b/activerecord/test/cases/migration/columns_test.rb
index 52906c8a01..2d7a7ec73a 100644
--- a/activerecord/test/cases/migration/columns_test.rb
+++ b/activerecord/test/cases/migration/columns_test.rb
@@ -55,10 +55,10 @@ module ActiveRecord
default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
assert_equal 70000, default_before
- rename_column "test_models", "salary", "anual_salary"
+ rename_column "test_models", "salary", "annual_salary"
- assert TestModel.column_names.include?("anual_salary")
- default_after = connection.columns("test_models").find { |c| c.name == "anual_salary" }.default
+ assert TestModel.column_names.include?("annual_salary")
+ default_after = connection.columns("test_models").find { |c| c.name == "annual_salary" }.default
assert_equal 70000, default_after
end
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index a29189df05..572431ee87 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -247,15 +247,15 @@ class PersistencesTest < ActiveRecord::TestCase
topic.title = "Another New Topic"
topic.written_on = "2003-12-12 23:23:00"
topic.save
- topicReloaded = Topic.find(topic.id)
- assert_equal("Another New Topic", topicReloaded.title)
+ topic_reloaded = Topic.find(topic.id)
+ assert_equal("Another New Topic", topic_reloaded.title)
- topicReloaded.title = "Updated topic"
- topicReloaded.save
+ topic_reloaded.title = "Updated topic"
+ topic_reloaded.save
- topicReloadedAgain = Topic.find(topic.id)
+ topic_reloaded_again = Topic.find(topic.id)
- assert_equal("Updated topic", topicReloadedAgain.title)
+ assert_equal("Updated topic", topic_reloaded_again.title)
end
def test_update_columns_not_equal_attributes
@@ -263,12 +263,12 @@ class PersistencesTest < ActiveRecord::TestCase
topic.title = "Still another topic"
topic.save
- topicReloaded = Topic.allocate
- topicReloaded.init_with(
+ topic_reloaded = Topic.allocate
+ topic_reloaded.init_with(
'attributes' => topic.attributes.merge('does_not_exist' => 'test')
)
- topicReloaded.title = 'A New Topic'
- assert_nothing_raised { topicReloaded.save }
+ topic_reloaded.title = 'A New Topic'
+ assert_nothing_raised { topic_reloaded.save }
end
def test_update_for_record_with_only_primary_key
@@ -296,6 +296,22 @@ class PersistencesTest < ActiveRecord::TestCase
assert_equal "Reply", topic.type
end
+ def test_update_after_create
+ klass = Class.new(Topic) do
+ def self.name; 'Topic'; end
+ after_create do
+ update_attribute("author_name", "David")
+ end
+ end
+ topic = klass.new
+ topic.title = "Another New Topic"
+ topic.save
+
+ topic_reloaded = Topic.find(topic.id)
+ assert_equal("Another New Topic", topic_reloaded.title)
+ assert_equal("David", topic_reloaded.author_name)
+ end
+
def test_delete
topic = Topic.find(1)
assert_equal topic, topic.delete, 'topic.delete did not return self'
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 1147b9a09e..9944527d48 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -177,13 +177,19 @@ class SchemaDumperTest < ActiveRecord::TestCase
def test_schema_dumps_index_columns_in_right_order
index_definition = standard_dump.split(/\n/).grep(/add_index.*companies/).first.strip
- assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index"', index_definition
+ if current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter) || current_adapter?(:PostgreSQLAdapter)
+ assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index", using: :btree', index_definition
+ else
+ assert_equal 'add_index "companies", ["firm_id", "type", "rating"], name: "company_index"', index_definition
+ end
end
def test_schema_dumps_partial_indices
index_definition = standard_dump.split(/\n/).grep(/add_index.*company_partial_index/).first.strip
if current_adapter?(:PostgreSQLAdapter)
- assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)"', index_definition
+ assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition
+ elsif current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter)
+ assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", using: :btree', index_definition
else
assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index"', index_definition
end
@@ -219,6 +225,12 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r{t.text\s+"medium_text",\s+limit: 16777215$}, output
assert_match %r{t.text\s+"long_text",\s+limit: 2147483647$}, output
end
+
+ def test_schema_dumps_index_type
+ output = standard_dump
+ assert_match %r{add_index "key_tests", \["awesome"\], name: "index_key_tests_on_awesome", type: :fulltext}, output
+ assert_match %r{add_index "key_tests", \["pizza"\], name: "index_key_tests_on_pizza", using: :btree}, output
+ end
end
def test_schema_dump_includes_decimal_options
diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index 6cd89b6227..5a65ad5dfa 100644
--- a/activerecord/test/cases/relation_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -1,334 +1,6 @@
-require "cases/helper"
+require 'cases/helper'
require 'models/post'
-require 'models/author'
require 'models/developer'
-require 'models/project'
-require 'models/comment'
-require 'models/category'
-require 'models/person'
-require 'models/reference'
-
-class RelationScopingTest < ActiveRecord::TestCase
- fixtures :authors, :developers, :projects, :comments, :posts, :developers_projects
-
- def test_reverse_order
- assert_equal Developer.order("id DESC").to_a.reverse, Developer.order("id DESC").reverse_order
- end
-
- def test_reverse_order_with_arel_node
- assert_equal Developer.order("id DESC").to_a.reverse, Developer.order(Developer.arel_table[:id].desc).reverse_order
- end
-
- def test_reverse_order_with_multiple_arel_nodes
- assert_equal Developer.order("id DESC").order("name DESC").to_a.reverse, Developer.order(Developer.arel_table[:id].desc).order(Developer.arel_table[:name].desc).reverse_order
- end
-
- def test_reverse_order_with_arel_nodes_and_strings
- assert_equal Developer.order("id DESC").order("name DESC").to_a.reverse, Developer.order("id DESC").order(Developer.arel_table[:name].desc).reverse_order
- end
-
- def test_double_reverse_order_produces_original_order
- assert_equal Developer.order("name DESC"), Developer.order("name DESC").reverse_order.reverse_order
- end
-
- def test_scoped_find
- Developer.where("name = 'David'").scoping do
- assert_nothing_raised { Developer.find(1) }
- end
- end
-
- def test_scoped_find_first
- developer = Developer.find(10)
- Developer.where("salary = 100000").scoping do
- assert_equal developer, Developer.order("name").first
- end
- end
-
- def test_scoped_find_last
- highest_salary = Developer.order("salary DESC").first
-
- Developer.order("salary").scoping do
- assert_equal highest_salary, Developer.last
- end
- end
-
- def test_scoped_find_last_preserves_scope
- lowest_salary = Developer.order("salary ASC").first
- highest_salary = Developer.order("salary DESC").first
-
- Developer.order("salary").scoping do
- assert_equal highest_salary, Developer.last
- assert_equal lowest_salary, Developer.first
- end
- end
-
- def test_scoped_find_combines_and_sanitizes_conditions
- Developer.where("salary = 9000").scoping do
- assert_equal developers(:poor_jamis), Developer.where("name = 'Jamis'").first
- end
- end
-
- def test_scoped_find_all
- Developer.where("name = 'David'").scoping do
- assert_equal [developers(:david)], Developer.all
- end
- end
-
- def test_scoped_find_select
- Developer.select("id, name").scoping do
- developer = Developer.where("name = 'David'").first
- assert_equal "David", developer.name
- assert !developer.has_attribute?(:salary)
- end
- end
-
- def test_scope_select_concatenates
- Developer.select("id, name").scoping do
- developer = Developer.select('salary').where("name = 'David'").first
- assert_equal 80000, developer.salary
- assert developer.has_attribute?(:id)
- assert developer.has_attribute?(:name)
- assert developer.has_attribute?(:salary)
- end
- end
-
- def test_scoped_count
- Developer.where("name = 'David'").scoping do
- assert_equal 1, Developer.count
- end
-
- Developer.where('salary = 100000').scoping do
- assert_equal 8, Developer.count
- assert_equal 1, Developer.where("name LIKE 'fixture_1%'").count
- end
- end
-
- def test_scoped_find_include
- # with the include, will retrieve only developers for the given project
- scoped_developers = Developer.includes(:projects).scoping do
- Developer.where('projects.id' => 2).to_a
- end
- assert scoped_developers.include?(developers(:david))
- assert !scoped_developers.include?(developers(:jamis))
- assert_equal 1, scoped_developers.size
- end
-
- def test_scoped_find_joins
- scoped_developers = Developer.joins('JOIN developers_projects ON id = developer_id').scoping do
- Developer.where('developers_projects.project_id = 2').to_a
- end
-
- assert scoped_developers.include?(developers(:david))
- assert !scoped_developers.include?(developers(:jamis))
- assert_equal 1, scoped_developers.size
- assert_equal developers(:david).attributes, scoped_developers.first.attributes
- end
-
- def test_scoped_create_with_where
- new_comment = VerySpecialComment.where(:post_id => 1).scoping do
- VerySpecialComment.create :body => "Wonderful world"
- end
-
- assert_equal 1, new_comment.post_id
- assert Post.find(1).comments.include?(new_comment)
- end
-
- def test_scoped_create_with_create_with
- new_comment = VerySpecialComment.create_with(:post_id => 1).scoping do
- VerySpecialComment.create :body => "Wonderful world"
- end
-
- assert_equal 1, new_comment.post_id
- assert Post.find(1).comments.include?(new_comment)
- end
-
- def test_scoped_create_with_create_with_has_higher_priority
- new_comment = VerySpecialComment.where(:post_id => 2).create_with(:post_id => 1).scoping do
- VerySpecialComment.create :body => "Wonderful world"
- end
-
- assert_equal 1, new_comment.post_id
- assert Post.find(1).comments.include?(new_comment)
- end
-
- def test_ensure_that_method_scoping_is_correctly_restored
- begin
- Developer.where("name = 'Jamis'").scoping do
- raise "an exception"
- end
- rescue
- end
-
- assert !Developer.all.where_values.include?("name = 'Jamis'")
- end
-
- def test_default_scope_filters_on_joins
- assert_equal 1, DeveloperFilteredOnJoins.all.count
- assert_equal DeveloperFilteredOnJoins.all.first, developers(:david).becomes(DeveloperFilteredOnJoins)
- end
-
- def test_update_all_default_scope_filters_on_joins
- DeveloperFilteredOnJoins.update_all(:salary => 65000)
- assert_equal 65000, Developer.find(developers(:david).id).salary
-
- # has not changed jamis
- assert_not_equal 65000, Developer.find(developers(:jamis).id).salary
- end
-
- def test_delete_all_default_scope_filters_on_joins
- assert_not_equal [], DeveloperFilteredOnJoins.all
-
- DeveloperFilteredOnJoins.delete_all()
-
- assert_equal [], DeveloperFilteredOnJoins.all
- assert_not_equal [], Developer.all
- end
-end
-
-class NestedRelationScopingTest < ActiveRecord::TestCase
- fixtures :authors, :developers, :projects, :comments, :posts
-
- def test_merge_options
- Developer.where('salary = 80000').scoping do
- Developer.limit(10).scoping do
- devs = Developer.all
- assert_match '(salary = 80000)', devs.to_sql
- assert_equal 10, devs.taken
- end
- end
- end
-
- def test_merge_inner_scope_has_priority
- Developer.limit(5).scoping do
- Developer.limit(10).scoping do
- assert_equal 10, Developer.all.size
- end
- end
- end
-
- def test_replace_options
- Developer.where(:name => 'David').scoping do
- Developer.unscoped do
- assert_equal 'Jamis', Developer.where(:name => 'Jamis').first[:name]
- end
-
- assert_equal 'David', Developer.first[:name]
- end
- end
-
- def test_three_level_nested_exclusive_scoped_find
- Developer.where("name = 'Jamis'").scoping do
- assert_equal 'Jamis', Developer.first.name
-
- Developer.unscoped.where("name = 'David'") do
- assert_equal 'David', Developer.first.name
-
- Developer.unscoped.where("name = 'Maiha'") do
- assert_equal nil, Developer.first
- end
-
- # ensure that scoping is restored
- assert_equal 'David', Developer.first.name
- end
-
- # ensure that scoping is restored
- assert_equal 'Jamis', Developer.first.name
- end
- end
-
- def test_nested_scoped_create
- comment = Comment.create_with(:post_id => 1).scoping do
- Comment.create_with(:post_id => 2).scoping do
- Comment.create :body => "Hey guys, nested scopes are broken. Please fix!"
- end
- end
-
- assert_equal 2, comment.post_id
- end
-
- def test_nested_exclusive_scope_for_create
- comment = Comment.create_with(:body => "Hey guys, nested scopes are broken. Please fix!").scoping do
- Comment.unscoped.create_with(:post_id => 1).scoping do
- assert Comment.new.body.blank?
- Comment.create :body => "Hey guys"
- end
- end
-
- assert_equal 1, comment.post_id
- assert_equal 'Hey guys', comment.body
- end
-end
-
-class HasManyScopingTest< ActiveRecord::TestCase
- fixtures :comments, :posts, :people, :references
-
- def setup
- @welcome = Post.find(1)
- end
-
- def test_forwarding_of_static_methods
- assert_equal 'a comment...', Comment.what_are_you
- assert_equal 'a comment...', @welcome.comments.what_are_you
- end
-
- def test_forwarding_to_scoped
- assert_equal 4, Comment.search_by_type('Comment').size
- assert_equal 2, @welcome.comments.search_by_type('Comment').size
- end
-
- def test_nested_scope_finder
- Comment.where('1=0').scoping do
- assert_equal 0, @welcome.comments.count
- assert_equal 'a comment...', @welcome.comments.what_are_you
- end
-
- Comment.where('1=1').scoping do
- assert_equal 2, @welcome.comments.count
- assert_equal 'a comment...', @welcome.comments.what_are_you
- end
- end
-
- def test_should_maintain_default_scope_on_associations
- magician = BadReference.find(1)
- assert_equal [magician], people(:michael).bad_references
- end
-
- def test_should_default_scope_on_associations_is_overriden_by_association_conditions
- reference = references(:michael_unicyclist).becomes(BadReference)
- assert_equal [reference], people(:michael).fixed_bad_references
- end
-
- def test_should_maintain_default_scope_on_eager_loaded_associations
- michael = Person.where(:id => people(:michael).id).includes(:bad_references).first
- magician = BadReference.find(1)
- assert_equal [magician], michael.bad_references
- end
-end
-
-class HasAndBelongsToManyScopingTest< ActiveRecord::TestCase
- fixtures :posts, :categories, :categories_posts
-
- def setup
- @welcome = Post.find(1)
- end
-
- def test_forwarding_of_static_methods
- assert_equal 'a category...', Category.what_are_you
- assert_equal 'a category...', @welcome.categories.what_are_you
- end
-
- def test_nested_scope_finder
- Category.where('1=0').scoping do
- assert_equal 0, @welcome.categories.count
- assert_equal 'a category...', @welcome.categories.what_are_you
- end
-
- Category.where('1=1').scoping do
- assert_equal 2, @welcome.categories.count
- assert_equal 'a category...', @welcome.categories.what_are_you
- end
- end
-end
class DefaultScopingTest < ActiveRecord::TestCase
fixtures :developers, :posts
diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb
index 1eb3bc4177..3e2e6ab701 100644
--- a/activerecord/test/cases/named_scope_test.rb
+++ b/activerecord/test/cases/scoping/named_scoping_test.rb
@@ -6,7 +6,7 @@ require 'models/reply'
require 'models/author'
require 'models/developer'
-class NamedScopeTest < ActiveRecord::TestCase
+class NamedScopingTest < ActiveRecord::TestCase
fixtures :posts, :authors, :topics, :comments, :author_addresses
def test_implements_enumerable
diff --git a/activerecord/test/cases/scoping/relation_scoping_test.rb b/activerecord/test/cases/scoping/relation_scoping_test.rb
new file mode 100644
index 0000000000..0018fc06f2
--- /dev/null
+++ b/activerecord/test/cases/scoping/relation_scoping_test.rb
@@ -0,0 +1,331 @@
+require "cases/helper"
+require 'models/post'
+require 'models/author'
+require 'models/developer'
+require 'models/project'
+require 'models/comment'
+require 'models/category'
+require 'models/person'
+require 'models/reference'
+
+class RelationScopingTest < ActiveRecord::TestCase
+ fixtures :authors, :developers, :projects, :comments, :posts, :developers_projects
+
+ def test_reverse_order
+ assert_equal Developer.order("id DESC").to_a.reverse, Developer.order("id DESC").reverse_order
+ end
+
+ def test_reverse_order_with_arel_node
+ assert_equal Developer.order("id DESC").to_a.reverse, Developer.order(Developer.arel_table[:id].desc).reverse_order
+ end
+
+ def test_reverse_order_with_multiple_arel_nodes
+ assert_equal Developer.order("id DESC").order("name DESC").to_a.reverse, Developer.order(Developer.arel_table[:id].desc).order(Developer.arel_table[:name].desc).reverse_order
+ end
+
+ def test_reverse_order_with_arel_nodes_and_strings
+ assert_equal Developer.order("id DESC").order("name DESC").to_a.reverse, Developer.order("id DESC").order(Developer.arel_table[:name].desc).reverse_order
+ end
+
+ def test_double_reverse_order_produces_original_order
+ assert_equal Developer.order("name DESC"), Developer.order("name DESC").reverse_order.reverse_order
+ end
+
+ def test_scoped_find
+ Developer.where("name = 'David'").scoping do
+ assert_nothing_raised { Developer.find(1) }
+ end
+ end
+
+ def test_scoped_find_first
+ developer = Developer.find(10)
+ Developer.where("salary = 100000").scoping do
+ assert_equal developer, Developer.order("name").first
+ end
+ end
+
+ def test_scoped_find_last
+ highest_salary = Developer.order("salary DESC").first
+
+ Developer.order("salary").scoping do
+ assert_equal highest_salary, Developer.last
+ end
+ end
+
+ def test_scoped_find_last_preserves_scope
+ lowest_salary = Developer.order("salary ASC").first
+ highest_salary = Developer.order("salary DESC").first
+
+ Developer.order("salary").scoping do
+ assert_equal highest_salary, Developer.last
+ assert_equal lowest_salary, Developer.first
+ end
+ end
+
+ def test_scoped_find_combines_and_sanitizes_conditions
+ Developer.where("salary = 9000").scoping do
+ assert_equal developers(:poor_jamis), Developer.where("name = 'Jamis'").first
+ end
+ end
+
+ def test_scoped_find_all
+ Developer.where("name = 'David'").scoping do
+ assert_equal [developers(:david)], Developer.all
+ end
+ end
+
+ def test_scoped_find_select
+ Developer.select("id, name").scoping do
+ developer = Developer.where("name = 'David'").first
+ assert_equal "David", developer.name
+ assert !developer.has_attribute?(:salary)
+ end
+ end
+
+ def test_scope_select_concatenates
+ Developer.select("id, name").scoping do
+ developer = Developer.select('salary').where("name = 'David'").first
+ assert_equal 80000, developer.salary
+ assert developer.has_attribute?(:id)
+ assert developer.has_attribute?(:name)
+ assert developer.has_attribute?(:salary)
+ end
+ end
+
+ def test_scoped_count
+ Developer.where("name = 'David'").scoping do
+ assert_equal 1, Developer.count
+ end
+
+ Developer.where('salary = 100000').scoping do
+ assert_equal 8, Developer.count
+ assert_equal 1, Developer.where("name LIKE 'fixture_1%'").count
+ end
+ end
+
+ def test_scoped_find_include
+ # with the include, will retrieve only developers for the given project
+ scoped_developers = Developer.includes(:projects).scoping do
+ Developer.where('projects.id' => 2).to_a
+ end
+ assert scoped_developers.include?(developers(:david))
+ assert !scoped_developers.include?(developers(:jamis))
+ assert_equal 1, scoped_developers.size
+ end
+
+ def test_scoped_find_joins
+ scoped_developers = Developer.joins('JOIN developers_projects ON id = developer_id').scoping do
+ Developer.where('developers_projects.project_id = 2').to_a
+ end
+
+ assert scoped_developers.include?(developers(:david))
+ assert !scoped_developers.include?(developers(:jamis))
+ assert_equal 1, scoped_developers.size
+ assert_equal developers(:david).attributes, scoped_developers.first.attributes
+ end
+
+ def test_scoped_create_with_where
+ new_comment = VerySpecialComment.where(:post_id => 1).scoping do
+ VerySpecialComment.create :body => "Wonderful world"
+ end
+
+ assert_equal 1, new_comment.post_id
+ assert Post.find(1).comments.include?(new_comment)
+ end
+
+ def test_scoped_create_with_create_with
+ new_comment = VerySpecialComment.create_with(:post_id => 1).scoping do
+ VerySpecialComment.create :body => "Wonderful world"
+ end
+
+ assert_equal 1, new_comment.post_id
+ assert Post.find(1).comments.include?(new_comment)
+ end
+
+ def test_scoped_create_with_create_with_has_higher_priority
+ new_comment = VerySpecialComment.where(:post_id => 2).create_with(:post_id => 1).scoping do
+ VerySpecialComment.create :body => "Wonderful world"
+ end
+
+ assert_equal 1, new_comment.post_id
+ assert Post.find(1).comments.include?(new_comment)
+ end
+
+ def test_ensure_that_method_scoping_is_correctly_restored
+ begin
+ Developer.where("name = 'Jamis'").scoping do
+ raise "an exception"
+ end
+ rescue
+ end
+
+ assert !Developer.all.where_values.include?("name = 'Jamis'")
+ end
+
+ def test_default_scope_filters_on_joins
+ assert_equal 1, DeveloperFilteredOnJoins.all.count
+ assert_equal DeveloperFilteredOnJoins.all.first, developers(:david).becomes(DeveloperFilteredOnJoins)
+ end
+
+ def test_update_all_default_scope_filters_on_joins
+ DeveloperFilteredOnJoins.update_all(:salary => 65000)
+ assert_equal 65000, Developer.find(developers(:david).id).salary
+
+ # has not changed jamis
+ assert_not_equal 65000, Developer.find(developers(:jamis).id).salary
+ end
+
+ def test_delete_all_default_scope_filters_on_joins
+ assert_not_equal [], DeveloperFilteredOnJoins.all
+
+ DeveloperFilteredOnJoins.delete_all()
+
+ assert_equal [], DeveloperFilteredOnJoins.all
+ assert_not_equal [], Developer.all
+ end
+end
+
+class NestedRelationScopingTest < ActiveRecord::TestCase
+ fixtures :authors, :developers, :projects, :comments, :posts
+
+ def test_merge_options
+ Developer.where('salary = 80000').scoping do
+ Developer.limit(10).scoping do
+ devs = Developer.all
+ assert_match '(salary = 80000)', devs.to_sql
+ assert_equal 10, devs.taken
+ end
+ end
+ end
+
+ def test_merge_inner_scope_has_priority
+ Developer.limit(5).scoping do
+ Developer.limit(10).scoping do
+ assert_equal 10, Developer.all.size
+ end
+ end
+ end
+
+ def test_replace_options
+ Developer.where(:name => 'David').scoping do
+ Developer.unscoped do
+ assert_equal 'Jamis', Developer.where(:name => 'Jamis').first[:name]
+ end
+
+ assert_equal 'David', Developer.first[:name]
+ end
+ end
+
+ def test_three_level_nested_exclusive_scoped_find
+ Developer.where("name = 'Jamis'").scoping do
+ assert_equal 'Jamis', Developer.first.name
+
+ Developer.unscoped.where("name = 'David'") do
+ assert_equal 'David', Developer.first.name
+
+ Developer.unscoped.where("name = 'Maiha'") do
+ assert_equal nil, Developer.first
+ end
+
+ # ensure that scoping is restored
+ assert_equal 'David', Developer.first.name
+ end
+
+ # ensure that scoping is restored
+ assert_equal 'Jamis', Developer.first.name
+ end
+ end
+
+ def test_nested_scoped_create
+ comment = Comment.create_with(:post_id => 1).scoping do
+ Comment.create_with(:post_id => 2).scoping do
+ Comment.create :body => "Hey guys, nested scopes are broken. Please fix!"
+ end
+ end
+
+ assert_equal 2, comment.post_id
+ end
+
+ def test_nested_exclusive_scope_for_create
+ comment = Comment.create_with(:body => "Hey guys, nested scopes are broken. Please fix!").scoping do
+ Comment.unscoped.create_with(:post_id => 1).scoping do
+ assert Comment.new.body.blank?
+ Comment.create :body => "Hey guys"
+ end
+ end
+
+ assert_equal 1, comment.post_id
+ assert_equal 'Hey guys', comment.body
+ end
+end
+
+class HasManyScopingTest< ActiveRecord::TestCase
+ fixtures :comments, :posts, :people, :references
+
+ def setup
+ @welcome = Post.find(1)
+ end
+
+ def test_forwarding_of_static_methods
+ assert_equal 'a comment...', Comment.what_are_you
+ assert_equal 'a comment...', @welcome.comments.what_are_you
+ end
+
+ def test_forwarding_to_scoped
+ assert_equal 4, Comment.search_by_type('Comment').size
+ assert_equal 2, @welcome.comments.search_by_type('Comment').size
+ end
+
+ def test_nested_scope_finder
+ Comment.where('1=0').scoping do
+ assert_equal 0, @welcome.comments.count
+ assert_equal 'a comment...', @welcome.comments.what_are_you
+ end
+
+ Comment.where('1=1').scoping do
+ assert_equal 2, @welcome.comments.count
+ assert_equal 'a comment...', @welcome.comments.what_are_you
+ end
+ end
+
+ def test_should_maintain_default_scope_on_associations
+ magician = BadReference.find(1)
+ assert_equal [magician], people(:michael).bad_references
+ end
+
+ def test_should_default_scope_on_associations_is_overridden_by_association_conditions
+ reference = references(:michael_unicyclist).becomes(BadReference)
+ assert_equal [reference], people(:michael).fixed_bad_references
+ end
+
+ def test_should_maintain_default_scope_on_eager_loaded_associations
+ michael = Person.where(:id => people(:michael).id).includes(:bad_references).first
+ magician = BadReference.find(1)
+ assert_equal [magician], michael.bad_references
+ end
+end
+
+class HasAndBelongsToManyScopingTest< ActiveRecord::TestCase
+ fixtures :posts, :categories, :categories_posts
+
+ def setup
+ @welcome = Post.find(1)
+ end
+
+ def test_forwarding_of_static_methods
+ assert_equal 'a category...', Category.what_are_you
+ assert_equal 'a category...', @welcome.categories.what_are_you
+ end
+
+ def test_nested_scope_finder
+ Category.where('1=0').scoping do
+ assert_equal 0, @welcome.categories.count
+ assert_equal 'a category...', @welcome.categories.what_are_you
+ end
+
+ Category.where('1=1').scoping do
+ assert_equal 2, @welcome.categories.count
+ assert_equal 'a category...', @welcome.categories.what_are_you
+ end
+ end
+end
diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb
index f25f72c481..1b1457ab9c 100644
--- a/activerecord/test/schema/mysql2_specific_schema.rb
+++ b/activerecord/test/schema/mysql2_specific_schema.rb
@@ -14,6 +14,16 @@ ActiveRecord::Schema.define do
add_index :binary_fields, :var_binary
+ create_table :key_tests, force: true, :options => 'ENGINE=MyISAM' do |t|
+ t.string :awesome
+ t.string :pizza
+ t.string :snacks
+ end
+
+ add_index :key_tests, :awesome, :type => :fulltext, :name => 'index_key_tests_on_awesome'
+ add_index :key_tests, :pizza, :using => :btree, :name => 'index_key_tests_on_pizza'
+ add_index :key_tests, :snacks, :name => 'index_key_tests_on_snack'
+
ActiveRecord::Base.connection.execute <<-SQL
DROP PROCEDURE IF EXISTS ten;
SQL
diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb
index 5401c12ed5..ecdce1519b 100644
--- a/activerecord/test/schema/mysql_specific_schema.rb
+++ b/activerecord/test/schema/mysql_specific_schema.rb
@@ -14,6 +14,16 @@ ActiveRecord::Schema.define do
add_index :binary_fields, :var_binary
+ create_table :key_tests, force: true, :options => 'ENGINE=MyISAM' do |t|
+ t.string :awesome
+ t.string :pizza
+ t.string :snacks
+ end
+
+ add_index :key_tests, :awesome, :type => :fulltext, :name => 'index_key_tests_on_awesome'
+ add_index :key_tests, :pizza, :using => :btree, :name => 'index_key_tests_on_pizza'
+ add_index :key_tests, :snacks, :name => 'index_key_tests_on_snack'
+
ActiveRecord::Base.connection.execute <<-SQL
DROP PROCEDURE IF EXISTS ten;
SQL
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 8fd4898ad6..8beb58f3fc 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -183,6 +183,7 @@ ActiveRecord::Schema.define do
add_index :companies, [:firm_id, :type, :rating], :name => "company_index"
add_index :companies, [:firm_id, :type], :name => "company_partial_index", :where => "rating > 10"
+ add_index :companies, :name, :name => 'company_name_index', :using => :btree
create_table :vegetables, :force => true do |t|
t.string :name
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 08ec528419..31395d6da2 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -85,7 +85,7 @@
* Improve `String#squish` to handle Unicode whitespace. *Antoine Lyset*
-* Standardise on `to_time` returning an instance of `Time` in the local system timezone
+* Standardize on `to_time` returning an instance of `Time` in the local system timezone
across `String`, `Time`, `Date`, `DateTime` and `ActiveSupport::TimeWithZone`.
*Andrew White*
@@ -151,7 +151,7 @@
* Remove surrogate unicode character encoding from `ActiveSupport::JSON.encode`
The encoding scheme was broken for unicode characters outside the basic multilingual plane;
- since json is assumed to be UTF-8, and we already force the encoding to UTF-8,
+ since JSON is assumed to be UTF-8, and we already force the encoding to UTF-8,
simply pass through the un-encoded characters.
*Brett Carter*
@@ -370,7 +370,7 @@
* An optional block can be passed to `HashWithIndifferentAccess#update` and `#merge`.
The block will be invoked for each duplicated key, and used to resolve the conflict,
- thus replicating the behaviour of the corresponding methods on the `Hash` class.
+ thus replicating the behavior of the corresponding methods on the `Hash` class.
*Leo Cassarani*
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index f2d9df6d13..6c0cae71ed 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -315,7 +315,7 @@ module ActiveSupport
@config = {
:terminator => "false",
:scope => [ :kind ]
- }.merge(config)
+ }.merge!(config)
end
def compile
diff --git a/activesupport/lib/active_support/core_ext/string/indent.rb b/activesupport/lib/active_support/core_ext/string/indent.rb
index afc3032272..ce3a69cf5f 100644
--- a/activesupport/lib/active_support/core_ext/string/indent.rb
+++ b/activesupport/lib/active_support/core_ext/string/indent.rb
@@ -29,7 +29,7 @@ class String
# "foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar"
# "foo".indent(2, "\t") # => "\t\tfoo"
#
- # While +indent_string+ is tipically one space or tab, it may be any string.
+ # While +indent_string+ is typically one space or tab, it may be any string.
#
# The third argument, +indent_empty_lines+, is a flag that says whether
# empty lines should be indented. Default is false.
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
index 306d80b2df..837db05dcc 100644
--- a/activesupport/lib/active_support/hash_with_indifferent_access.rb
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -78,7 +78,7 @@ module ActiveSupport
end
def self.[](*args)
- new.merge(Hash[*args])
+ new.merge!(Hash[*args])
end
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb
index e0ae60e61f..0c9a729ce5 100644
--- a/activesupport/lib/active_support/notifications/instrumenter.rb
+++ b/activesupport/lib/active_support/notifications/instrumenter.rb
@@ -2,7 +2,7 @@ require 'securerandom'
module ActiveSupport
module Notifications
- # Instrumentors are stored in a thread local.
+ # Instrumenters are stored in a thread local.
class Instrumenter
attr_reader :id
diff --git a/activesupport/lib/active_support/testing/constant_lookup.rb b/activesupport/lib/active_support/testing/constant_lookup.rb
index 52bfeb7179..1b2a75c35d 100644
--- a/activesupport/lib/active_support/testing/constant_lookup.rb
+++ b/activesupport/lib/active_support/testing/constant_lookup.rb
@@ -38,6 +38,8 @@ module ActiveSupport
begin
constant = names.join("::").constantize
break(constant) if yield(constant)
+ rescue NoMethodError # subclass of NameError
+ raise
rescue NameError
# Constant wasn't found, move on
ensure
diff --git a/activesupport/test/descendants_tracker_with_autoloading_test.rb b/activesupport/test/descendants_tracker_with_autoloading_test.rb
index ab1be296f8..a2ae066a21 100644
--- a/activesupport/test/descendants_tracker_with_autoloading_test.rb
+++ b/activesupport/test/descendants_tracker_with_autoloading_test.rb
@@ -6,7 +6,7 @@ require 'descendants_tracker_test_cases'
class DescendantsTrackerWithAutoloadingTest < ActiveSupport::TestCase
include DescendantsTrackerTestCases
- def test_clear_with_autoloaded_parent_children_and_granchildren
+ def test_clear_with_autoloaded_parent_children_and_grandchildren
mark_as_autoloaded(*ALL) do
ActiveSupport::DescendantsTracker.clear
ALL.each do |k|
@@ -15,7 +15,7 @@ class DescendantsTrackerWithAutoloadingTest < ActiveSupport::TestCase
end
end
- def test_clear_with_autoloaded_children_and_granchildren
+ def test_clear_with_autoloaded_children_and_grandchildren
mark_as_autoloaded Child1, Grandchild1, Grandchild2 do
ActiveSupport::DescendantsTracker.clear
assert_equal_sets [Child2], Parent.descendants
@@ -23,7 +23,7 @@ class DescendantsTrackerWithAutoloadingTest < ActiveSupport::TestCase
end
end
- def test_clear_with_autoloaded_granchildren
+ def test_clear_with_autoloaded_grandchildren
mark_as_autoloaded Grandchild1, Grandchild2 do
ActiveSupport::DescendantsTracker.clear
assert_equal_sets [Child1, Child2], Parent.descendants
diff --git a/activesupport/test/ordered_options_test.rb b/activesupport/test/ordered_options_test.rb
index f60f9a58e3..fdc745b23b 100644
--- a/activesupport/test/ordered_options_test.rb
+++ b/activesupport/test/ordered_options_test.rb
@@ -7,13 +7,13 @@ class OrderedOptionsTest < ActiveSupport::TestCase
assert_nil a[:not_set]
- a[:allow_concurreny] = true
+ a[:allow_concurrency] = true
assert_equal 1, a.size
- assert a[:allow_concurreny]
+ assert a[:allow_concurrency]
- a[:allow_concurreny] = false
+ a[:allow_concurrency] = false
assert_equal 1, a.size
- assert !a[:allow_concurreny]
+ assert !a[:allow_concurrency]
a["else_where"] = 56
assert_equal 2, a.size
@@ -23,10 +23,10 @@ class OrderedOptionsTest < ActiveSupport::TestCase
def test_looping
a = ActiveSupport::OrderedOptions.new
- a[:allow_concurreny] = true
+ a[:allow_concurrency] = true
a["else_where"] = 56
- test = [[:allow_concurreny, true], [:else_where, 56]]
+ test = [[:allow_concurrency, true], [:else_where, 56]]
a.each_with_index do |(key, value), index|
assert_equal test[index].first, key
@@ -39,13 +39,13 @@ class OrderedOptionsTest < ActiveSupport::TestCase
assert_nil a.not_set
- a.allow_concurreny = true
+ a.allow_concurrency = true
assert_equal 1, a.size
- assert a.allow_concurreny
+ assert a.allow_concurrency
- a.allow_concurreny = false
+ a.allow_concurrency = false
assert_equal 1, a.size
- assert !a.allow_concurreny
+ assert !a.allow_concurrency
a.else_where = 56
assert_equal 2, a.size
diff --git a/activesupport/test/testing/constant_lookup_test.rb b/activesupport/test/testing/constant_lookup_test.rb
index 19280ba74a..aca2951450 100644
--- a/activesupport/test/testing/constant_lookup_test.rb
+++ b/activesupport/test/testing/constant_lookup_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'dependencies_test_helpers'
class Foo; end
class Bar < Foo
@@ -10,6 +11,7 @@ module FooBar; end
class ConstantLookupTest < ActiveSupport::TestCase
include ActiveSupport::Testing::ConstantLookup
+ include DependenciesTestHelpers
def find_foo(name)
self.class.determine_constant_from_test_name(name) do |constant|
@@ -56,4 +58,12 @@ class ConstantLookupTest < ActiveSupport::TestCase
assert_nil find_module("DoesntExist::Nadda::Nope")
assert_nil find_module("DoesntExist::Nadda::Nope::NotHere")
end
+
+ def test_does_not_swallow_exception_on_no_method_error
+ assert_raises(NoMethodError) {
+ with_autoloading_fixtures {
+ self.class.determine_constant_from_test_name("RaisesNoMethodError")
+ }
+ }
+ end
end
diff --git a/guides/code/getting_started/Gemfile b/guides/code/getting_started/Gemfile
index dca00b43cd..f06fc65de6 100644
--- a/guides/code/getting_started/Gemfile
+++ b/guides/code/getting_started/Gemfile
@@ -4,24 +4,28 @@ gem 'rails', '4.0.0'
gem 'sqlite3'
-# Gems used only for assets and not required
-# in production environments by default.
-group :assets do
- gem 'sprockets-rails'
- gem 'sass-rails'
- gem 'coffee-rails'
+# Use SCSS for stylesheets
+gem 'sass-rails'
- # See https://github.com/sstephenson/execjs#readme for more supported runtimes
- # gem 'therubyracer', platforms: :ruby
+# Use CoffeeScript for .js.coffee assets and views
+gem 'coffee-rails'
- gem 'uglifier', '>= 1.0.3'
-end
+# See https://github.com/sstephenson/execjs#readme for more supported runtimes
+# gem 'therubyracer', platforms: :ruby
+
+# Use Uglifier as compressor for JavaScript assets
+gem 'uglifier', '>= 1.0.3'
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
+group :doc do
+ # bundle exec rake doc:rails generates the API under doc/api.
+ gem 'sdoc', require: false
+end
+
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 1.2'
diff --git a/guides/code/getting_started/config/application.rb b/guides/code/getting_started/config/application.rb
index 526a782b5c..3d7604b659 100644
--- a/guides/code/getting_started/config/application.rb
+++ b/guides/code/getting_started/config/application.rb
@@ -2,8 +2,9 @@ require File.expand_path('../boot', __FILE__)
require 'rails/all'
-# Assets should be precompiled for production (so we don't need the gems loaded then)
-Bundler.require(*Rails.groups(assets: %w(development test)))
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(:default, Rails.env)
module Blog
class Application < Rails::Application
diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md
index e01d0d57ea..5e99063da8 100644
--- a/guides/source/action_controller_overview.md
+++ b/guides/source/action_controller_overview.md
@@ -39,7 +39,7 @@ class ClientsController < ApplicationController
end
```
-As an example, if a user goes to `/clients/new` in your application to add a new client, Rails will create an instance of `ClientsController` and run the `new` method. Note that the empty method from the example above could work just fine because Rails will by default render the `new.html.erb` view unless the action says otherwise. The `new` method could make available to the view a `@client` instance variable by creating a new `Client`:
+As an example, if a user goes to `/clients/new` in your application to add a new client, Rails will create an instance of `ClientsController` and run the `new` method. Note that the empty method from the example above would work just fine because Rails will by default render the `new.html.erb` view unless the action says otherwise. The `new` method could make available to the view a `@client` instance variable by creating a new `Client`:
```ruby
def new
@@ -113,21 +113,21 @@ To send a hash you include the key name inside the brackets:
</form>
```
-When this form is submitted, the value of `params[:client]` will be `{"name" => "Acme", "phone" => "12345", "address" => {"postcode" => "12345", "city" => "Carrot City"}}`. Note the nested hash in `params[:client][:address]`.
+When this form is submitted, the value of `params[:client]` will be `{ "name" => "Acme", "phone" => "12345", "address" => { "postcode" => "12345", "city" => "Carrot City" } }`. Note the nested hash in `params[:client][:address]`.
-Note that the `params` hash is actually an instance of `ActiveSupport::HashWithIndifferentAccess`, which acts like a hash that lets you use symbols and strings interchangeably as keys.
+Note that the `params` hash is actually an instance of `ActiveSupport::HashWithIndifferentAccess`, which acts like a hash but lets you use symbols and strings interchangeably as keys.
### JSON parameters
-If you're writing a web service application, you might find yourself more comfortable on accepting parameters in JSON format. Rails will automatically convert your parameters into `params` hash, which you'll be able to access like you would normally do with form data.
+If you're writing a web service application, you might find yourself more comfortable accepting parameters in JSON format. Rails will automatically convert your parameters into the `params` hash, which you can access as you would normally.
-So for example, if you are sending this JSON parameter:
+So for example, if you are sending this JSON content:
```json
{ "company": { "name": "acme", "address": "123 Carrot Street" } }
```
-You'll get `params[:company]` as `{ :name => "acme", "address" => "123 Carrot Street" }`.
+You'll get `params[:company]` as `{ "name" => "acme", "address" => "123 Carrot Street" }`.
Also, if you've turned on `config.wrap_parameters` in your initializer or calling `wrap_parameters` in your controller, you can safely omit the root element in the JSON parameter. The parameters will be cloned and wrapped in the key according to your controller's name by default. So the above parameter can be written as:
@@ -138,19 +138,19 @@ Also, if you've turned on `config.wrap_parameters` in your initializer or callin
And assume that you're sending the data to `CompaniesController`, it would then be wrapped in `:company` key like this:
```ruby
-{ :name => "acme", :address => "123 Carrot Street", :company => { :name => "acme", :address => "123 Carrot Street" }}
+{ :name => "acme", :address => "123 Carrot Street", :company => { :name => "acme", :address => "123 Carrot Street" } }
```
You can customize the name of the key or specific parameters you want to wrap by consulting the [API documentation](http://api.rubyonrails.org/classes/ActionController/ParamsWrapper.html)
-NOTE: A support for parsing XML parameters has been extracted into a gem named `actionpack-xml_parser`
+NOTE: Support for parsing XML parameters has been extracted into a gem named `actionpack-xml_parser`
### Routing Parameters
The `params` hash will always contain the `:controller` and `:action` keys, but you should use the methods `controller_name` and `action_name` instead to access these values. Any other parameters defined by the routing, such as `:id` will also be available. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the `:status` parameter in a "pretty" URL:
```ruby
-match '/clients/:status' => 'clients#index', foo: "bar"
+match '/clients/:status' => 'clients#index', foo: 'bar'
```
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".
@@ -173,7 +173,7 @@ If you define `default_url_options` in `ApplicationController`, as in the exampl
### Strong Parameters
-With strong parameters Action Controller parameters are forbidden to
+With strong parameters, Action Controller parameters are forbidden to
be used in Active Model mass assignments until they have been
whitelisted. This means you'll have to make a conscious choice about
which attributes to allow for mass updating and thus prevent
@@ -232,15 +232,15 @@ The permitted scalar types are `String`, `Symbol`, `NilClass`,
`StringIO`, `IO`, `ActionDispatch::Http::UploadedFile` and
`Rack::Test::UploadedFile`.
-To declare that the value in `params+ must be an array of permitted
+To declare that the value in `params` must be an array of permitted
scalar values map the key to an empty array:
```ruby
params.permit(:id => [])
```
-To whitelist an entire hash of parameters, the `permit!+ method can be
-used
+To whitelist an entire hash of parameters, the `permit!` method can be
+used:
```ruby
params.require(:log_entry).permit!
@@ -273,7 +273,7 @@ to having a `name` (any permitted scalar values allowed, too).
You want to also use the permitted attributes in the `new`
action. This raises the problem that you can't use `require` on the
-root-key because normally it does not exist when calling `new`:
+root key because normally it does not exist when calling `new`:
```ruby
# using `fetch` you can supply a default and use
@@ -281,7 +281,7 @@ root-key because normally it does not exist when calling `new`:
params.fetch(:blog, {}).permit(:title, :author)
```
-`accepts_nested_attributes_for` allows you update and destroy the
+`accepts_nested_attributes_for` allows you to update and destroy
associated records. This is based on the `id` and `_destroy`
parameters:
@@ -291,7 +291,7 @@ params.require(:author).permit(:name, books_attributes: [:title, :id, :_destroy]
```
Hashes with integer keys are treated differently and you can declare
-the attributes as if they were direct children. You get this kind of
+the attributes as if they were direct children. You get these kinds of
parameters when you use `accepts_nested_attributes_for` in combination
with a `has_many` association:
@@ -311,7 +311,7 @@ in mind. It is not meant as a silver bullet to handle all your
whitelisting problems. However you can easily mix the API with your
own code to adapt to your situation.
-Imagine a situation where you want to whitelist an attribute
+Imagine a scenario where you want to whitelist an attribute
containing a hash with any keys. Using strong parameters you can't
allow a hash with any keys but you can use a simple assignment to get
the job done:
diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md
index 4cdac43a7e..3b5963efc2 100644
--- a/guides/source/action_view_overview.md
+++ b/guides/source/action_view_overview.md
@@ -492,7 +492,7 @@ image_path("edit.png") # => /assets/edit-2d1a2db63fc738690021fedb5a65b68e.png
#### image_url
-Computes the url to an image asset in the `app/asset/images` directory. This will call `image_path` internally and merge with your current host or your asset host.
+Computes the url to an image asset in the `app/assets/images` directory. This will call `image_path` internally and merge with your current host or your asset host.
```ruby
image_url("edit.png") # => http://www.example.com/assets/edit.png
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 7355f6816c..2589accadd 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -506,19 +506,15 @@ This code will generate SQL like this:
SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
```
-### NOT, LIKE, and NOT LIKE Conditions
+### NOT Conditions
-`NOT`, `LIKE`, and `NOT LIKE` SQL queries can be built by `where.not`, `where.like`, and `where.not_like` respectively.
+`NOT` SQL queries can be built by `where.not`.
```ruby
Post.where.not(author: author)
-
-Author.where.like(name: 'Nari%')
-
-Developer.where.not_like(name: 'Tenderl%')
```
-In other words, these sort of queries can be generated by calling `where` with no argument, then immediately chain with `not`, `like`, or `not_like` passing `where` conditions.
+In other words, this query can be generated by calling `where` with no argument, then immediately chain with `not` passing `where` conditions.
Ordering
--------
@@ -971,7 +967,7 @@ SELECT categories.* FROM categories
INNER JOIN posts ON posts.category_id = categories.id
```
-Or, in English: "return a Category object for all categories with posts". Note that you will see duplicate categories if more than one post has the same category. If you want unique categories, you can use `Category.joins(:posts).select("distinct(categories.id)")`.
+Or, in English: "return a Category object for all categories with posts". Note that you will see duplicate categories if more than one post has the same category. If you want unique categories, you can use `Category.joins(:posts).uniq`.
#### Joining Multiple Associations
@@ -1298,7 +1294,7 @@ recommended that you use the block form of `unscoped`:
```ruby
Client.unscoped {
- Client.created_before(Time.zome.now)
+ Client.created_before(Time.zone.now)
}
```
diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md
index 32641d04c1..df39d3c5dc 100644
--- a/guides/source/active_record_validations.md
+++ b/guides/source/active_record_validations.md
@@ -530,6 +530,47 @@ field you should use `validates :field_name, inclusion: { in: [true, false] }`.
The default error message is _"can't be empty"_.
+### `absence`
+
+This helper validates that the specified attributes are absent. It uses the
+`present?` method to check if the value is not either nil or a blank string, that
+is, a string that is either empty or consists of whitespace.
+
+```ruby
+class Person < ActiveRecord::Base
+ validates :name, :login, :email, absence: true
+end
+```
+
+If you want to be sure that an association is absent, you'll need to test
+whether the associated object itself is absent, and not the foreign key used
+to map the association.
+
+```ruby
+class LineItem < ActiveRecord::Base
+ belongs_to :order
+ validates :order, absence: true
+end
+```
+
+In order to validate associated records whose absence is required, you must
+specify the `:inverse_of` option for the association:
+
+```ruby
+class Order < ActiveRecord::Base
+ has_many :line_items, inverse_of: :order
+end
+```
+
+If you validate the absence of an object associated via a `has_one` or
+`has_many` relationship, it will check that the object is neither `present?` nor
+`marked_for_destruction?`.
+
+Since `false.present?` is false, if you want to validate the absence of a boolean
+field you should use `validates :field_name, exclusion: { in: [true, false] }`.
+
+The default error message is _"must be blank"_.
+
### `uniqueness`
This helper validates that the attribute's value is unique right before the
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 517db0d222..43529e3e96 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -1344,7 +1344,7 @@ The second argument, `indent_string`, specifies which indent string to use. The
"foo".indent(2, "\t") # => "\t\tfoo"
```
-While `indent_string` is tipically one space or tab, it may be any string.
+While `indent_string` is typically one space or tab, it may be any string.
The third argument, `indent_empty_lines`, is a flag that says whether empty lines should be indented. Default is false.
@@ -2198,7 +2198,7 @@ This method accepts three options:
* `:words_connector`: What is used to join the elements of arrays with 3 or more elements, except for the last two. Default is ", ".
* `:last_word_connector`: What is used to join the last items of an array with 3 or more elements. Default is ", and ".
-The defaults for these options can be localised, their keys are:
+The defaults for these options can be localized, their keys are:
| Option | I18n key |
| ---------------------- | ----------------------------------- |
diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md
index d08000eb69..38dbfd3152 100644
--- a/guides/source/active_support_instrumentation.md
+++ b/guides/source/active_support_instrumentation.md
@@ -273,7 +273,7 @@ Action Mailer
to: ["users@rails.com", "ddh@rails.com"],
from: ["me@rails.com"],
date: Sat, 10 Mar 2012 14:18:09 +0100,
- mail: "..." # ommitted for beverity
+ mail: "..." # omitted for brevity
}
```
@@ -299,7 +299,7 @@ Action Mailer
to: ["users@rails.com", "ddh@rails.com"],
from: ["me@rails.com"],
date: Sat, 10 Mar 2012 14:18:09 +0100,
- mail: "..." # ommitted for beverity
+ mail: "..." # omitted for brevity
}
```
@@ -428,7 +428,7 @@ end
```
Defining all those block arguments each time can be tedious. You can easily create an `ActiveSupport::Notifications::Event`
-from block args like this:
+from block arguments like this:
```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
@@ -442,7 +442,7 @@ ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*a
end
```
-Most times you only care about the data itself. Here is a shortuct to just get the data.
+Most times you only care about the data itself. Here is a shortcut to just get the data.
```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
@@ -465,7 +465,7 @@ Creating custom events
Adding your own events is easy as well. `ActiveSupport::Notifications` will take care of
all the heavy lifting for you. Simply call `instrument` with a `name`, `payload` and a block.
The notification will be sent after the block returns. `ActiveSupport` will generate the start and end times
-as well as the unique ID. All data passed into the `insturment` call will make it into the payload.
+as well as the unique ID. All data passed into the `instrument` call will make it into the payload.
Here's an example:
diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md
index e939606c88..448f0e1f9a 100644
--- a/guides/source/asset_pipeline.md
+++ b/guides/source/asset_pipeline.md
@@ -547,7 +547,35 @@ This directive is available if the core module that provides this feature was co
If you're compiling nginx with Phusion Passenger you'll need to pass that option when prompted.
-A robust configuration for Apache is possible but tricky; please Google around. (Or help update this Guide if you have a good example configuration for Apache.)
+Apache is also able to serve the [gzipped](http://en.wikipedia.org/wiki/Gzip) version of your assets; however, it requires a bit more work:
+
+```apache
+<LocationMatch "^/assets/.*$">
+ Header unset ETag
+ FileETag None
+
+ # RFC says only cache for 1 year
+ ExpiresActive On
+ ExpiresDefault "access plus 1 year"
+
+ RewriteEngine On
+ RewriteCond %{HTTP:Accept-Encoding} gzip
+ RewriteCond %{HTTP_USER_AGENT} !Konqueror
+ RewriteCond %{REQUEST_FILENAME}.gz -f
+ RewriteRule ^(.+).(css|js)$ $1.$2.gz [QSA,L]
+</LocationMatch>
+
+<FilesMatch \.css\.gz>
+ ForceType text/css
+</FilesMatch>
+
+<FilesMatch \.js\.gz>
+ ForceType application/javascript
+</FilesMatch>
+AddEncoding gzip .gz
+```
+
+NOTE: You will need to make sure `mod_headers`, `mod_mime` and `mod_rewrite` are loaded; otherwise, the above configuration will fail.
### Local Precompilation
@@ -740,7 +768,7 @@ end
```
Now that you have a `Template` class, it's time to associate it with an
-extenstion for template files:
+extension for template files:
```ruby
Sprockets.register_engine '.bang', BangBang::Template
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index 65c8154064..18d9f5c562 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -572,7 +572,7 @@ end
These need to be backed up by a migration to create the `assemblies_parts` table. This table should be created without a primary key:
```ruby
-class CreateAssemblyPartJoinTable < ActiveRecord::Migration
+class CreateAssembliesPartsJoinTable < ActiveRecord::Migration
def change
create_table :assemblies_parts, id: false do |t|
t.integer :assembly_id
diff --git a/guides/source/command_line.md b/guides/source/command_line.md
index 9d1fb03fab..4711186522 100644
--- a/guides/source/command_line.md
+++ b/guides/source/command_line.md
@@ -82,7 +82,7 @@ The server can be run on a different port using the `-p` option. The default dev
$ rails server -e production -p 4000
```
-The `-b` option binds Rails to the specified ip, by default it is 0.0.0.0. You can run a server as a daemon by passing a `-d` option.
+The `-b` option binds Rails to the specified IP, by default it is 0.0.0.0. You can run a server as a daemon by passing a `-d` option.
### `rails generate`
@@ -414,7 +414,7 @@ app/controllers/admin/users_controller.rb:
* [ 20] [TODO] any other way to do this?
* [132] [FIXME] high priority for next deploy
-app/model/school.rb:
+app/models/school.rb:
* [ 13] [OPTIMIZE] refactor this code to make it faster
* [ 17] [FIXME]
```
@@ -427,7 +427,7 @@ $ rake notes:fixme
app/controllers/admin/users_controller.rb:
* [132] high priority for next deploy
-app/model/school.rb:
+app/models/school.rb:
* [ 17]
```
@@ -436,7 +436,7 @@ You can also use custom annotations in your code and list them using `rake notes
```bash
$ rake notes:custom ANNOTATION=BUG
(in /home/foobar/commandsapp)
-app/model/post.rb:
+app/models/post.rb:
* [ 23] Have to fix this one before pushing!
```
@@ -448,7 +448,7 @@ By default, `rake notes` will look in the `app`, `config`, `lib`, `bin` and `tes
$ export SOURCE_ANNOTATION_DIRECTORIES='rspec,vendor'
$ rake notes
(in /home/foobar/commandsapp)
-app/model/user.rb:
+app/models/user.rb:
* [ 35] [FIXME] User should have a subscription at this point
rspec/model/user_spec.rb:
* [122] [TODO] Verify the user that has a subscription works
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index dbbeec7126..9ea493325d 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -646,7 +646,7 @@ Below is a comprehensive list of all the initializers found in Rails in the orde
* `active_support.initialize_time_zone` Sets the default time zone for the application based on the `config.time_zone` setting, which defaults to "UTC".
-* `active_support.initialize_beginning_of_week` Sets the default beginnig of week for the application based on `config.beginning_of_week` setting, which defaults to `:monday`.
+* `active_support.initialize_beginning_of_week` Sets the default beginning of week for the application based on `config.beginning_of_week` setting, which defaults to `:monday`.
* `action_dispatch.configure` Configures the `ActionDispatch::Http::URL.tld_length` to be set to the value of `config.action_dispatch.tld_length`.
@@ -698,7 +698,7 @@ Below is a comprehensive list of all the initializers found in Rails in the orde
* `engines_blank_point` Provides a point-in-initialization to hook into if you wish to do anything before engines are loaded. After this point, all railtie and engine initializers are run.
-* `add_generator_templates` Finds templates for generators at `lib/templates` for the application, railities and engines and adds these to the `config.generators.templates` setting, which will make the templates available for all generators to reference.
+* `add_generator_templates` Finds templates for generators at `lib/templates` for the application, railties and engines and adds these to the `config.generators.templates` setting, which will make the templates available for all generators to reference.
* `ensure_autoload_once_paths_as_subset` Ensures that the `config.autoload_once_paths` only contains paths from `config.autoload_paths`. If it contains extra paths, then an exception will be raised.
diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index cc4e369e7d..b6363bdfb1 100644
--- a/guides/source/contributing_to_ruby_on_rails.md
+++ b/guides/source/contributing_to_ruby_on_rails.md
@@ -53,6 +53,22 @@ The easiest and recommended way to get a development environment ready to hack i
In case you can't use the Rails development box, see section above, check [this other guide](development_dependencies_install.html).
+
+Running an Application Against Your Local Branch
+------------------------------------------------
+
+The `--dev` flag of `rails new` generates an application that uses your local
+branch:
+
+```bash
+$ cd rails
+$ bundle exec rails new ~/my-test-app --dev
+```
+
+The application generated in `~/my-test-app` runs against your local branch
+and in particular sees any modifications upon server reboot.
+
+
Testing Active Record
---------------------
@@ -190,7 +206,7 @@ $ cd rails
$ git checkout -b my_new_branch
```
-It doesn’t matter much what name you use, because this branch will only exist on your local computer and your personal repository on Github. It won't be part of the Rails Git repository.
+It doesn’t matter much what name you use, because this branch will only exist on your local computer and your personal repository on GitHub. It won't be part of the Rails Git repository.
### Write Your Code
@@ -201,6 +217,17 @@ Now get busy and add or edit code. You’re on your branch now, so you can write
* Include tests that fail without your code, and pass with it.
* Update the (surrounding) documentation, examples elsewhere, and the guides: whatever is affected by your contribution.
+It is not customary in Rails to run the full test suite before pushing
+changes. The railties test suite in particular takes a long time, and even
+more if the source code is mounted in `/vagrant` as happens in the recommended
+workflow with the [rails-dev-box](https://github.com/rails/rails-dev-box).
+
+As a compromise, test what your code obviously affects, and if the change is
+not in railties run the whole test suite of the affected component. If all is
+green that's enough to propose your contribution. We have [Travis CI](https
+://travis-ci.org/) as a safety net for catching unexpected breakages
+elsewhere.
+
TIP: Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of Rails will generally not be accepted.
### Follow the Coding Conventions
@@ -225,7 +252,7 @@ The above are guidelines — please use your best judgment in using them.
The CHANGELOG is an important part of every release. It keeps the list of changes for every Rails version.
-You should add an entry to the CHANGELOG of the framework that you modified if you're adding or removing a feature, commiting a bug fix or adding deprecation notices. Refactorings and documentation changes generally should not go to the CHANGELOG.
+You should add an entry to the CHANGELOG of the framework that you modified if you're adding or removing a feature, committing a bug fix or adding deprecation notices. Refactorings and documentation changes generally should not go to the CHANGELOG.
A CHANGELOG entry should summarize what was changed and should end with author's name. You can use multiple lines if you need more space and you can attach code examples indented with 4 spaces. If a change is related to a specific issue, you should attach issue's number. Here is an example CHANGELOG entry:
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index 5531dee343..6699098e51 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -23,7 +23,7 @@ One common task is to inspect the contents of a variable. In Rails, you can do t
### `debug`
-The `debug` helper will return a \<pre>-tag that renders the object using the YAML format. This will generate human-readable data from any object. For example, if you have this code in a view:
+The `debug` helper will return a \<pre> tag that renders the object using the YAML format. This will generate human-readable data from any object. For example, if you have this code in a view:
```html+erb
<%= debug @post %>
@@ -174,7 +174,7 @@ class PostsController < ApplicationController
end
```
-Here's an example of the log generated by this method:
+Here's an example of the log generated when this controller action is executed:
```
Processing PostsController#create (for 127.0.0.1 at 2008-09-08 11:52:54) [POST]
@@ -194,11 +194,11 @@ Redirected to #<Post:0x20af760>
Completed in 0.01224 (81 reqs/sec) | DB: 0.00044 (3%) | 302 Found [http://localhost/posts]
```
-Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels, to avoid filling your production logs with useless trivia.
+Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels to avoid filling your production logs with useless trivia.
### Tagged Logging
-When running multi-user, multi-account applications, it’s often useful to be able to filter the logs using some custom rules. `TaggedLogging` in Active Support helps in doing exactly that by stamping log lines with subdomains, request ids, and anything else to aid debugging such applications.
+When running multi-user, multi-account applications, it’s often useful to be able to filter the logs using some custom rules. `TaggedLogging` in ActiveSupport helps in doing exactly that by stamping log lines with subdomains, request ids, and anything else to aid debugging such applications.
```ruby
logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
@@ -216,7 +216,7 @@ The debugger can also help you if you want to learn about the Rails source code
### Setup
-Rails uses the `debugger` gem to set breakpoints and step through live code. To install it, just run:
+You can use the `debugger` gem to set breakpoints and step through live code in Rails. To install it, just run:
```bash
$ gem install debugger
@@ -235,7 +235,7 @@ class PeopleController < ApplicationController
end
```
-If you see the message in the console or logs:
+If you see this message in the console or logs:
```
***** Debugger requested, but was not available: Start server with --debugger to enable *****
@@ -246,12 +246,12 @@ Make sure you have started your web server with the option `--debugger`:
```bash
$ rails server --debugger
=> Booting WEBrick
-=> Rails 3.0.0 application starting on http://0.0.0.0:3000
+=> Rails 3.2.13 application starting on http://0.0.0.0:3000
=> Debugger enabled
...
```
-TIP: In development mode, you can dynamically `require \'debugger\'` instead of restarting the server, if it was started without `--debugger`.
+TIP: In development mode, you can dynamically `require \'debugger\'` instead of restarting the server, even if it was started without `--debugger`.
### The Shell
@@ -266,7 +266,7 @@ For example:
(rdb:7)
```
-Now it's time to explore and dig into your application. A good place to start is by asking the debugger for help... so type: `help` (You didn't see that coming, right?)
+Now it's time to explore and dig into your application. A good place to start is by asking the debugger for help. Type: `help`
```
(rdb:7) help
@@ -281,7 +281,7 @@ condition down finish list ps save thread var
continue edit frame method putl set tmate where
```
-TIP: To view the help menu for any command use `help <command-name>` in active debug mode. For example: _`help var`_
+TIP: To view the help menu for any command use `help <command-name>` at the debugger prompt. For example: _`help var`_
The next command to learn is one of the most useful: `list`. You can abbreviate any debugging command by supplying just enough letters to distinguish them from other commands, so you can also use `l` for the `list` command.
@@ -289,7 +289,7 @@ This command shows you where you are in the code by printing 10 lines centered a
```
(rdb:7) list
-[1, 10] in /PathToProject/posts_controller.rb
+[1, 10] in /PathTo/project/app/controllers/posts_controller.rb
1 class PostsController < ApplicationController
2 # GET /posts
3 # GET /posts.json
@@ -325,7 +325,7 @@ On the other hand, to see the previous ten lines you should type `list-` (or `l-
```
(rdb:7) l-
-[1, 10] in /PathToProject/posts_controller.rb
+[1, 10] in /PathTo/project/app/controllers/posts_controller.rb
1 class PostsController < ApplicationController
2 # GET /posts
3 # GET /posts.json
@@ -343,7 +343,7 @@ Finally, to see where you are in the code again you can type `list=`
```
(rdb:7) list=
-[1, 10] in /PathToProject/posts_controller.rb
+[1, 10] in /PathTo/project/app/controllers/posts_controller.rb
1 class PostsController < ApplicationController
2 # GET /posts
3 # GET /posts.json
@@ -502,7 +502,7 @@ TIP: You can use the debugger while using `rails console`. Just remember to `req
```
$ rails console
-Loading development environment (Rails 3.1.0)
+Loading development environment (Rails 3.2.13)
>> require "debugger"
=> []
>> author = Author.first
diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md
index 817a732051..3f16ebcf1d 100644
--- a/guides/source/form_helpers.md
+++ b/guides/source/form_helpers.md
@@ -423,7 +423,7 @@ Whenever Rails sees that the internal value of an option being generated matches
TIP: The second argument to `options_for_select` must be exactly equal to the desired internal value. In particular if the value is the integer 2 you cannot pass "2" to `options_for_select` — you must pass 2. Be aware of values extracted from the `params` hash as they are all strings.
-WARNING: when `:inlude_blank` or `:prompt:` are not present, `:include_blank` is forced true if the select attribute `required` is true, display `size` is one and `multiple` is not true.
+WARNING: when `:include_blank` or `:prompt` are not present, `:include_blank` is forced true if the select attribute `required` is true, display `size` is one and `multiple` is not true.
You can add arbitrary attributes to the options using hashes:
diff --git a/guides/source/generators.md b/guides/source/generators.md
index d7c789e2d8..a8a34d0ac4 100644
--- a/guides/source/generators.md
+++ b/guides/source/generators.md
@@ -589,11 +589,11 @@ Creates an initializer in the `config/initializers` directory of the application
initializer "begin.rb", "puts 'this is the beginning'"
```
-This method also takes a block:
+This method also takes a block, expected to return a string:
```ruby
initializer "begin.rb" do
- puts "Almost done!"
+ "puts 'this is the beginning'"
end
```
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index cd23b5ee15..3881bb1195 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -1761,7 +1761,7 @@ cannot be automatically detected by Rails and corrected.
Two very common sources of data that are not UTF-8:
-* Your text editor: Most text editors (such as Textmate), default to saving files as
+* Your text editor: Most text editors (such as TextMate), default to saving files as
UTF-8. If your text editor does not, this can result in special characters that you
enter in your templates (such as é) to appear as a diamond with a question mark inside
in the browser. This also applies to your i18n translation files.
diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md
index bfd1a7c61b..a3b3472701 100644
--- a/guides/source/layouts_and_rendering.md
+++ b/guides/source/layouts_and_rendering.md
@@ -363,7 +363,7 @@ You can use a symbol to defer the choice of layout until a request is processed:
```ruby
class ProductsController < ApplicationController
- layout "products_layout"
+ layout :products_layout
def show
@product = Product.find(params[:id])
diff --git a/guides/source/migrations.md b/guides/source/migrations.md
index bd63970bea..086cf434d9 100644
--- a/guides/source/migrations.md
+++ b/guides/source/migrations.md
@@ -831,7 +831,7 @@ end
```
```ruby
-# app/model/product.rb
+# app/models/product.rb
class Product < ActiveRecord::Base
validates :flag, presence: true
@@ -856,7 +856,7 @@ end
```
```ruby
-# app/model/product.rb
+# app/models/product.rb
class Product < ActiveRecord::Base
validates :flag, :fuzz, presence: true
diff --git a/guides/source/routing.md b/guides/source/routing.md
index d7a4a237ed..04098f0a5c 100644
--- a/guides/source/routing.md
+++ b/guides/source/routing.md
@@ -530,7 +530,7 @@ In particular, simple routing makes it very easy to map legacy URLs to new Rails
### Bound Parameters
-When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: `:controller` maps to the name of a controller in your application, and `:action` maps to the name of an action within that controller. For example, consider one of the default Rails routes:
+When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: `:controller` maps to the name of a controller in your application, and `:action` maps to the name of an action within that controller. For example, consider this route:
```ruby
get ':controller(/:action(/:id))'
@@ -850,7 +850,7 @@ resources :user_permissions, controller: 'admin/user_permissions'
This will route to the `Admin::UserPermissions` controller.
-NOTE: Only the directory notation is supported. specifying the
+NOTE: Only the directory notation is supported. Specifying the
controller with ruby constant notation (eg. `:controller =>
'Admin::UserPermissions'`) can lead to routing problems and results in
a warning.
diff --git a/guides/source/ruby_on_rails_guides_guidelines.md b/guides/source/ruby_on_rails_guides_guidelines.md
index a78711f4b2..136dfb4cae 100644
--- a/guides/source/ruby_on_rails_guides_guidelines.md
+++ b/guides/source/ruby_on_rails_guides_guidelines.md
@@ -65,7 +65,7 @@ HTML Guides
### Generation
-To generate all the guides, just `cd` into the **`guides`** directory, run `bundle install` and execute:
+To generate all the guides, just `cd` into the `guides` directory, run `bundle install` and execute:
```
bundle exec rake guides:generate
diff --git a/guides/source/security.md b/guides/source/security.md
index 769bd130be..d56ce47b3c 100644
--- a/guides/source/security.md
+++ b/guides/source/security.md
@@ -432,7 +432,7 @@ Depending on your web application, there may be more ways to hijack the user's a
INFO: _A CAPTCHA is a challenge-response test to determine that the response is not generated by a computer. It is often used to protect comment forms from automatic spam bots by asking the user to type the letters of a distorted image. The idea of a negative CAPTCHA is not for a user to prove that he is human, but reveal that a robot is a robot._
-But not only spam robots (bots) are a problem, but also automatic login bots. A popular CAPTCHA API is [reCAPTCHA](http://recaptcha.net/) which displays two distorted images of words from old books. It also adds an angled line, rather than a distorted background and high levels of warping on the text as earlier CAPTCHAs did, because the latter were broken. As a bonus, using reCAPTCHA helps to digitize old books. [ReCAPTCHA](http://ambethia.com/recaptcha/) is also a Rails plug-in with the same name as the API.
+But not only spam robots (bots) are a problem, but also automatic login bots. A popular CAPTCHA API is [reCAPTCHA](http://recaptcha.net/) which displays two distorted images of words from old books. It also adds an angled line, rather than a distorted background and high levels of warping on the text as earlier CAPTCHAs did, because the latter were broken. As a bonus, using reCAPTCHA helps to digitize old books. [ReCAPTCHA](https://github.com/ambethia/recaptcha/) is also a Rails plug-in with the same name as the API.
You will get two keys from the API, a public and a private key, which you have to put into your Rails environment. After that you can use the recaptcha_tags method in the view, and the verify_recaptcha method in the controller. Verify_recaptcha will return false if the validation fails.
The problem with CAPTCHAs is, they are annoying. Additionally, some visually impaired users have found certain kinds of distorted CAPTCHAs difficult to read. The idea of negative CAPTCHAs is not to ask a user to proof that he is human, but reveal that a spam robot is a bot.
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 3b1c159aec..70061dc815 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -128,12 +128,12 @@ When you use `rails generate scaffold`, for a resource among other things it cre
$ rails generate scaffold post title:string body:text
...
create app/models/post.rb
-create test/models/post_test.rb
+create test/unit/post_test.rb
create test/fixtures/posts.yml
...
```
-The default test stub in `test/models/post_test.rb` looks like this:
+The default test stub in `test/unit/post_test.rb` looks like this:
```ruby
require 'test_helper'
@@ -690,9 +690,9 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
get "/login"
assert_response :success
- post_via_redirect "/login", username: users(:avs).username, password: users(:avs).password
+ post_via_redirect "/login", username: users(:david).username, password: users(:david).password
assert_equal '/welcome', path
- assert_equal 'Welcome avs!', flash[:notice]
+ assert_equal 'Welcome david!', flash[:notice]
https!(false)
get "/posts/all"
@@ -715,12 +715,12 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
test "login and browse site" do
# User avs logs in
- avs = login(:avs)
+ avs = login(:david)
# User guest logs in
guest = login(:guest)
# Both are now available in different sessions
- assert_equal 'Welcome avs!', avs.flash[:notice]
+ assert_equal 'Welcome david!', avs.flash[:notice]
assert_equal 'Welcome guest!', guest.flash[:notice]
# User avs can browse site
@@ -997,5 +997,6 @@ The built-in `test/unit` based testing is not the only way to test Rails applica
* [NullDB](http://avdi.org/projects/nulldb/), a way to speed up testing by avoiding database use.
* [Factory Girl](https://github.com/thoughtbot/factory_girl/tree/master), a replacement for fixtures.
* [Machinist](https://github.com/notahat/machinist/tree/master), another replacement for fixtures.
+* [MiniTest::Spec Rails](https://github.com/metaskills/minitest-spec-rails), use the MiniTest::Spec DSL within your rails tests.
* [Shoulda](http://www.thoughtbot.com/projects/shoulda), an extension to `test/unit` with additional helpers, macros, and assertions.
* [RSpec](http://relishapp.com/rspec), a behavior-driven development framework
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 8ad2e2bdb4..a2ba5dd062 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -31,6 +31,10 @@ If your application is currently on any version of Rails older than 3.2.x, you s
The following changes are meant for upgrading your application to Rails 4.0.
+### Gemfile
+
+Rails 4.0 removed the `assets` group from Gemfile. You'd need to remove that line from your Gemfile when upgrading.
+
### vendor/plugins
Rails 4.0 no longer supports loading plugins from `vendor/plugins`. You must replace any plugins by extracting them to gems and adding them to your Gemfile. If you choose not to make them gems, you can move them into, say, `lib/my_plugin/*` and add an appropriate initializer in `config/initializers/my_plugin.rb`.
@@ -67,7 +71,7 @@ Rails 4.0 extracted Active Resource to its own gem. If you still need the featur
* Rails 4.0 has changed how errors attach with the `ActiveModel::Validations::ConfirmationValidator`. Now when confirmation validations fail, the error will be attached to `:#{attribute}_confirmation` instead of `attribute`.
-* Rails 4.0 has changed `ActiveModel::Serializers::JSON.include_root_in_json` default value to `false`. Now, Active Model Serializers and Active Record objects have the same default behaviour. This means that you can comment or remove the following option in the `config/initializers/wrap_parameters.rb` file:
+* Rails 4.0 has changed `ActiveModel::Serializers::JSON.include_root_in_json` default value to `false`. Now, Active Model Serializers and Active Record objects have the same default behavior. This means that you can comment or remove the following option in the `config/initializers/wrap_parameters.rb` file:
```ruby
# Disable root element in JSON by default.
@@ -311,7 +315,7 @@ config.assets.debug = true
Again, most of the changes below are for the asset pipeline. You can read more about these in the [Asset Pipeline](asset_pipeline.html) guide.
```ruby
-# Compress JavaScripts and CSS
+# Compress JavaScript and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
diff --git a/guides/source/working_with_javascript_in_rails.md b/guides/source/working_with_javascript_in_rails.md
index 7c4192ee26..ddefaf6ff8 100644
--- a/guides/source/working_with_javascript_in_rails.md
+++ b/guides/source/working_with_javascript_in_rails.md
@@ -394,3 +394,4 @@ Here are some helpful links to help you learn even more:
* [jquery-ujs list of external articles](https://github.com/rails/jquery-ujs/wiki/External-articles)
* [Rails 3 Remote Links and Forms: A Definitive Guide](http://www.alfajango.com/blog/rails-3-remote-links-and-forms/)
* [Railscasts: Unobtrusive JavaScript](http://railscasts.com/episodes/205-unobtrusive-javascript)
+* [Railscasts: Turbolinks](http://railscasts.com/episodes/390-turbolinks) \ No newline at end of file
diff --git a/rails.gemspec b/rails.gemspec
index 8a5d042361..a223ea1413 100644
--- a/rails.gemspec
+++ b/rails.gemspec
@@ -16,9 +16,7 @@ Gem::Specification.new do |s|
s.email = 'david@loudthinking.com'
s.homepage = 'http://www.rubyonrails.org'
- s.bindir = 'bin'
- s.executables = []
- s.files = ['README.rdoc'] + Dir['guides/**/*']
+ s.files = ['README.rdoc'] + Dir['guides/**/*']
s.add_dependency 'activesupport', version
s.add_dependency 'actionpack', version
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 2727f1a85d..c9c1048150 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,5 +1,10 @@
## Rails 4.0.0 (unreleased) ##
+* The application rake task `doc:rails` generates now an API like the
+ official one (except for the links to GitHub).
+
+ *Xavier Noria*
+
* Allow vanilla apps to render CoffeeScript templates in production
Vanilla apps already render CoffeeScript templates in development and test
@@ -64,7 +69,9 @@
*Prem Sichanugrist and Chris Toomey*
-* Improve service pages with new layout (404, etc). *Stanislav Sobolev*
+* Improve service pages with new layout (404, etc).
+
+ *Stanislav Sobolev*
## Rails 4.0.0.beta1 (February 25, 2013) ##
@@ -281,17 +288,25 @@
*Derek Prior & Francesco Rodriguez*
-* Fixed support for DATABASE_URL environment variable for rake db tasks. *Grace Liu*
+* Fixed support for `DATABASE_URL` environment variable for rake db tasks.
+
+ *Grace Liu*
-* rails dbconsole now can use SSL for MySQL. The database.yml options sslca, sslcert, sslcapath, sslcipher,
- and sslkey now affect rails dbconsole. *Jim Kingdon and Lars Petrus*
+* `rails dbconsole` now can use SSL for MySQL. The `database.yml` options sslca, sslcert, sslcapath, sslcipher
+ and sslkey now affect `rails dbconsole`.
+
+ *Jim Kingdon and Lars Petrus*
* Correctly handle SCRIPT_NAME when generating routes to engine in application
that's mounted at a sub-uri. With this behavior, you *should not* use
- default_url_options[:script_name] to set proper application's mount point by
- yourself. *Piotr Sarnacki*
+ `default_url_options[:script_name]` to set proper application's mount point by
+ yourself.
+
+ *Piotr Sarnacki*
+
+* `config.threadsafe!` is deprecated in favor of `config.eager_load` which provides a more fine grained control on what is eager loaded .
-* `config.threadsafe!` is deprecated in favor of `config.eager_load` which provides a more fine grained control on what is eager loaded *José Valim*
+ *José Valim*
* The migration generator will now produce AddXXXToYYY/RemoveXXXFromYYY migrations with references statements, for instance
@@ -314,21 +329,35 @@
*Aleksey Magusev*
-* Set `config.active_record.migration_error` to `:page_load` for development *Richard Schneeman*
+* Set `config.active_record.migration_error` to `:page_load` for development.
+
+ *Richard Schneeman*
+
+* Add runner to `Rails::Railtie` as a hook called just after runner starts.
-* Add runner to Rails::Railtie as a hook called just after runner starts. *José Valim & kennyj*
+ *José Valim & kennyj*
-* Add `/rails/info/routes` path, displays same information as `rake routes` *Richard Schneeman & Andrew White*
+* Add `/rails/info/routes` path, displays same information as `rake routes` .
-* Improved `rake routes` output for redirects *Łukasz Strzałkowski & Andrew White*
+ *Richard Schneeman & Andrew White*
-* Load all environments available in `config.paths["config/environments"]`. *Piotr Sarnacki*
+* Improved `rake routes` output for redirects.
-* Remove Rack::SSL in favour of ActionDispatch::SSL. *Rafael Mendonça França*
+ *Łukasz Strzałkowski & Andrew White*
-* Remove Active Resource from Rails framework. *Prem Sichangrist*
+* Load all environments available in `config.paths["config/environments"]`.
-* Allow to set class that will be used to run as a console, other than IRB, with `Rails.application.config.console=`. It's best to add it to `console` block. *Piotr Sarnacki*
+ *Piotr Sarnacki*
+
+* Remove `Rack::SSL` in favour of `ActionDispatch::SSL`.
+
+ *Rafael Mendonça França*
+
+* Remove Active Resource from Rails framework.
+
+ *Prem Sichangrist*
+
+* Allow to set class that will be used to run as a console, other than IRB, with `Rails.application.config.console=`. It's best to add it to `console` block.
Example:
@@ -340,12 +369,20 @@
config.console = Pry
end
+ *Piotr Sarnacki*
+
* Add convenience `hide!` method to Rails generators to hide current generator
- namespace from showing when running `rails generate`. *Carlos Antonio da Silva*
+ namespace from showing when running `rails generate`.
+
+ *Carlos Antonio da Silva*
-* Rails::Plugin has gone. Instead of adding plugins to vendor/plugins use gems or bundler with path or git dependencies. *Santiago Pastorino*
+* Rails::Plugin has gone. Instead of adding plugins to vendor/plugins use gems or bundler with path or git dependencies.
+
+ *Santiago Pastorino*
* Set config.action_mailer.async = true to turn on asynchronous
- message delivery *Brian Cardarella*
+ message delivery.
+
+ *Brian Cardarella*
Please check [3-2-stable](https://github.com/rails/rails/blob/3-2-stable/railties/CHANGELOG.md) for previous changes.
diff --git a/railties/RDOC_MAIN.rdoc b/railties/RDOC_MAIN.rdoc
new file mode 100644
index 0000000000..cadf0fb43e
--- /dev/null
+++ b/railties/RDOC_MAIN.rdoc
@@ -0,0 +1,73 @@
+== Welcome to \Rails
+
+\Rails is a web-application framework that includes everything needed to create
+database-backed web applications according to the {Model-View-Controller (MVC)}[http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller] pattern.
+
+Understanding the MVC pattern is key to understanding \Rails. MVC divides your application
+into three layers, each with a specific responsibility.
+
+The View layer is composed of "templates" that are responsible for providing
+appropriate representations of your application's resources. Templates
+can come in a variety of formats, but most view templates are \HTML with embedded Ruby
+code (.erb files).
+
+The Model layer represents your domain model (such as Account, Product, Person, Post)
+and encapsulates the business logic that is specific to your application. In \Rails,
+database-backed model classes are derived from ActiveRecord::Base. Active Record allows
+you to present the data from database rows as objects and embellish these data objects
+with business logic methods. Although most \Rails models are backed by a database, models
+can also be ordinary Ruby classes, or Ruby classes that implement a set of interfaces as
+provided by the ActiveModel module. You can read more about Active Record in its
+{README}[link:/activerecord/README.rdoc].
+
+The Controller layer is responsible for handling incoming HTTP requests and providing a
+suitable response. Usually this means returning \HTML, but \Rails controllers can also
+generate XML, JSON, PDFs, mobile-specific views, and more. Controllers manipulate models
+and render view templates in order to generate the appropriate HTTP response.
+
+In \Rails, the Controller and View layers are handled together by Action Pack.
+These two layers are bundled in a single package due to their heavy interdependence.
+This is unlike the relationship between Active Record and Action Pack, which are
+independent. Each of these packages can be used independently outside of \Rails. You
+can read more about Action Pack in its {README}[link:/actionpack/README.rdoc].
+
+== Getting Started
+
+1. Install \Rails at the command prompt if you haven't yet:
+
+ gem install rails
+
+2. At the command prompt, create a new \Rails application:
+
+ rails new myapp
+
+ where "myapp" is the application name.
+
+3. Change directory to +myapp+ and start the web server:
+
+ cd myapp; rails server
+
+ Run with <tt>--help</tt> or <tt>-h</tt> for options.
+
+4. Go to http://localhost:3000 and you'll see:
+
+ "Welcome aboard: You're riding Ruby on Rails!"
+
+5. Follow the guidelines to start developing your application. You may find the following resources handy:
+
+* The README file created within your application.
+* {Getting Started with \Rails}[http://guides.rubyonrails.org/getting_started.html].
+* {Ruby on \Rails Tutorial}[http://ruby.railstutorial.org/ruby-on-rails-tutorial-book].
+* {Ruby on \Rails Guides}[http://guides.rubyonrails.org].
+* {The API Documentation}[http://api.rubyonrails.org].
+
+== Contributing
+
+We encourage you to contribute to Ruby on \Rails! Please check out the {Contributing to Rails
+guide}[http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html] for guidelines about how
+to proceed. {Join us}[http://contributors.rubyonrails.org]!
+
+
+== License
+
+Ruby on \Rails is released under the {MIT License}[http://www.opensource.org/licenses/MIT].
diff --git a/railties/lib/rails/api/task.rb b/railties/lib/rails/api/task.rb
new file mode 100644
index 0000000000..1e6458cf93
--- /dev/null
+++ b/railties/lib/rails/api/task.rb
@@ -0,0 +1,157 @@
+require 'rdoc/task'
+
+module Rails
+ module API
+ class Task < RDoc::Task
+ RDOC_FILES = {
+ 'activesupport' => {
+ :include => %w(
+ README.rdoc
+ CHANGELOG.md
+ lib/active_support/**/*.rb
+ ),
+ :exclude => 'lib/active_support/vendor/*'
+ },
+
+ 'activerecord' => {
+ :include => %w(
+ README.rdoc
+ CHANGELOG.md
+ lib/active_record/**/*.rb
+ ),
+ :exclude => 'lib/active_record/vendor/*'
+ },
+
+ 'activemodel' => {
+ :include => %w(
+ README.rdoc
+ CHANGELOG.md
+ lib/active_model/**/*.rb
+ )
+ },
+
+ 'actionpack' => {
+ :include => %w(
+ README.rdoc
+ CHANGELOG.md
+ lib/abstract_controller/**/*.rb
+ lib/action_controller/**/*.rb
+ lib/action_dispatch/**/*.rb
+ lib/action_view/**/*.rb
+ ),
+ :exclude => 'lib/action_controller/vendor/*'
+ },
+
+ 'actionmailer' => {
+ :include => %w(
+ README.rdoc
+ CHANGELOG.md
+ lib/action_mailer/**/*.rb
+ ),
+ :exclude => 'lib/action_mailer/vendor/*'
+ },
+
+ 'railties' => {
+ :include => %w(
+ README.rdoc
+ CHANGELOG.md
+ MIT-LICENSE
+ lib/**/*.rb
+ )
+ }
+ }
+
+ def initialize(name)
+ super
+
+ # Every time rake runs this task is instantiated as all the rest.
+ # Be lazy computing stuff to have as light impact as possible to
+ # the rest of tasks.
+ before_running_rdoc do
+ load_and_configure_sdoc
+ configure_rdoc_files
+ setup_horo_variables
+ end
+ end
+
+ # Hack, ignore the desc calls performed by the original initializer.
+ def desc(description)
+ # no-op
+ end
+
+ def load_and_configure_sdoc
+ require 'sdoc'
+
+ self.title = 'Ruby on Rails API'
+ self.rdoc_dir = api_dir
+
+ options << '-m' << api_main
+ options << '-e' << 'UTF-8'
+
+ options << '-f' << 'sdoc'
+ options << '-T' << 'rails'
+ rescue LoadError
+ $stderr.puts %(Unable to load SDoc, please add\n\n gem 'sdoc', require: false\n\nto the Gemfile.)
+ exit 1
+ end
+
+ def configure_rdoc_files
+ rdoc_files.include(api_main)
+
+ RDOC_FILES.each do |component, cfg|
+ cdr = component_root_dir(component)
+
+ Array(cfg[:include]).each do |pattern|
+ rdoc_files.include("#{cdr}/#{pattern}")
+ end
+
+ Array(cfg[:exclude]).each do |pattern|
+ rdoc_files.exclude("#{cdr}/#{pattern}")
+ end
+ end
+ end
+
+ def setup_horo_variables
+ ENV['HORO_PROJECT_NAME'] = 'Ruby on Rails'
+ ENV['HORO_PROJECT_VERSION'] = rails_version
+ end
+
+ def api_main
+ component_root_dir('railties') + '/RDOC_MAIN.rdoc'
+ end
+ end
+
+ class RepoTask < Task
+ def load_and_configure_sdoc
+ super
+ options << '-g' # link to GitHub, SDoc flag
+ end
+
+ def component_root_dir(component)
+ component
+ end
+
+ def api_dir
+ 'doc/rdoc'
+ end
+
+ def rails_version
+ "master@#{`git rev-parse HEAD`[0, 7]}"
+ end
+ end
+
+ class AppTask < Task
+ def component_root_dir(gem_name)
+ $:.grep(%r{#{gem_name}[\w.-]*/lib\z}).first[0..-5]
+ end
+
+ def api_dir
+ 'doc/api'
+ end
+
+ def rails_version
+ Rails::VERSION::STRING
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 579af8c6a5..93504b3b35 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -107,7 +107,7 @@ module Rails
#
# The <tt>Application</tt> class adds a couple more paths to this set. And as in your
# <tt>Application</tt>, all folders under +app+ are automatically added to the load path.
- # If you have an <tt>app/services/tt> folder for example, it will be added by default.
+ # If you have an <tt>app/services</tt> folder for example, it will be added by default.
#
# == Endpoint
#
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index 63e9b720a4..8b568ff8df 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -179,16 +179,29 @@ module Rails
gemfile = if options.dev? || options.edge?
<<-GEMFILE.gsub(/^ {12}/, '')
- # Gems used for assets
+ # Use edge version of sprockets-rails
gem 'sprockets-rails', github: 'rails/sprockets-rails'
+
+ # Use SCSS for stylesheets
gem 'sass-rails', github: 'rails/sass-rails'
- gem 'uglifier', '>= 1.0.3'
+
+ # To use Uglifier as compressor for JavaScript assets
+ gem 'uglifier', '>= 1.3.0'
GEMFILE
else
<<-GEMFILE.gsub(/^ {12}/, '')
- # Gems used for assets
+ # Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.0.beta1'
- gem 'uglifier', '>= 1.0.3'
+
+ # To use Uglifier as compressor for JavaScript assets
+ gem 'uglifier', '>= 1.3.0'
+ GEMFILE
+ end
+
+ if options[:skip_javascript]
+ gemfile += <<-GEMFILE.gsub(/^ {12}/, '')
+ #{coffee_gemfile_entry}
+ #{javascript_runtime_gemfile_entry}
GEMFILE
end
@@ -196,11 +209,19 @@ module Rails
end
def coffee_gemfile_entry
- if options.dev? || options.edge?
- "gem 'coffee-rails', github: 'rails/coffee-rails'"
+ gemfile = if options.dev? || options.edge?
+ <<-GEMFILE.gsub(/^ {12}/, '')
+ # Use CoffeeScript for .js.coffee assets and views
+ gem 'coffee-rails', github: 'rails/coffee-rails'
+ GEMFILE
else
- "gem 'coffee-rails', '~> 4.0.0.beta1'"
+ <<-GEMFILE.gsub(/^ {12}/, '')
+ # Use CoffeeScript for .js.coffee assets and views
+ gem 'coffee-rails', '~> 4.0.0.beta1'
+ GEMFILE
end
+
+ gemfile.strip_heredoc.gsub(/^[ \t]*$/, '')
end
def javascript_gemfile_entry
@@ -208,9 +229,8 @@ module Rails
unless options[:skip_javascript]
<<-GEMFILE.gsub(/^ {12}/, '').strip_heredoc
- #{javascript_runtime_gemfile_entry}
- # Use CoffeeScript for .js.coffee assets and views
#{coffee_gemfile_entry}
+ #{javascript_runtime_gemfile_entry}
gem '#{options[:javascript]}-rails'#{args[options[:javascript]]}
@@ -220,7 +240,7 @@ module Rails
end
end
- def javascript_runtime_gemfile_entry(n_spaces=0)
+ def javascript_runtime_gemfile_entry
runtime = if defined?(JRUBY_VERSION)
"gem 'therubyrhino'"
else
@@ -228,7 +248,7 @@ module Rails
end
<<-GEMFILE.gsub(/^ {10}/, '')
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
- #{" "*n_spaces}#{runtime}
+ #{runtime}
GEMFILE
end
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile
index f6bd107eba..07cf31dd83 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile
@@ -9,6 +9,11 @@ source 'https://rubygems.org'
<%= assets_gemfile_entry %>
<%= javascript_gemfile_entry -%>
+group :doc do
+ # bundle exec rake doc:rails generates the API under doc/api.
+ gem 'sdoc', require: false
+end
+
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 1.0.1'
diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb
index daf399a538..ceb2bdf371 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb
@@ -11,8 +11,9 @@ require "action_mailer/railtie"
<%= comment_if :skip_test_unit %>require "rails/test_unit/railtie"
<% end -%>
-# Assets should be precompiled for production (so we don't need the gems loaded then)
-Bundler.require(*Rails.groups(assets: %w(development test)))
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(:default, Rails.env)
module <%= app_const_base %>
class Application < Rails::Application
diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake
index 0057b0f887..1c3426028d 100644
--- a/railties/lib/rails/tasks/documentation.rake
+++ b/railties/lib/rails/tasks/documentation.rake
@@ -1,4 +1,5 @@
require 'rdoc/task'
+require 'rails/api/task'
# Monkey-patch to remove redoc'ing and clobber descriptions to cut down on rake -T noise
class RDocTaskWithoutDescriptions < RDoc::Task
@@ -52,52 +53,7 @@ namespace :doc do
Rake::Task['doc:app'].comment = "Generate docs for the app -- also available doc:rails, doc:guides (options: TEMPLATE=/rdoc-template.rb, TITLE=\"Custom Title\")"
# desc 'Generate documentation for the Rails framework.'
- RDocTaskWithoutDescriptions.new("rails") { |rdoc|
- rdoc.rdoc_dir = 'doc/api'
- rdoc.template = "#{ENV['template']}.rb" if ENV['template']
- rdoc.title = "Rails Framework Documentation"
- rdoc.options << '--line-numbers'
-
- gem_path('rails') do |rails|
- rdoc.options << '-m' << "#{rails}/README.rdoc"
- end
-
- gem_path('actionmailer') do |actionmailer|
- %w(README.rdoc CHANGELOG.md MIT-LICENSE lib/action_mailer/base.rb).each do |file|
- rdoc.rdoc_files.include("#{actionmailer}/#{file}")
- end
- end
-
- gem_path('actionpack') do |actionpack|
- %w(README.rdoc CHANGELOG.md MIT-LICENSE lib/action_controller/**/*.rb lib/action_view/**/*.rb).each do |file|
- rdoc.rdoc_files.include("#{actionpack}/#{file}")
- end
- end
-
- gem_path('activemodel') do |activemodel|
- %w(README.rdoc CHANGELOG.md MIT-LICENSE lib/active_model/**/*.rb).each do |file|
- rdoc.rdoc_files.include("#{activemodel}/#{file}")
- end
- end
-
- gem_path('activerecord') do |activerecord|
- %w(README.rdoc CHANGELOG.md lib/active_record/**/*.rb).each do |file|
- rdoc.rdoc_files.include("#{activerecord}/#{file}")
- end
- end
-
- gem_path('activesupport') do |activesupport|
- %w(README.rdoc CHANGELOG.md lib/active_support/**/*.rb).each do |file|
- rdoc.rdoc_files.include("#{activesupport}/#{file}")
- end
- end
-
- gem_path('railties') do |railties|
- %w(README.rdoc CHANGELOG.md lib/{*.rb,commands/*.rb,generators/*.rb}).each do |file|
- rdoc.rdoc_files.include("#{railties}/#{file}")
- end
- end
- }
+ Rails::API::AppTask.new('rails')
# desc "Generate Rails Guides"
task :guides do
diff --git a/railties/railties.gemspec b/railties/railties.gemspec
index a55bf012da..45968052a8 100644
--- a/railties/railties.gemspec
+++ b/railties/railties.gemspec
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
s.email = 'david@loudthinking.com'
s.homepage = 'http://www.rubyonrails.org'
- s.files = Dir['CHANGELOG.md', 'README.rdoc', 'bin/**/*', 'lib/**/{*,.[a-z]*}']
+ s.files = Dir['CHANGELOG.md', 'README.rdoc', 'RDOC_MAIN.rdoc', 'bin/**/*', 'lib/**/{*,.[a-z]*}']
s.require_path = 'lib'
s.bindir = 'bin'
@@ -27,6 +27,5 @@ Gem::Specification.new do |s|
s.add_dependency 'actionpack', version
s.add_dependency 'rake', '>= 0.8.7'
- s.add_dependency 'thor', '>= 0.17.0', '< 2.0'
- s.add_dependency 'rdoc', '~> 3.4'
+ s.add_dependency 'thor', '>= 0.18.1', '< 2.0'
end
diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb
index 80700a1d64..31bc003dcb 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -127,24 +127,23 @@ class FullStackConsoleTest < ActiveSupport::TestCase
end
def spawn_console
- pid = Process.spawn(
+ Process.spawn(
"#{app_path}/bin/rails console --sandbox",
in: @slave, out: @slave, err: @slave
)
assert_output "> ", 30
- pid
end
def test_sandbox
- pid = spawn_console
+ spawn_console
write_prompt "Post.count", "=> 0"
write_prompt "Post.create"
write_prompt "Post.count", "=> 1"
@master.puts "quit"
- pid = spawn_console
+ spawn_console
write_prompt "Post.count", "=> 0"
write_prompt "Post.transaction { Post.create; raise }"
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index b813a7f6bb..51e91656c0 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -303,6 +303,11 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "Gemfile", /# gem 'debugger'/
end
+ def test_inclusion_of_lazy_loaded_sdoc
+ run_generator
+ assert_file 'Gemfile', /gem 'sdoc', require: false/
+ end
+
def test_template_from_dir_pwd
FileUtils.cd(Rails.root)
assert_match(/It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"]))
diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb
index 9953aa929b..361784f509 100644
--- a/railties/test/generators_test.rb
+++ b/railties/test/generators_test.rb
@@ -164,7 +164,7 @@ class GeneratorsTest < Rails::Generators::TestCase
Rails::Generators.invoke "super_shoulda:model", ["Account"]
end
- def test_developer_options_are_overwriten_by_user_options
+ def test_developer_options_are_overwritten_by_user_options
Rails::Generators.options[:with_options] = { generate: false }
self.class.class_eval(<<-end_eval, __FILE__, __LINE__ + 1)
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 26b388b6f9..01fa2c6864 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -187,7 +187,7 @@ module RailtiesTest
assert_equal "Hello bukkits\n", response[2].body
end
- test "adds its views to view paths with lower proriority than app ones" do
+ test "adds its views to view paths with lower priority than app ones" do
@plugin.write "app/controllers/bukkit_controller.rb", <<-RUBY
class BukkitController < ActionController::Base
def index
diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb
index c80b0f63af..0786b8f8c7 100644
--- a/railties/test/railties/railtie_test.rb
+++ b/railties/test/railties/railtie_test.rb
@@ -32,7 +32,7 @@ module RailtiesTest
end
end
- test "railtie_name can be set manualy" do
+ test "railtie_name can be set manually" do
class Foo < Rails::Railtie
railtie_name "bar"
end