Permalink
Browse files

Merge branch '3-0-stable' of github.com:rails/rails into 3-0-stable

  • Loading branch information...
2 parents 6eab52d + 6e66d61 commit b7b28d522420c9679a1942fea7d736e459bf8357 @dhh dhh committed Nov 26, 2010
Showing with 383 additions and 171 deletions.
  1. +1 −1 actionpack/lib/action_controller/metal/renderers.rb
  2. +1 −1 actionpack/lib/action_dispatch/http/mime_negotiation.rb
  3. +1 −1 actionpack/lib/action_dispatch/http/request.rb
  4. +8 −2 actionpack/lib/action_dispatch/http/upload.rb
  5. +14 −9 actionpack/lib/action_dispatch/routing/mapper.rb
  6. +9 −3 actionpack/lib/action_view/helpers/asset_tag_helper.rb
  7. +0 −8 actionpack/test/abstract_unit.rb
  8. +12 −0 actionpack/test/activerecord/active_record_store_test.rb
  9. +18 −0 actionpack/test/controller/mime_responds_test.rb
  10. +9 −1 actionpack/test/controller/routing_test.rb
  11. +11 −0 actionpack/test/dispatch/routing_test.rb
  12. +12 −0 actionpack/test/dispatch/uploaded_file_test.rb
  13. +6 −0 actionpack/test/lib/controller/fake_models.rb
  14. +24 −4 actionpack/test/template/asset_tag_helper_test.rb
  15. +3 −1 activemodel/lib/active_model/validations/validates.rb
  16. +0 −6 activemodel/test/cases/helper.rb
  17. +6 −0 activemodel/test/cases/validations/validates_test.rb
  18. +21 −5 activerecord/lib/active_record/association_preload.rb
  19. +1 −1 activerecord/lib/active_record/autosave_association.rb
  20. +1 −0 activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
  21. +5 −0 activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
  22. +2 −5 activerecord/lib/active_record/nested_attributes.rb
  23. +23 −5 activerecord/lib/active_record/relation/query_methods.rb
  24. +52 −0 activerecord/test/cases/associations/eager_test.rb
  25. +0 −5 activerecord/test/cases/helper.rb
  26. +1 −0 activerecord/test/cases/locking_test.rb
  27. +14 −1 activerecord/test/cases/nested_attributes_test.rb
  28. +21 −0 activerecord/test/cases/relations_test.rb
  29. +8 −0 activerecord/test/models/pet.rb
  30. +1 −0 activesupport/lib/active_support/core_ext/module/synchronization.rb
  31. +14 −6 activesupport/lib/active_support/core_ext/string/output_safety.rb
  32. +3 −4 activesupport/lib/active_support/hash_with_indifferent_access.rb
  33. +14 −0 activesupport/test/core_ext/hash_ext_test.rb
  34. +1 −0 activesupport/test/core_ext/module/synchronization_test.rb
  35. +1 −1 railties/guides/assets/stylesheets/main.css
  36. +2 −7 railties/guides/rails_guides/helpers.rb
  37. +2 −2 railties/guides/source/3_0_release_notes.textile
  38. +0 −2 railties/guides/source/action_controller_overview.textile
  39. +1 −1 railties/guides/source/action_mailer_basics.textile
  40. +0 −2 railties/guides/source/action_view_overview.textile
  41. +0 −2 railties/guides/source/active_record_querying.textile
  42. +3 −5 railties/guides/source/active_record_validations_callbacks.textile
  43. +6 −2 railties/guides/source/active_support_core_extensions.textile
  44. +0 −2 railties/guides/source/association_basics.textile
  45. +0 −1 railties/guides/source/caching_with_rails.textile
  46. +0 −3 railties/guides/source/command_line.textile
  47. +0 −2 railties/guides/source/configuring.textile
  48. +1 −1 railties/guides/source/contribute.textile
  49. +1 −3 railties/guides/source/contributing_to_rails.textile
  50. +0 −2 railties/guides/source/debugging_rails_applications.textile
  51. +0 −2 railties/guides/source/form_helpers.textile
  52. +2 −4 railties/guides/source/generators.textile
  53. +0 −2 railties/guides/source/getting_started.textile
  54. +12 −17 railties/guides/source/i18n.textile
  55. +7 −7 railties/guides/source/index.html.erb
  56. +25 −0 railties/guides/source/layout.html.erb
  57. +0 −2 railties/guides/source/layouts_and_rendering.textile
  58. +0 −2 railties/guides/source/migrations.textile
  59. +0 −2 railties/guides/source/performance_testing.textile
  60. +0 −2 railties/guides/source/plugins.textile
  61. +0 −2 railties/guides/source/rails_application_templates.textile
  62. +0 −2 railties/guides/source/rails_on_rack.textile
  63. +1 −3 railties/guides/source/routing.textile
  64. +0 −2 railties/guides/source/security.textile
  65. +0 −2 railties/guides/source/testing.textile
  66. +2 −2 railties/lib/rails/railtie.rb
  67. +0 −11 railties/lib/rails/test_help.rb
