aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile.lock2
-rw-r--r--actionpack/CHANGELOG.md6
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb4
-rw-r--r--actionpack/lib/action_dispatch/request/session.rb24
-rw-r--r--actionview/lib/action_view/helpers/form_options_helper.rb21
-rw-r--r--actionview/test/actionpack/controller/render_test.rb20
-rw-r--r--activerecord/lib/active_record/associations.rb19
-rw-r--r--activerecord/lib/active_record/attribute_methods/serialization.rb3
-rw-r--r--activerecord/lib/active_record/enum.rb2
-rw-r--r--activerecord/lib/active_record/fixtures.rb2
-rw-r--r--activerecord/test/cases/serialized_attribute_test.rb8
-rw-r--r--guides/source/active_job_basics.md34
-rw-r--r--guides/source/testing.md7
-rw-r--r--railties/CHANGELOG.md4
-rw-r--r--railties/lib/rails/test_unit/reporter.rb6
-rw-r--r--railties/test/test_unit/reporter_test.rb14
-rw-r--r--tools/test.rb2
17 files changed, 118 insertions, 60 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index 3cc20f1c9c..c6d7ad0926 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -308,4 +308,4 @@ DEPENDENCIES
w3c_validators
BUNDLED WITH
- 1.10.2
+ 1.10.3
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 7b2f150c67..78ae506389 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,9 @@
+* Adds`Rack::Utils::ParameterTypeError` and `Rack::Utils::InvalidParameterError`
+ to the rescue_responses hash in `ExceptionWrapper` (Rack recommends
+ integrators serve 400s for both of these).
+
+ *Grey Baker*
+
* Add support for API only apps.
ActionController::API is added as a replacement of
ActionController::Base for this kind of applications.
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index d176a73633..8c3d45584d 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -17,7 +17,9 @@ module ActionDispatch
'ActionController::InvalidCrossOriginRequest' => :unprocessable_entity,
'ActionDispatch::ParamsParser::ParseError' => :bad_request,
'ActionController::BadRequest' => :bad_request,
- 'ActionController::ParameterMissing' => :bad_request
+ 'ActionController::ParameterMissing' => :bad_request,
+ 'Rack::Utils::ParameterTypeError' => :bad_request,
+ 'Rack::Utils::InvalidParameterError' => :bad_request
)
cattr_accessor :rescue_templates
diff --git a/actionpack/lib/action_dispatch/request/session.rb b/actionpack/lib/action_dispatch/request/session.rb
index 773d41de88..a8a3cd20b9 100644
--- a/actionpack/lib/action_dispatch/request/session.rb
+++ b/actionpack/lib/action_dispatch/request/session.rb
@@ -17,7 +17,7 @@ module ActionDispatch
session.merge! session_was if session_was
set(env, session)
- Options.set(env, Request::Session::Options.new(store, env, default_options))
+ Options.set(env, Request::Session::Options.new(store, default_options))
session
end
@@ -38,20 +38,19 @@ module ActionDispatch
env[ENV_SESSION_OPTIONS_KEY]
end
- def initialize(by, env, default_options)
+ def initialize(by, default_options)
@by = by
- @env = env
@delegate = default_options.dup
end
def [](key)
- if key == :id
- @delegate.fetch(key) {
- @delegate[:id] = @by.send(:extract_session_id, @env)
- }
- else
- @delegate[key]
- end
+ @delegate[key]
+ end
+
+ def id(env)
+ @delegate.fetch(:id) {
+ @by.send(:extract_session_id, env)
+ }
end
def []=(k,v); @delegate[k] = v; end
@@ -68,7 +67,7 @@ module ActionDispatch
end
def id
- options[:id]
+ options.id(@env)
end
def options
@@ -78,8 +77,7 @@ module ActionDispatch
def destroy
clear
options = self.options || {}
- new_sid = @by.send(:destroy_session, @env, options[:id], options)
- options[:id] = new_sid # Reset session id with a new value or nil
+ @by.send(:destroy_session, @env, options.id(@env), options)
# Load the new sid to be written with the response
@loaded = false
diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb
index d3deee0df3..1b7b188d65 100644
--- a/actionview/lib/action_view/helpers/form_options_helper.rb
+++ b/actionview/lib/action_view/helpers/form_options_helper.rb
@@ -707,6 +707,27 @@ module ActionView
# collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
# b.label(:"data-value" => b.value) { b.check_box + b.text }
# end
+ #
+ # ==== Gotcha
+ #
+ # When no selection is made for a collection of checkboxes most
+ # web browsers will not send any value.
+ #
+ # For example, if we have a +User+ model with +category_ids+ field and we
+ # have the following code in our update action:
+ #
+ # @user.update(params[:user])
+ #
+ # If no +category_ids+ are selected then we can safely assume this field
+ # will not be updated.
+ #
+ # This is possible thanks to a hidden field generated by the helper method
+ # for every collection of checkboxes.
+ # This hidden field is given the same field name as the checkboxes with a
+ # blank value.
+ #
+ # In the rare case you don't want this hidden field, you can pass the
+ # <tt>include_hidden: false</tt> option to the helper method.
def collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
Tags::CollectionCheckBoxes.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
end
diff --git a/actionview/test/actionpack/controller/render_test.rb b/actionview/test/actionpack/controller/render_test.rb
index c4228b5683..ebaf39a12d 100644
--- a/actionview/test/actionpack/controller/render_test.rb
+++ b/actionview/test/actionpack/controller/render_test.rb
@@ -1,6 +1,5 @@
require 'abstract_unit'
require 'active_model'
-require 'fileutils'
class ApplicationController < ActionController::Base
self.view_paths = File.join(FIXTURE_LOAD_PATH, "actionpack")
@@ -679,14 +678,6 @@ class RenderTest < ActionController::TestCase
ActionView::Base.logger = nil
end
- def case_sensitive_file_system?
- fname = '.case_sensitive_file_system_test'
- FileUtils.touch(fname)
- !File.exist?(fname.upcase)
- ensure
- FileUtils.rm_f(fname)
- end
-
# :ported:
def test_simple_show
get :hello_world
@@ -753,15 +744,8 @@ class RenderTest < ActionController::TestCase
end
def test_render_action_upcased
- action = :render_action_upcased_hello_world
-
- if case_sensitive_file_system?
- assert_raise ActionView::MissingTemplate do
- get action
- end
- else
- get action
- assert_equal 'Hello world!', @response.body
+ assert_raise ActionView::MissingTemplate do
+ get :render_action_upcased_hello_world
end
end
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 1ca648d48d..82cb3fed59 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -955,20 +955,16 @@ module ActiveRecord
# The +traps+ association on +Dungeon+ and the +dungeon+ association on +Trap+ are
# the inverse of each other and the inverse of the +dungeon+ association on +EvilWizard+
# is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default,
- # Active Record doesn't know anything about these inverse relationships and so no object
- # loading optimization is possible. For example:
+ # Active Record can guess the inverse of the association based on the name
+ # of the class. The result is the following:
#
# d = Dungeon.first
# t = d.traps.first
- # d.level == t.dungeon.level # => true
- # d.level = 10
- # d.level == t.dungeon.level # => false
+ # d.object_id == t.dungeon.object_id # => true
#
# The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to
- # the same object data from the database, but are actually different in-memory copies
- # of that data. Specifying the <tt>:inverse_of</tt> option on associations lets you tell
- # Active Record about inverse relationships and it will optimise object loading. For
- # example, if we changed our model definitions to:
+ # the same in-memory instance since the association matches the name of the class.
+ # The result would be the same if we added +:inverse_of+ to our model definitions:
#
# class Dungeon < ActiveRecord::Base
# has_many :traps, inverse_of: :dungeon
@@ -983,15 +979,14 @@ module ActiveRecord
# belongs_to :dungeon, inverse_of: :evil_wizard
# end
#
- # Then, from our code snippet above, +d+ and <tt>t.dungeon</tt> are actually the same
- # in-memory instance and our final <tt>d.level == t.dungeon.level</tt> will return +true+.
- #
# There are limitations to <tt>:inverse_of</tt> support:
#
# * does not work with <tt>:through</tt> associations.
# * does not work with <tt>:polymorphic</tt> associations.
# * for +belongs_to+ associations +has_many+ inverse associations are ignored.
#
+ # For more information, see the documentation for the +:inverse_of+ option.
+ #
# == Deleting from associations
#
# === Dependent associations
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb
index fd7099e0de..e03bf5945d 100644
--- a/activerecord/lib/active_record/attribute_methods/serialization.rb
+++ b/activerecord/lib/active_record/attribute_methods/serialization.rb
@@ -11,6 +11,9 @@ module ActiveRecord
# serialized object must be of that class on assignment and retrieval.
# Otherwise <tt>SerializationTypeMismatch</tt> will be raised.
#
+ # Empty objects as +{}+, in the case of +Hash+, or +[]+, in the case of
+ # +Array+, will always be persisted as null.
+ #
# Keep in mind that database adapters handle certain serialization tasks
# for you. For instance: +json+ and +jsonb+ types in PostgreSQL will be
# converted between JSON object/array syntax and Ruby +Hash+ or +Array+
diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb
index ad33c84dbc..84b05d9136 100644
--- a/activerecord/lib/active_record/enum.rb
+++ b/activerecord/lib/active_record/enum.rb
@@ -89,7 +89,7 @@ module ActiveRecord
# enum verification: [:done, :fail], enum_prefix: :verification_status
# end
#
- # Note that <tt>:enum_prefix</tt>/<tt>:enum_postfix</tt> are reserved keywords
+ # Note that <tt>:enum_prefix</tt>/<tt>:enum_suffix</tt> are reserved keywords
# and can not be used as an enum name.
module Enum
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 738fab2bd9..b01444a090 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -110,7 +110,7 @@ module ActiveRecord
# <% 1.upto(1000) do |i| %>
# fix_<%= i %>:
# id: <%= i %>
- # name: guy_<%= 1 %>
+ # name: guy_<%= i %>
# <% end %>
#
# This will create 1000 very simple fixtures.
diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb
index a31c3c828c..6056156698 100644
--- a/activerecord/test/cases/serialized_attribute_test.rb
+++ b/activerecord/test/cases/serialized_attribute_test.rb
@@ -287,4 +287,12 @@ class SerializedAttributeTest < ActiveRecord::TestCase
assert_equal [topic, topic2], Topic.where(content: nil)
end
+
+ def test_nil_is_always_persisted_as_null
+ Topic.serialize(:content, Hash)
+
+ topic = Topic.create!(content: { foo: "bar" })
+ topic.update_attribute :content, nil
+ assert_equal [topic], Topic.where(content: nil)
+ end
end
diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md
index 29d0c32b09..22f3c0146a 100644
--- a/guides/source/active_job_basics.md
+++ b/guides/source/active_job_basics.md
@@ -4,7 +4,7 @@ Active Job Basics
=================
This guide provides you with all you need to get started in creating,
-enqueueing and executing background jobs.
+enqueuing and executing background jobs.
After reading this guide, you will know:
@@ -20,7 +20,7 @@ Introduction
------------
Active Job is a framework for declaring jobs and making them run on a variety
-of queueing backends. These jobs can be everything from regularly scheduled
+of queuing backends. These jobs can be everything from regularly scheduled
clean-ups, to billing charges, to mailings. Anything that can be chopped up
into small units of work and run in parallel, really.
@@ -28,11 +28,14 @@ into small units of work and run in parallel, really.
The Purpose of Active Job
-----------------------------
The main point is to ensure that all Rails apps will have a job infrastructure
-in place, even if it's in the form of an "immediate runner". We can then have
-framework features and other gems build on top of that, without having to
-worry about API differences between various job runners such as Delayed Job
-and Resque. Picking your queuing backend becomes more of an operational concern,
-then. And you'll be able to switch between them without having to rewrite your jobs.
+in place. We can then have framework features and other gems build on top of that,
+without having to worry about API differences between various job runners such as
+Delayed Job and Resque. Picking your queuing backend becomes more of an operational
+concern, then. And you'll be able to switch between them without having to rewrite
+your jobs.
+
+NOTE: Rails by default comes with an "immediate runner" queuing implementation.
+That means that each job that has been enqueued will run immediately.
Creating a Job
@@ -78,7 +81,7 @@ end
Enqueue a job like so:
```ruby
-# Enqueue a job to be performed as soon the queueing system is
+# Enqueue a job to be performed as soon the queuing system is
# free.
MyJob.perform_later record
```
@@ -99,17 +102,20 @@ That's it!
Job Execution
-------------
-If no adapter is set, the job is immediately executed.
+For enqueuing and executing jobs you need to set up a queuing backend, that is to
+say you need to decide for a 3rd-party queuing library that Rails should use.
+Rails itself does not provide a sophisticated queuing system and just executes the
+job immediately if no adapter is set.
### Backends
-Active Job has built-in adapters for multiple queueing backends (Sidekiq,
+Active Job has built-in adapters for multiple queuing backends (Sidekiq,
Resque, Delayed Job and others). To get an up-to-date list of the adapters
see the API Documentation for [ActiveJob::QueueAdapters](http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters.html).
### Setting the Backend
-You can easily set your queueing backend:
+You can easily set your queuing backend:
```ruby
# config/application.rb
@@ -123,6 +129,10 @@ module YourApp
end
```
+NOTE: Since jobs run in parallel to your Rails application, most queuing libraries
+require that you start a library-specific queuing service (in addition to
+starting your Rails app) for the job processing to work. For information on
+how to do that refer to the documentation of your respective library.
Queues
------
@@ -212,7 +222,7 @@ end
ProcessVideoJob.perform_later(Video.last)
```
-NOTE: Make sure your queueing backend "listens" on your queue name. For some
+NOTE: Make sure your queuing backend "listens" on your queue name. For some
backends you need to specify the queues to listen to.
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 230e8162f3..2fd54a48fc 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -141,6 +141,13 @@ users(:david).id
email(david.partner.email, david.location_tonight)
```
+To get multiple fixtures at once, you can pass in a list of fixture names. For example:
+
+```ruby
+# this will return an array containing the fixtures david and steve
+users(:david, :steve)
+```
+
### Console Tasks for Running your Tests
Rails comes with a CLI command to run tests.
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 3536929d00..ca07ff349c 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Make it possible to customize the executable inside rerun snippets.
+
+ *Yves Senn*
+
* Add support for API only apps.
Middleware stack was slimmed down and it has only the needed
middleware for API apps & generators generates the right files,
diff --git a/railties/lib/rails/test_unit/reporter.rb b/railties/lib/rails/test_unit/reporter.rb
index bfdc9754d4..faf551f381 100644
--- a/railties/lib/rails/test_unit/reporter.rb
+++ b/railties/lib/rails/test_unit/reporter.rb
@@ -1,7 +1,11 @@
+require "active_support/core_ext/class/attribute"
require "minitest"
module Rails
class TestUnitReporter < Minitest::StatisticsReporter
+ class_attribute :executable
+ self.executable = "bin/rails test"
+
def report
return if results.empty?
io.puts
@@ -15,7 +19,7 @@ module Rails
filtered_results.reject!(&:skipped?) unless options[:verbose]
filtered_results.map do |result|
location, line = result.method(result.name).source_location
- "bin/rails test #{relative_path_for(location)}:#{line}"
+ "#{self.executable} #{relative_path_for(location)}:#{line}"
end.join "\n"
end
diff --git a/railties/test/test_unit/reporter_test.rb b/railties/test/test_unit/reporter_test.rb
index 77883612f5..d619a3e515 100644
--- a/railties/test/test_unit/reporter_test.rb
+++ b/railties/test/test_unit/reporter_test.rb
@@ -43,6 +43,20 @@ class TestUnitReporterTest < ActiveSupport::TestCase
assert_rerun_snippet_count 1
end
+ test "allows to customize the executable in the rerun snippet" do
+ original_executable = Rails::TestUnitReporter.executable
+ begin
+ Rails::TestUnitReporter.executable = "bin/test"
+ verbose = Rails::TestUnitReporter.new @output, verbose: true
+ @reporter.record(failed_test)
+ @reporter.report
+
+ assert_match %r{^bin/test .*test/test_unit/reporter_test.rb:6$}, @output.string
+ ensure
+ Rails::TestUnitReporter.executable = original_executable
+ end
+ end
+
private
def assert_rerun_snippet_count(snippet_count)
assert_equal snippet_count, @output.string.scan(%r{^bin/rails test }).size
diff --git a/tools/test.rb b/tools/test.rb
index 50cce2081a..70f295b554 100644
--- a/tools/test.rb
+++ b/tools/test.rb
@@ -8,3 +8,5 @@ module Rails
@root ||= Pathname.new(COMPONENT_ROOT)
end
end
+
+Rails::TestUnitReporter.executable = "bin/test"