@@ -71,7 +71,7 @@ def self._write_render_options
end
add :json do |json, options|
- json = json.to_json(options) unless json.respond_to?(:to_str)
+ json = json.to_json(options) unless json.kind_of?(String)
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
self.content_type ||= Mime::JSON
self.response_body = json
@@ -36,7 +36,7 @@ def accepts
#
# GET /posts/5.xml | request.format => Mime::XML
# GET /posts/5.xhtml | request.format => Mime::HTML
- # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt>
+ # GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first
#
def format(view_path = [])
formats.first
@@ -216,7 +216,7 @@ def body_stream #:nodoc:
# TODO This should be broken apart into AD::Request::Session and probably
# be included by the session middleware.
def reset_session
- session.destroy if session
+ session.destroy if session && session.respond_to?(:destroy)
self.session = {}
@env['action_dispatch.request.flash_hash'] = nil
end
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/object/blank'
-
module ActionDispatch
module Http
class UploadedFile
@@ -13,6 +11,14 @@ def initialize(hash)
raise(ArgumentError, ':tempfile is required') unless @tempfile
end
+ def open
+ @tempfile.open
+ end
+
+ def path
+ @tempfile.path
+ end
+
def read(*args)
@tempfile.read(*args)
end
@@ -66,6 +66,18 @@ def normalize_options!
end
@options.merge!(default_controller_and_action(to_shorthand))
+
+ requirements.each do |name, requirement|
+ # segment_keys.include?(k.to_s) || k == :controller
+ next unless Regexp === requirement && !constraints[name]
+
+ if requirement.source =~ %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
+ raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
+ end
+ if requirement.multiline?
+ raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
+ end
+ end
end
# match "account/overview"
@@ -113,15 +125,6 @@ def requirements
@requirements ||= (@options[:constraints].is_a?(Hash) ? @options[:constraints] : {}).tap do |requirements|
requirements.reverse_merge!(@scope[:constraints]) if @scope[:constraints]
@options.each { |k, v| requirements[k] = v if v.is_a?(Regexp) }
-
- requirements.values.grep(Regexp).each do |requirement|
- if requirement.source =~ %r{\A(\\A|\^)|(\\Z|\\z|\$)\Z}
- raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
- end
- if requirement.multiline?
- raise ArgumentError, "Regexp multiline option not allowed in routing requirements: #{requirement.inspect}"
- end
- end
end
end
@@ -1262,6 +1265,8 @@ def name_for_action(as, action)
name_prefix = @scope[:as]
if parent_resource
+ return nil if as.nil? && action.nil?
+
collection_name = parent_resource.collection_name
member_name = parent_resource.member_name
end
@@ -375,7 +375,10 @@ def javascript_include_tag(*sources)
# <script type="text/javascript" src="/javascripts/body.js"></script>
# <script type="text/javascript" src="/javascripts/tail.js"></script>
def self.register_javascript_expansion(expansions)
- @@javascript_expansions.merge!(expansions)
+ expansions.each do |key, values|
+ @@javascript_expansions[key] ||= []
+ @@javascript_expansions[key] += Array(values)
+ end
end
# Register one or more stylesheet files to be included when <tt>symbol</tt>
@@ -390,7 +393,10 @@ def self.register_javascript_expansion(expansions)
# <link href="/stylesheets/body.css" media="screen" rel="stylesheet" type="text/css" />
# <link href="/stylesheets/tail.css" media="screen" rel="stylesheet" type="text/css" />
def self.register_stylesheet_expansion(expansions)
- @@stylesheet_expansions.merge!(expansions)
+ expansions.each do |key, values|
+ @@stylesheet_expansions[key] ||= []
+ @@stylesheet_expansions[key] += Array(values)
+ end
end
def self.reset_javascript_include_default
@@ -860,7 +866,7 @@ def expand_stylesheet_sources(sources, recursive)
def determine_source(source, collection)
case source
when Symbol
- collection[source] || raise(ArgumentError, "No expansion found for #{source.inspect}")
+ collection[source].present? ? collection[source] : raise(ArgumentError, "No expansion found for #{source.inspect}")
else
source
end
@@ -36,14 +36,6 @@
require 'action_controller/caching'
require 'action_controller/caching/sweeping'
-begin
- require 'ruby-debug'
- Debugger.settings[:autoeval] = true
- Debugger.start
-rescue LoadError
- # Debugging disabled. `gem install ruby-debug` to enable.
-end
-
require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
module Rails
@@ -23,6 +23,7 @@ def get_session_id
def call_reset_session
session[:foo]
reset_session
+ reset_session if params[:twice]
session[:foo] = "baz"
head :ok
end
@@ -74,6 +75,17 @@ def test_getting_nil_session_value
end
end
+ def test_calling_reset_session_twice_does_not_raise_errors
+ with_test_route_set do
+ get '/call_reset_session', :twice => "true"
+ assert_response :success
+
+ get '/get_session_value'
+ assert_response :success
+ assert_equal 'foo: "baz"', response.body
+ end
+ end
+
def test_setting_session_value_after_session_reset
with_test_route_set do
get '/set_session_value'
@@ -556,6 +556,17 @@ def index
end
end
+class RenderJsonRespondWithController < RespondWithController
+ clear_respond_to
+ respond_to :json
+
+ def index
+ respond_with(resource) do |format|
+ format.json { render :json => RenderJsonTestException.new('boom') }
+ end
+ end
+end
+
class EmptyRespondWithController < ActionController::Base
def index
respond_with(Customer.new("david", 13))
@@ -869,6 +880,13 @@ def test_block_inside_respond_with_is_rendered
assert_equal "JSON", @response.body
end
+ def test_render_json_object_responds_to_str_still_produce_json
+ @controller = RenderJsonRespondWithController.new
+ @request.accept = "application/json"
+ get :index, :format => :json
+ assert_equal %Q{{"message":"boom","error":"RenderJsonTestException"}}, @response.body
+ end
+
def test_no_double_render_is_raised
@request.accept = "text/html"
assert_raise ActionView::MissingTemplate do
@@ -875,7 +875,15 @@ def test_route_with_parameter_shell
assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10'))
end
- def test_route_requirements_with_anchor_chars_are_invalid
+ def test_route_constraints_on_request_object_with_anchors_are_valid
+ assert_nothing_raised do
+ set.draw do
+ match 'page/:id' => 'pages#show', :constraints => { :host => /^foo$/ }
+ end
+ end
+ end
+
+ def test_route_constraints_with_anchor_chars_are_invalid
assert_raise ArgumentError do
set.draw do |map|
map.connect 'page/:id', :controller => 'pages', :action => 'show', :id => /^\d+/
@@ -155,6 +155,11 @@ def self.matches?(request)
end
resources :replies do
+ collection do
+ get 'page/:page' => 'replies#index', :page => %r{\d+}
+ get ':page' => 'replies#index', :page => %r{\d+}
+ end
+
new do
post :preview
end
@@ -1249,6 +1254,12 @@ def test_match_shorthand_inside_namespace
end
end
+ def test_dynamically_generated_helpers_on_collection_do_not_clobber_resources_url_helper
+ with_test_routes do
+ assert_equal '/replies', replies_path
+ end
+ end
+
def test_scoped_controller_with_namespace_and_action
with_test_routes do
assert_equal '/account/twitter/callback', account_callback_path("twitter")
@@ -28,6 +28,18 @@ def test_tempfile
assert_equal 'foo', uf.tempfile
end
+ def test_delegates_path_to_tempfile
+ tf = Class.new { def path; 'thunderhorse' end }
+ uf = Http::UploadedFile.new(:tempfile => tf.new)
+ assert_equal 'thunderhorse', uf.path
+ end
+
+ def test_delegates_open_to_tempfile
+ tf = Class.new { def open; 'thunderhorse' end }
+ uf = Http::UploadedFile.new(:tempfile => tf.new)
+ assert_equal 'thunderhorse', uf.open
+ end
+
def test_delegates_to_tempfile
tf = Class.new { def read; 'thunderhorse' end }
uf = Http::UploadedFile.new(:tempfile => tf.new)
@@ -159,3 +159,9 @@ def each
a.each { |i| yield i }
end
end
+
+class RenderJsonTestException < Exception
+ def to_json(options = nil)
+ return { :error => self.class.name, :message => self.to_str }.to_json
+ end
+end
@@ -47,13 +47,19 @@ def host_with_port() 'localhost' end
ActionView::Helpers::AssetTagHelper::register_javascript_expansion :defaults => ['prototype', 'effects', 'dragdrop', 'controls', 'rails']
end
- def url_for(*args)
- "http://www.example.com"
- end
-
def teardown
+ super
config.perform_caching = false
ENV.delete('RAILS_ASSET_ID')
+
+ ActionView::Helpers::AssetTagHelper.module_eval do
+ javascript_expansions.clear
+ stylesheet_expansions.clear
+ end
+ end
+
+ def url_for(*args)
+ "http://www.example.com"
end
AutoDiscoveryToTag = {
@@ -268,6 +274,13 @@ def test_custom_javascript_expansions_and_defaults_puts_application_js_at_the_en
assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag('controls',:defaults, :robbery, 'effects')
end
+ def test_registering_javascript_expansions_merges_with_existing_expansions
+ ENV["RAILS_ASSET_ID"] = ""
+ ActionView::Helpers::AssetTagHelper::register_javascript_expansion :can_merge => ['bank']
+ ActionView::Helpers::AssetTagHelper::register_javascript_expansion :can_merge => ['robber']
+ assert_dom_equal %(<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>), javascript_include_tag(:can_merge)
+ end
+
def test_custom_javascript_expansions_with_undefined_symbol
ActionView::Helpers::AssetTagHelper::register_javascript_expansion :monkey => nil
assert_raise(ArgumentError) { javascript_include_tag('first', :monkey, 'last') }
@@ -334,6 +347,13 @@ def test_custom_stylesheet_expansions_with_undefined_symbol
assert_raise(ArgumentError) { stylesheet_link_tag('first', :monkey, 'last') }
end
+ def test_registering_stylesheet_expansions_merges_with_existing_expansions
+ ENV["RAILS_ASSET_ID"] = ""
+ ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :can_merge => ['bank']
+ ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :can_merge => ['robber']
+ assert_dom_equal %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag(:can_merge)
+ end
+
def test_image_path
ImagePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
@@ -103,8 +103,10 @@ def _parse_validates_options(options) #:nodoc:
{ :with => options }
when Range, Array
{ :in => options }
+ else
+ raise ArgumentError, "#{options.inspect} is an invalid option. Expecting true, Hash, Regexp, Range, or Array"
end
end
end
end
-end
+end
@@ -12,9 +12,3 @@
require 'rubygems'
require 'test/unit'
-
-begin
- require 'ruby-debug'
- Debugger.start
-rescue LoadError
-end
@@ -60,6 +60,12 @@ def test_validates_with_allow_nil_shared_conditions
assert person.valid?
end
+ def test_validates_raises_error_on_invalid_option
+ assert_raises ArgumentError do
+ Person.validates :karma, :length => 5
+ end
+ end
+
def test_validates_with_regexp
Person.validates :karma, :format => /positive|negative/
person = Person.new
Oops, something went wrong.

0 comments on commit b7b28d5

Please sign in to comment.