aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2010-08-20 17:18:57 +0200
committerXavier Noria <fxn@hashref.com>2010-08-20 17:18:57 +0200
commit0c75ec51a9b60252125534b8f9a3f6406713a957 (patch)
tree34165e93f7dd01157f77e4e70a46ec6a5bed77c8
parent87398e531d0bb23b30787fe26d86678dba322895 (diff)
parent2ffa50f5a9fac08e08869687006031b70322497a (diff)
downloadrails-0c75ec51a9b60252125534b8f9a3f6406713a957.tar.gz
rails-0c75ec51a9b60252125534b8f9a3f6406713a957.tar.bz2
rails-0c75ec51a9b60252125534b8f9a3f6406713a957.zip
Merge remote branch 'rails/master'
-rw-r--r--Gemfile2
-rw-r--r--Rakefile8
-rw-r--r--actionmailer/Rakefile16
-rw-r--r--actionpack/Rakefile21
-rw-r--r--actionpack/actionpack.gemspec4
-rw-r--r--actionpack/lib/action_controller/metal/responder.rb10
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb10
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb43
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb2
-rw-r--r--actionpack/test/dispatch/request_test.rb36
-rw-r--r--actionpack/test/dispatch/routing_test.rb139
-rw-r--r--actionpack/test/template/form_helper_test.rb2
-rw-r--r--actionpack/test/template/form_tag_helper_test.rb2
-rw-r--r--activemodel/Rakefile18
-rw-r--r--activemodel/lib/active_model/validations/callbacks.rb2
-rw-r--r--activemodel/test/cases/validations_test.rb2
-rw-r--r--activemodel/test/models/topic.rb9
-rw-r--r--activerecord/Rakefile25
-rw-r--r--activerecord/activerecord.gemspec2
-rw-r--r--activerecord/lib/active_record/associations/association_collection.rb7
-rw-r--r--activerecord/lib/active_record/base.rb10
-rw-r--r--activerecord/lib/active_record/callbacks.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb1
-rw-r--r--activerecord/lib/active_record/relation.rb11
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb10
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb2
-rw-r--r--activerecord/test/cases/adapters/mysql2/connection_test.rb2
-rw-r--r--activerecord/test/cases/associations/extension_test.rb13
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb19
-rw-r--r--activerecord/test/cases/autosave_association_test.rb26
-rw-r--r--activerecord/test/cases/base_test.rb2
-rw-r--r--activerecord/test/cases/callbacks_test.rb7
-rw-r--r--activerecord/test/cases/pooled_connections_test.rb2
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb12
-rw-r--r--activerecord/test/models/bulb.rb7
-rw-r--r--activerecord/test/models/car.rb1
-rw-r--r--activerecord/test/schema/schema.rb5
-rw-r--r--activeresource/Rakefile17
-rw-r--r--activesupport/Rakefile17
-rw-r--r--activesupport/lib/active_support/core_ext/hash/indifferent_access.rb4
-rw-r--r--activesupport/lib/active_support/dependencies.rb94
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb13
-rw-r--r--activesupport/test/dependencies_test.rb10
-rwxr-xr-xci/ci_build.rb2
-rw-r--r--railties/Rakefile16
-rw-r--r--railties/guides/source/initialization.textile4
47 files changed, 401 insertions, 276 deletions
diff --git a/Gemfile b/Gemfile
index 714437d917..32dc75588d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -10,7 +10,7 @@ gem "rails", :path => File.dirname(__FILE__)
gem "rake", ">= 0.8.7"
gem "mocha", ">= 0.9.8"
-gem "rdoc", ">= 2.5.9"
+gem "rdoc", ">= 2.5.10"
gem "horo", ">= 1.0.1"
# AS
diff --git a/Rakefile b/Rakefile
index ceb0e832b3..092d854c35 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,4 +1,4 @@
-gem 'rdoc', '>= 2.5.9'
+gem 'rdoc', '>= 2.5.10'
require 'rdoc'
require 'rake'
@@ -144,12 +144,6 @@ task :rdoc do
FileUtils.copy "activerecord/examples/associations.png", "doc/rdoc/files/examples/associations.png"
end
-desc "Publish API docs for Rails as a whole and for each component"
-task :pdoc => :rdoc do
- require 'rake/contrib/sshpublisher'
- Rake::SshDirPublisher.new("rails@api.rubyonrails.org", "public_html/api", "doc/rdoc").upload
-end
-
task :update_versions do
require File.dirname(__FILE__) + "/version"
diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile
index a47426bd07..cba6e93c8a 100644
--- a/actionmailer/Rakefile
+++ b/actionmailer/Rakefile
@@ -1,8 +1,5 @@
-gem 'rdoc', '>= 2.5.9'
-require 'rdoc'
require 'rake'
require 'rake/testtask'
-require 'rdoc/task'
require 'rake/packagetask'
require 'rake/gempackagetask'
@@ -25,19 +22,6 @@ namespace :test do
end
end
-# Generate the RDoc documentation
-RDoc::Task.new { |rdoc|
- rdoc.rdoc_dir = 'doc'
- rdoc.title = "Action Mailer -- Easy email delivery and testing"
- rdoc.options << '--charset' << 'utf-8'
- rdoc.options << '-f' << 'horo'
- rdoc.options << '--main' << 'README.rdoc'
- rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG')
- rdoc.rdoc_files.include('lib/action_mailer.rb')
- rdoc.rdoc_files.include('lib/action_mailer/*.rb')
- rdoc.rdoc_files.include('lib/action_mailer/delivery_method/*.rb')
-}
-
spec = eval(File.read('actionmailer.gemspec'))
Rake::GemPackageTask.new(spec) do |p|
diff --git a/actionpack/Rakefile b/actionpack/Rakefile
index 4af8ea167a..d67c6f2410 100644
--- a/actionpack/Rakefile
+++ b/actionpack/Rakefile
@@ -1,8 +1,5 @@
-gem 'rdoc', '>= 2.5.9'
-require 'rdoc'
require 'rake'
require 'rake/testtask'
-require 'rdoc/task'
require 'rake/packagetask'
require 'rake/gempackagetask'
@@ -36,24 +33,6 @@ Rake::TestTask.new(:test_active_record_integration) do |t|
t.test_files = Dir.glob("test/activerecord/*_test.rb")
end
-# Genereate the RDoc documentation
-
-RDoc::Task.new { |rdoc|
- rdoc.rdoc_dir = 'doc'
- rdoc.title = "Action Pack -- On rails from request to response"
- rdoc.options << '--charset' << 'utf-8'
- rdoc.options << '-f' << 'horo'
- rdoc.options << '--main' << 'README.rdoc'
- if ENV['DOC_FILES']
- rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
- else
- rdoc.rdoc_files.include('README.rdoc', 'RUNNING_UNIT_TESTS', 'CHANGELOG')
- rdoc.rdoc_files.include(Dir['lib/**/*.rb'] -
- Dir['lib/*/vendor/**/*.rb'])
- rdoc.rdoc_files.exclude('lib/actionpack.rb')
- end
-}
-
spec = eval(File.read('actionpack.gemspec'))
Rake::GemPackageTask.new(spec) do |p|
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index 99deff234c..a5ebc18e2a 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
s.add_dependency('i18n', '~> 0.4.1')
s.add_dependency('rack', '~> 1.2.1')
s.add_dependency('rack-test', '~> 0.5.4')
- s.add_dependency('rack-mount', '~> 0.6.9')
- s.add_dependency('tzinfo', '~> 0.3.22')
+ s.add_dependency('rack-mount', '~> 0.6.10')
+ s.add_dependency('tzinfo', '~> 0.3.23')
s.add_dependency('erubis', '~> 2.6.6')
end
diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb
index cb644dfd16..aafba2a65f 100644
--- a/actionpack/lib/action_controller/metal/responder.rb
+++ b/actionpack/lib/action_controller/metal/responder.rb
@@ -89,6 +89,8 @@ module ActionController #:nodoc:
def initialize(controller, resources, options={})
@controller = controller
+ @request = @controller.request
+ @format = @controller.formats.first
@resource = resources.last
@resources = resources
@options = options
@@ -99,14 +101,6 @@ module ActionController #:nodoc:
delegate :head, :render, :redirect_to, :to => :controller
delegate :get?, :post?, :put?, :delete?, :to => :request
- def request
- @request ||= @controller.request
- end
-
- def format
- @format ||= @controller.formats.first
- end
-
# Undefine :to_json and :to_yaml since it's defined on Object
undef_method(:to_json) if method_defined?(:to_json)
undef_method(:to_yaml) if method_defined?(:to_yaml)
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index b64a83c62e..ffb7bdd586 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -6,6 +6,11 @@ module ActionDispatch
protocol + host_with_port + fullpath
end
+ # Returns 'https' if this is an SSL request and 'http' otherwise.
+ def scheme
+ ssl? ? 'https' : 'http'
+ end
+
# Returns 'https://' if this is an SSL request and 'http://' otherwise.
def protocol
ssl? ? 'https://' : 'http://'
@@ -53,6 +58,11 @@ module ActionDispatch
end
end
+ # Returns whether this request is using the standard port
+ def standard_port?
+ port == standard_port
+ end
+
# Returns a \port suffix like ":8080" if the \port number of this request
# is not the default HTTP \port 80 or HTTPS \port 443.
def port_string
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index c118c72440..800c6b469e 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -288,7 +288,7 @@ module ActionDispatch
uri = URI.parse(path_proc.call(*params))
uri.scheme ||= req.scheme
uri.host ||= req.host
- uri.port ||= req.port unless req.port == 80
+ uri.port ||= req.port unless req.standard_port?
body = %(<html><body>You are being <a href="#{ERB::Util.h(uri.to_s)}">redirected</a>.</body></html>)
@@ -473,7 +473,7 @@ module ActionDispatch
def initialize(entities, options = {})
@name = entities.to_s
- @path = options.delete(:path) || @name
+ @path = (options.delete(:path) || @name).to_s
@controller = (options.delete(:controller) || @name).to_s
@as = options.delete(:as)
@options = options
@@ -498,16 +498,14 @@ module ActionDispatch
end
def plural
- name.to_s.pluralize
+ @plural ||= name.to_s
end
def singular
- name.to_s.singularize
+ @singular ||= name.to_s.singularize
end
- def member_name
- singular
- end
+ alias :member_name :singular
# Checks for uncountable plurals, and appends "_index" if they're.
def collection_name
@@ -518,9 +516,7 @@ module ActionDispatch
{ :controller => controller }
end
- def collection_scope
- path
- end
+ alias :collection_scope :path
def member_scope
"#{path}/:id"
@@ -541,21 +537,25 @@ module ActionDispatch
def initialize(entities, options)
@name = entities.to_s
- @path = options.delete(:path) || @name
+ @path = (options.delete(:path) || @name).to_s
@controller = (options.delete(:controller) || plural).to_s
@as = options.delete(:as)
@options = options
end
- def member_name
- name
+ def plural
+ @plural ||= name.to_s.pluralize
end
- alias :collection_name :member_name
- def member_scope
- path
+ def singular
+ @singular ||= name.to_s
end
- alias :nested_scope :member_scope
+
+ alias :member_name :singular
+ alias :collection_name :singular
+
+ alias :member_scope :path
+ alias :nested_scope :path
end
def initialize(*args) #:nodoc:
@@ -586,10 +586,10 @@ module ActionDispatch
end if parent_resource.actions.include?(:new)
member_scope do
+ get :edit if parent_resource.actions.include?(:edit)
get :show if parent_resource.actions.include?(:show)
put :update if parent_resource.actions.include?(:update)
delete :destroy if parent_resource.actions.include?(:destroy)
- get :edit if parent_resource.actions.include?(:edit)
end
end
@@ -616,10 +616,10 @@ module ActionDispatch
end if parent_resource.actions.include?(:new)
member_scope do
+ get :edit if parent_resource.actions.include?(:edit)
get :show if parent_resource.actions.include?(:show)
put :update if parent_resource.actions.include?(:update)
delete :destroy if parent_resource.actions.include?(:destroy)
- get :edit if parent_resource.actions.include?(:edit)
end
end
@@ -731,6 +731,7 @@ module ActionDispatch
end
elsif resource_method_scope?
path = path_for_custom_action
+ options[:action] ||= action
options[:as] = name_for_action(options[:as]) if options[:as]
args.push(options)
@@ -773,6 +774,10 @@ module ActionDispatch
return true
end
+ options.each do |k,v|
+ (options[:constraints] ||= {})[k] = options.delete(k) if options[k].is_a?(Regexp)
+ end
+
scope_options = options.slice!(*RESOURCE_OPTIONS)
unless scope_options.empty?
scope(scope_options) do
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index b9d27be639..43ffadc004 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -538,7 +538,7 @@ module ActionView
def extra_tags_for_form(html_options)
snowman_tag = tag(:input, :type => "hidden",
- :name => "_utf8", :value => "&#9731;".html_safe)
+ :name => "utf8", :value => "&#x2713;".html_safe)
method = html_options.delete("method").to_s
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 249fa406a0..546c4cb253 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -132,6 +132,32 @@ class RequestTest < ActiveSupport::TestCase
assert_equal [], request.subdomains
end
+ test "standard_port" do
+ request = stub_request
+ assert_equal 80, request.standard_port
+
+ request = stub_request 'HTTPS' => 'on'
+ assert_equal 443, request.standard_port
+ end
+
+ test "standard_port?" do
+ request = stub_request
+ assert !request.ssl?
+ assert request.standard_port?
+
+ request = stub_request 'HTTPS' => 'on'
+ assert request.ssl?
+ assert request.standard_port?
+
+ request = stub_request 'HTTP_HOST' => 'www.example.org:8080'
+ assert !request.ssl?
+ assert !request.standard_port?
+
+ request = stub_request 'HTTP_HOST' => 'www.example.org:8443', 'HTTPS' => 'on'
+ assert request.ssl?
+ assert !request.standard_port?
+ end
+
test "port string" do
request = stub_request 'HTTP_HOST' => 'www.example.org:80'
assert_equal "", request.port_string
@@ -223,6 +249,16 @@ class RequestTest < ActiveSupport::TestCase
assert request.ssl?
end
+ test "scheme returns https when proxied" do
+ request = stub_request 'rack.url_scheme' => 'http'
+ assert !request.ssl?
+ assert_equal 'http', request.scheme
+
+ request = stub_request 'rack.url_scheme' => 'http', 'HTTP_X_FORWARDED_PROTO' => 'https'
+ assert request.ssl?
+ assert_equal 'https', request.scheme
+ end
+
test "String request methods" do
[:get, :post, :put, :delete].each do |method|
request = stub_request 'REQUEST_METHOD' => method.to_s.upcase
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 3f090b7254..44b83f3afc 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -45,6 +45,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
match 'account/logout' => redirect("/logout"), :as => :logout_redirect
match 'account/login', :to => redirect("/login")
+ match 'secure', :to => redirect("/secure/login")
constraints(lambda { |req| true }) do
match 'account/overview'
@@ -128,7 +129,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
member do
- get :some_path_with_name
+ get 'some_path_with_name'
put :accessible_projects
post :resend, :generate_new_password
end
@@ -337,6 +338,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
resources :content
+ namespace :transport do
+ resources :taxis
+ end
+
+ namespace :medical do
+ resource :taxis
+ end
+
scope :constraints => { :id => /\d+/ } do
get '/tickets', :to => 'tickets#index', :as => :tickets
end
@@ -371,6 +380,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ namespace :wiki do
+ resources :articles, :id => /[^\/]+/ do
+ resources :comments, :only => [:create, :new]
+ end
+ end
+
+ resources :wiki_pages, :path => :pages
+ resource :wiki_account, :path => :my_account
+
scope :only => :show do
namespace :only do
resources :sectors, :only => :index do
@@ -405,6 +423,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ resources :sections, :id => /.+/ do
+ get :preview, :on => :member
+ end
+
match '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/
end
end
@@ -1884,11 +1906,126 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ def test_resources_are_not_pluralized
+ with_test_routes do
+ get '/transport/taxis'
+ assert_equal 'transport/taxis#index', @response.body
+ assert_equal '/transport/taxis', transport_taxis_path
+
+ get '/transport/taxis/new'
+ assert_equal 'transport/taxis#new', @response.body
+ assert_equal '/transport/taxis/new', new_transport_taxi_path
+
+ post '/transport/taxis'
+ assert_equal 'transport/taxis#create', @response.body
+
+ get '/transport/taxis/1'
+ assert_equal 'transport/taxis#show', @response.body
+ assert_equal '/transport/taxis/1', transport_taxi_path(:id => '1')
+
+ get '/transport/taxis/1/edit'
+ assert_equal 'transport/taxis#edit', @response.body
+ assert_equal '/transport/taxis/1/edit', edit_transport_taxi_path(:id => '1')
+
+ put '/transport/taxis/1'
+ assert_equal 'transport/taxis#update', @response.body
+
+ delete '/transport/taxis/1'
+ assert_equal 'transport/taxis#destroy', @response.body
+ end
+ end
+
+ def test_singleton_resources_are_not_singularized
+ with_test_routes do
+ get '/medical/taxis/new'
+ assert_equal 'medical/taxes#new', @response.body
+ assert_equal '/medical/taxis/new', new_medical_taxis_path
+
+ post '/medical/taxis'
+ assert_equal 'medical/taxes#create', @response.body
+
+ get '/medical/taxis'
+ assert_equal 'medical/taxes#show', @response.body
+ assert_equal '/medical/taxis', medical_taxis_path
+
+ get '/medical/taxis/edit'
+ assert_equal 'medical/taxes#edit', @response.body
+ assert_equal '/medical/taxis/edit', edit_medical_taxis_path
+
+ put '/medical/taxis'
+ assert_equal 'medical/taxes#update', @response.body
+
+ delete '/medical/taxis'
+ assert_equal 'medical/taxes#destroy', @response.body
+ end
+ end
+
+ def test_greedy_resource_id_regexp_doesnt_match_edit_and_custom_action
+ with_test_routes do
+ get '/sections/1/edit'
+ assert_equal 'sections#edit', @response.body
+ assert_equal '/sections/1/edit', edit_section_path(:id => '1')
+
+ get '/sections/1/preview'
+ assert_equal 'sections#preview', @response.body
+ assert_equal '/sections/1/preview', preview_section_path(:id => '1')
+ end
+ end
+
+ def test_resource_constraints_are_pushed_to_scope
+ with_test_routes do
+ get '/wiki/articles/Ruby_on_Rails_3.0'
+ assert_equal 'wiki/articles#show', @response.body
+ assert_equal '/wiki/articles/Ruby_on_Rails_3.0', wiki_article_path(:id => 'Ruby_on_Rails_3.0')
+
+ get '/wiki/articles/Ruby_on_Rails_3.0/comments/new'
+ assert_equal 'wiki/comments#new', @response.body
+ assert_equal '/wiki/articles/Ruby_on_Rails_3.0/comments/new', new_wiki_article_comment_path(:article_id => 'Ruby_on_Rails_3.0')
+
+ post '/wiki/articles/Ruby_on_Rails_3.0/comments'
+ assert_equal 'wiki/comments#create', @response.body
+ assert_equal '/wiki/articles/Ruby_on_Rails_3.0/comments', wiki_article_comments_path(:article_id => 'Ruby_on_Rails_3.0')
+ end
+ end
+
+ def test_resources_path_can_be_a_symbol
+ with_test_routes do
+ get '/pages'
+ assert_equal 'wiki_pages#index', @response.body
+ assert_equal '/pages', wiki_pages_path
+
+ get '/pages/Ruby_on_Rails'
+ assert_equal 'wiki_pages#show', @response.body
+ assert_equal '/pages/Ruby_on_Rails', wiki_page_path(:id => 'Ruby_on_Rails')
+
+ get '/my_account'
+ assert_equal 'wiki_accounts#show', @response.body
+ assert_equal '/my_account', wiki_account_path
+ end
+ end
+
+ def test_redirect_https
+ with_test_routes do
+ with_https do
+ get '/secure'
+ verify_redirect 'https://www.example.com/secure/login'
+ end
+ end
+ end
+
private
def with_test_routes
yield
end
+ def with_https
+ old_https = https?
+ https!
+ yield
+ ensure
+ https!(old_https)
+ end
+
def verify_redirect(url, status=301)
assert_equal status, @response.status
assert_equal url, @response.headers['Location']
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 4c81e691b2..71a5ae0245 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -1513,7 +1513,7 @@ class FormHelperTest < ActionView::TestCase
def snowman(method = nil)
txt = %{<div style="margin:0;padding:0;display:inline">}
- txt << %{<input name="_utf8" type="hidden" value="&#9731;" />}
+ txt << %{<input name="utf8" type="hidden" value="&#x2713;" />}
txt << %{<input name="_method" type="hidden" value="#{method}" />} if method
txt << %{</div>}
end
diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb
index d2f725a994..532f086d21 100644
--- a/actionpack/test/template/form_tag_helper_test.rb
+++ b/actionpack/test/template/form_tag_helper_test.rb
@@ -12,7 +12,7 @@ class FormTagHelperTest < ActionView::TestCase
method = options[:method]
txt = %{<div style="margin:0;padding:0;display:inline">}
- txt << %{<input name="_utf8" type="hidden" value="&#9731;" />}
+ txt << %{<input name="utf8" type="hidden" value="&#x2713;" />}
txt << %{<input name="_method" type="hidden" value="#{method}" />} if method
txt << %{</div>}
end
diff --git a/activemodel/Rakefile b/activemodel/Rakefile
index 3fffc0d021..0372c7a03e 100644
--- a/activemodel/Rakefile
+++ b/activemodel/Rakefile
@@ -1,8 +1,5 @@
dir = File.dirname(__FILE__)
-gem 'rdoc', '>= 2.5.9'
-require 'rdoc'
-
require 'rake/testtask'
task :default => :test
@@ -22,21 +19,6 @@ namespace :test do
end
end
-
-require 'rdoc/task'
-
-# Generate the RDoc documentation
-RDoc::Task.new do |rdoc|
- rdoc.rdoc_dir = "doc"
- rdoc.title = "Active Model"
- rdoc.options << '-f' << 'horo'
- rdoc.options << '--charset' << 'utf-8'
- rdoc.options << '--main' << 'README.rdoc'
- rdoc.rdoc_files.include("README.rdoc", "CHANGELOG")
- rdoc.rdoc_files.include("lib/**/*.rb")
-end
-
-
require 'rake/packagetask'
require 'rake/gempackagetask'
diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb
index afd65d3dd5..858cfda73e 100644
--- a/activemodel/lib/active_model/validations/callbacks.rb
+++ b/activemodel/lib/active_model/validations/callbacks.rb
@@ -40,7 +40,7 @@ module ActiveModel
options = args.extract_options!
options[:prepend] = true
options[:if] = Array.wrap(options[:if])
- options[:if] << "!halted && value != false"
+ options[:if] << "!halted"
options[:if] << "self.validation_context == :#{options[:on]}" if options[:on]
set_callback(:validation, :after, *(args << options), &block)
end
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index f9fc6613f4..1eed0b0c4d 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -25,9 +25,11 @@ class ValidationsTest < ActiveModel::TestCase
r = Reply.new
r.title = "There's no content!"
assert r.invalid?, "A reply without content shouldn't be saveable"
+ assert r.after_validation_performed, "after_validation callback should be called"
r.content = "Messa content!"
assert r.valid?, "A reply with content should be saveable"
+ assert r.after_validation_performed, "after_validation callback should be called"
end
def test_single_attr_validation_and_error_msg
diff --git a/activemodel/test/models/topic.rb b/activemodel/test/models/topic.rb
index f25b774cd7..ff34565bdb 100644
--- a/activemodel/test/models/topic.rb
+++ b/activemodel/test/models/topic.rb
@@ -1,7 +1,11 @@
class Topic
include ActiveModel::Validations
+ include ActiveModel::Validations::Callbacks
attr_accessor :title, :author_name, :content, :approved
+ attr_accessor :after_validation_performed
+
+ after_validation :perform_after_validation
def initialize(attributes = {})
attributes.each do |key, value|
@@ -16,4 +20,9 @@ class Topic
def condition_is_true_but_its_not
false
end
+
+ def perform_after_validation
+ self.after_validation_performed = true
+ end
+
end
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index c1e90cc099..c2d63cda23 100644
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -1,8 +1,5 @@
-gem 'rdoc', '>= 2.5.9'
-require 'rdoc'
require 'rake'
require 'rake/testtask'
-require 'rdoc/task'
require 'rake/packagetask'
require 'rake/gempackagetask'
@@ -163,28 +160,6 @@ end
task :build_frontbase_databases => 'frontbase:build_databases'
task :rebuild_frontbase_databases => 'frontbase:rebuild_databases'
-
-# Generate the RDoc documentation
-
-RDoc::Task.new { |rdoc|
- rdoc.rdoc_dir = 'doc'
- rdoc.title = "Active Record -- Object-relation mapping put on rails"
- rdoc.options << '-f' << 'horo'
- rdoc.options << '--main' << 'README.rdoc'
- rdoc.options << '--charset' << 'utf-8'
- rdoc.rdoc_files.include('README.rdoc', 'RUNNING_UNIT_TESTS', 'CHANGELOG')
- rdoc.rdoc_files.include('lib/**/*.rb')
- rdoc.rdoc_files.exclude('lib/active_record/vendor/*')
- rdoc.rdoc_files.include('dev-utils/*.rb')
-}
-
-# Enhance rdoc task to copy referenced images also
-task :rdoc do
- FileUtils.mkdir_p "doc/files/examples/"
- FileUtils.copy "examples/associations.png", "doc/files/examples/associations.png"
-end
-
-
spec = eval(File.read('activerecord.gemspec'))
Rake::GemPackageTask.new(spec) do |p|
diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec
index 67d521d56b..a3c0acb370 100644
--- a/activerecord/activerecord.gemspec
+++ b/activerecord/activerecord.gemspec
@@ -24,5 +24,5 @@ Gem::Specification.new do |s|
s.add_dependency('activesupport', version)
s.add_dependency('activemodel', version)
s.add_dependency('arel', '~> 0.4.0')
- s.add_dependency('tzinfo', '~> 0.3.22')
+ s.add_dependency('tzinfo', '~> 0.3.23')
end
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index b5159eead3..132e9cf882 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -492,7 +492,12 @@ module ActiveRecord
def create_record(attrs)
attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
ensure_owner_is_not_new
- record = @reflection.klass.send(:with_scope, :create => construct_scope[:create]) do
+
+ _scope = self.construct_scope[:create]
+ csm = @reflection.klass.send(:current_scoped_methods)
+ options = (csm.blank? || !_scope.is_a?(Hash)) ? _scope : _scope.merge(csm.where_values_hash)
+
+ record = @reflection.klass.send(:with_scope, :create => options) do
@reflection.build_association(attrs)
end
if block_given?
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 9d3ee9528a..90241dd897 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -918,7 +918,11 @@ module ActiveRecord #:nodoc:
self
else
begin
- compute_type(type_name)
+ if store_full_sti_class
+ ActiveSupport::Dependencies.constantize(type_name)
+ else
+ compute_type(type_name)
+ end
rescue NameError
raise SubclassNotFound,
"The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " +
@@ -1171,7 +1175,7 @@ MSG
if type_name.match(/^::/)
# If the type is prefixed with a scope operator then we assume that
# the type_name is an absolute reference.
- type_name.constantize
+ ActiveSupport::Dependencies.constantize(type_name)
else
# Build a list of candidates to search for
candidates = []
@@ -1180,7 +1184,7 @@ MSG
candidates.each do |candidate|
begin
- constant = candidate.constantize
+ constant = ActiveSupport::Dependencies.constantize(candidate)
return constant if candidate == constant.to_s
rescue NameError => e
# We don't want to swallow NoMethodError < NameError errors
diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb
index c203581735..a31973d529 100644
--- a/activerecord/lib/active_record/callbacks.rb
+++ b/activerecord/lib/active_record/callbacks.rb
@@ -235,7 +235,7 @@ module ActiveRecord
:after_initialize, :after_find, :after_touch, :before_validation, :after_validation,
:before_save, :around_save, :after_save, :before_create, :around_create,
:after_create, :before_update, :around_update, :after_update,
- :before_destroy, :around_destroy, :after_destroy
+ :before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback
]
included do
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index 288ce5aebb..37e584a629 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -93,11 +93,7 @@ module ActiveRecord
# #connection can be called any number of times; the connection is
# held in a hash keyed by the thread id.
def connection
- if conn = @reserved_connections[current_connection_id]
- conn
- else
- @reserved_connections[current_connection_id] = checkout
- end
+ @reserved_connections[current_connection_id] ||= checkout
end
# Signal that the thread is finished with the current connection.
@@ -326,7 +322,7 @@ module ActiveRecord
# already been opened.
def connected?(klass)
conn = retrieve_connection_pool(klass)
- conn ? conn.connected? : false
+ conn && conn.connected?
end
# Remove the connection for this class. This will close the active
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 9950387420..d797f9c6c3 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -31,6 +31,7 @@ module ActiveRecord
mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslca] || config[:sslkey]
default_flags = Mysql.const_defined?(:CLIENT_MULTI_RESULTS) ? Mysql::CLIENT_MULTI_RESULTS : 0
+ default_flags |= Mysql::CLIENT_FOUND_ROWS if Mysql.const_defined?(:CLIENT_FOUND_ROWS)
options = [host, username, password, database, port, socket, default_flags]
ConnectionAdapters::MysqlAdapter.new(mysql, logger, options, config)
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index cfe4d23965..03b06205d4 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -316,16 +316,19 @@ module ActiveRecord
@to_sql ||= arel.to_sql
end
- def scope_for_create
- @scope_for_create ||= begin
- @create_with_value || Hash[
- @where_values.find_all { |w|
+ def where_values_hash
+ Hash[@where_values.find_all { |w|
w.respond_to?(:operator) && w.operator == :==
}.map { |where|
[where.operand1.name,
where.operand2.respond_to?(:value) ?
where.operand2.value : where.operand2]
}]
+ end
+
+ def scope_for_create
+ @scope_for_create ||= begin
+ @create_with_value || where_values_hash
end
end
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index 64edcc1ef3..7cf73f7eb3 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -163,19 +163,17 @@ module ActiveRecord
def perform_calculation(operation, column_name, options = {})
operation = operation.to_s.downcase
+ distinct = nil
+
if operation == "count"
column_name ||= (select_for_count || :all)
- joins = arel.joins(arel)
- if joins.present? && joins =~ /LEFT OUTER/i
+ if arel.joins(arel) =~ /LEFT OUTER/i
distinct = true
column_name = @klass.primary_key if column_name == :all
end
- distinct = nil if column_name.to_s =~ /\s*DISTINCT\s+/i
- distinct ||= options[:distinct]
- else
- distinct = nil
+ distinct = nil if column_name =~ /\s*DISTINCT\s+/i
end
distinct = options[:distinct] || distinct
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 0bf0b37900..0b5e9b4fb2 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -229,7 +229,7 @@ module ActiveRecord
arel.project(selects.last)
end
else
- arel.project(@klass.quoted_table_name + '.*')
+ arel.project(Arel::SqlLiteral.new(@klass.quoted_table_name + '.*'))
end
end
diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb
index b973da621b..26091c713b 100644
--- a/activerecord/test/cases/adapters/mysql2/connection_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb
@@ -27,7 +27,7 @@ class MysqlConnectionTest < ActiveRecord::TestCase
sleep 2
@connection.verify!
assert @connection.active?
- end
+ end
private
diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb
index e9240de673..efaab8569e 100644
--- a/activerecord/test/cases/associations/extension_test.rb
+++ b/activerecord/test/cases/associations/extension_test.rb
@@ -46,16 +46,13 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase
assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
end
+ def test_extension_name
+ extension = Proc.new {}
+ name = :association_name
- def test_extension_name
- extension = Proc.new {}
- name = :association_name
-
- assert_equal 'DeveloperAssociationNameAssociationExtension', Developer.send(:create_extension_modules, name, extension, []).first.name
- assert_equal 'MyApplication::Business::DeveloperAssociationNameAssociationExtension', MyApplication::Business::Developer.send(:create_extension_modules, name, extension, []).first.name
+ assert_equal 'DeveloperAssociationNameAssociationExtension', Developer.send(:create_extension_modules, name, extension, []).first.name
+ assert_equal 'MyApplication::Business::DeveloperAssociationNameAssociationExtension', MyApplication::Business::Developer.send(:create_extension_modules, name, extension, []).first.name
assert_equal 'MyApplication::Business::DeveloperAssociationNameAssociationExtension', MyApplication::Business::Developer.send(:create_extension_modules, name, extension, []).first.name
assert_equal 'MyApplication::Business::DeveloperAssociationNameAssociationExtension', MyApplication::Business::Developer.send(:create_extension_modules, name, extension, []).first.name
end
-
-
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 7e10a8ceeb..63fc15bca3 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -13,6 +13,8 @@ require 'models/reader'
require 'models/tagging'
require 'models/invoice'
require 'models/line_item'
+require 'models/car'
+require 'models/bulb'
class HasManyAssociationsTestForCountWithFinderSql < ActiveRecord::TestCase
class Invoice < ActiveRecord::Base
@@ -47,6 +49,23 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
Client.destroyed_client_ids.clear
end
+ def test_create_from_association_should_respect_default_scope
+ car = Car.create(:name => 'honda')
+ assert_equal 'honda', car.name
+
+ bulb = Bulb.create
+ assert_equal 'defaulty', bulb.name
+
+ bulb = car.bulbs.build
+ assert_equal 'defaulty', bulb.name
+
+ bulb = car.bulbs.create
+ assert_equal 'defaulty', bulb.name
+
+ bulb = car.bulbs.create(:name => 'exotic')
+ assert_equal 'exotic', bulb.name
+ end
+
def test_create_resets_cached_counters
person = Person.create!(:first_name => 'tenderlove')
post = Post.first
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 4693cb45fc..52382f5afc 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -249,8 +249,8 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
assert_equal customer1, order.billing
assert_equal customer2, order.shipping
- assert_equal num_orders +1, Order.count
- assert_equal num_customers +2, Customer.count
+ assert_equal num_orders + 1, Order.count
+ assert_equal num_customers + 2, Customer.count
end
def test_store_association_in_two_relations_with_one_save
@@ -268,8 +268,8 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
assert_equal customer, order.billing
assert_equal customer, order.shipping
- assert_equal num_orders +1, Order.count
- assert_equal num_customers +1, Customer.count
+ assert_equal num_orders + 1, Order.count
+ assert_equal num_customers + 1, Customer.count
end
def test_store_association_in_two_relations_with_one_save_in_existing_object
@@ -287,8 +287,8 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
assert_equal customer, order.billing
assert_equal customer, order.shipping
- assert_equal num_orders +1, Order.count
- assert_equal num_customers +1, Customer.count
+ assert_equal num_orders + 1, Order.count
+ assert_equal num_customers + 1, Customer.count
end
def test_store_association_in_two_relations_with_one_save_in_existing_object_with_values
@@ -311,14 +311,14 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
assert_equal customer, order.billing
assert_equal customer, order.shipping
- assert_equal num_orders +1, Order.count
- assert_equal num_customers +2, Customer.count
+ assert_equal num_orders + 1, Order.count
+ assert_equal num_customers + 2, Customer.count
end
def test_store_association_with_a_polymorphic_relationship
num_tagging = Tagging.count
tags(:misc).create_tagging(:taggable => posts(:thinking))
- assert_equal num_tagging +1, Tagging.count
+ assert_equal num_tagging + 1, Tagging.count
end
end
@@ -372,7 +372,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
assert firm.save
assert !client.new_record?
- assert_equal no_of_clients+1, Client.count
+ assert_equal no_of_clients + 1, Client.count
end
def test_invalid_build
@@ -403,8 +403,8 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
assert !new_firm.new_record?
assert !c.new_record?
assert_equal new_firm, c.firm
- assert_equal no_of_firms+1, Firm.count # Firm was saved to database.
- assert_equal no_of_clients+2, Client.count # Clients were saved to database.
+ assert_equal no_of_firms + 1, Firm.count # Firm was saved to database.
+ assert_equal no_of_clients + 2, Client.count # Clients were saved to database.
assert_equal 2, new_firm.clients_of_firm.size
assert_equal 2, new_firm.clients_of_firm(true).size
@@ -1061,7 +1061,7 @@ module AutosaveAssociationOnACollectionAssociationTests
end
def test_should_allow_to_bypass_validations_on_the_associated_models_on_create
- assert_difference("#{ @association_name == :birds ? 'Bird' : 'Parrot' }.count", +2) do
+ assert_difference("#{ @association_name == :birds ? 'Bird' : 'Parrot' }.count", 2) do
2.times { @pirate.send(@association_name).build }
@pirate.save(:validate => false)
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index b2799f649a..55f0b1ce21 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1409,7 +1409,7 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_compute_type_no_method_error
- String.any_instance.stubs(:constantize).raises(NoMethodError)
+ ActiveSupport::Dependencies.stubs(:constantize).raises(NoMethodError)
assert_raises NoMethodError do
ActiveRecord::Base.send :compute_type, 'InvalidModel'
end
diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb
index dc7f82b001..8a84f19836 100644
--- a/activerecord/test/cases/callbacks_test.rb
+++ b/activerecord/test/cases/callbacks_test.rb
@@ -461,7 +461,12 @@ class CallbacksTest < ActiveRecord::TestCase
[ :before_validation, :proc ],
[ :before_validation, :object ],
[ :before_validation, :block ],
- [ :before_validation, :returning_false ]
+ [ :before_validation, :returning_false ],
+ [ :after_rollback, :block ],
+ [ :after_rollback, :object ],
+ [ :after_rollback, :proc ],
+ [ :after_rollback, :string ],
+ [ :after_rollback, :method ],
], david.history
end
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index e61960059e..de5fa140ba 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -89,7 +89,7 @@ class PooledConnectionsTest < ActiveRecord::TestCase
def test_undefined_connection_returns_false
old_handler = ActiveRecord::Base.connection_handler
ActiveRecord::Base.connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
- assert_equal false, ActiveRecord::Base.connected?
+ assert ! ActiveRecord::Base.connected?
ensure
ActiveRecord::Base.connection_handler = old_handler
end
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index cc146f5574..85f222bca2 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -260,22 +260,26 @@ class TransactionObserverCallbacksTest < ActiveRecord::TestCase
class TopicWithObserverAttachedObserver < ActiveRecord::Observer
def after_commit(record)
- record.history.push :"TopicWithObserverAttachedObserver#after_commit"
+ record.history.push "after_commit"
end
def after_rollback(record)
- record.history.push :"TopicWithObserverAttachedObserver#after_rollback"
+ record.history.push "after_rollback"
end
end
def test_after_commit_called
+ assert TopicWithObserverAttachedObserver.instance, 'should have observer'
+
topic = TopicWithObserverAttached.new
topic.save!
- assert_equal topic.history, [:"TopicWithObserverAttachedObserver#after_commit"]
+ assert_equal %w{ after_commit }, topic.history
end
def test_after_rollback_called
+ assert TopicWithObserverAttachedObserver.instance, 'should have observer'
+
topic = TopicWithObserverAttached.new
Topic.transaction do
@@ -283,6 +287,6 @@ class TransactionObserverCallbacksTest < ActiveRecord::TestCase
raise ActiveRecord::Rollback
end
- assert_equal topic.history, [:"TopicWithObserverObserver#after_rollback"]
+ assert_equal %w{ after_rollback }, topic.history
end
end
diff --git a/activerecord/test/models/bulb.rb b/activerecord/test/models/bulb.rb
new file mode 100644
index 0000000000..9eefc5803a
--- /dev/null
+++ b/activerecord/test/models/bulb.rb
@@ -0,0 +1,7 @@
+class Bulb < ActiveRecord::Base
+
+ default_scope :conditions => {:name => 'defaulty' }
+
+ belongs_to :car
+
+end
diff --git a/activerecord/test/models/car.rb b/activerecord/test/models/car.rb
index faf4e6cbc0..903ec53288 100644
--- a/activerecord/test/models/car.rb
+++ b/activerecord/test/models/car.rb
@@ -1,4 +1,5 @@
class Car < ActiveRecord::Base
+ has_many :bulbs
has_many :tyres
has_many :engines
has_many :wheels, :as => :wheelable
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 8017e13920..7657e00800 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -198,6 +198,11 @@ ActiveRecord::Schema.define do
t.integer :car_id
end
+ create_table :bulbs, :force => true do |t|
+ t.integer :car_id
+ t.string :name
+ end
+
create_table :entrants, :force => true do |t|
t.string :name, :null => false
t.integer :course_id, :null => false
diff --git a/activeresource/Rakefile b/activeresource/Rakefile
index 2145f1017c..905241acc0 100644
--- a/activeresource/Rakefile
+++ b/activeresource/Rakefile
@@ -1,8 +1,5 @@
-gem 'rdoc', '>= 2.5.9'
-require 'rdoc'
require 'rake'
require 'rake/testtask'
-require 'rdoc/task'
require 'rake/packagetask'
require 'rake/gempackagetask'
@@ -27,20 +24,6 @@ namespace :test do
end
end
-# Generate the RDoc documentation
-
-RDoc::Task.new { |rdoc|
- rdoc.rdoc_dir = 'doc'
- rdoc.title = "Active Resource -- Object-oriented REST services"
- rdoc.options << '-f' << 'horo'
- rdoc.options << '--main' << 'README.rdoc'
- rdoc.options << '--charset' << 'utf-8'
- rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG')
- rdoc.rdoc_files.include('lib/**/*.rb')
- rdoc.rdoc_files.exclude('lib/activeresource.rb')
-}
-
-
spec = eval(File.read('activeresource.gemspec'))
Rake::GemPackageTask.new(spec) do |p|
diff --git a/activesupport/Rakefile b/activesupport/Rakefile
index 8e2683ef89..d117ca6356 100644
--- a/activesupport/Rakefile
+++ b/activesupport/Rakefile
@@ -1,7 +1,4 @@
-gem 'rdoc', '>= 2.5.9'
-require 'rdoc'
require 'rake/testtask'
-require 'rdoc/task'
require 'rake/gempackagetask'
task :default => :test
@@ -9,6 +6,7 @@ Rake::TestTask.new do |t|
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.warning = true
+ t.verbose = true
end
namespace :test do
@@ -20,19 +18,6 @@ end
# Create compressed packages
dist_dirs = [ "lib", "test"]
-# Genereate the RDoc documentation
-
-RDoc::Task.new { |rdoc|
- rdoc.rdoc_dir = 'doc'
- rdoc.title = "Active Support -- Utility classes and standard library extensions from Rails"
- rdoc.options << '-f' << 'horo'
- rdoc.options << '--main' << 'README.rdoc'
- rdoc.options << '--charset' << 'utf-8'
- rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG')
- rdoc.rdoc_files.include('lib/active_support.rb')
- rdoc.rdoc_files.include('lib/active_support/**/*.rb')
-}
-
spec = eval(File.read('activesupport.gemspec'))
Rake::GemPackageTask.new(spec) do |p|
diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
index 0420e206af..aad4b61e16 100644
--- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
+++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
@@ -7,8 +7,6 @@ class Hash
# {:a => 1}.with_indifferent_access["a"] # => 1
#
def with_indifferent_access
- hash = ActiveSupport::HashWithIndifferentAccess.new(self)
- hash.default = self.default
- hash
+ ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default(self)
end
end
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 2b80bd214f..e6170b2daf 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -63,58 +63,78 @@ module ActiveSupport #:nodoc:
mattr_accessor :log_activity
self.log_activity = false
- class WatchStack < Array
+ # The WatchStack keeps a stack of the modules being watched as files are loaded.
+ # If a file in the process of being loaded (parent.rb) triggers the load of
+ # another file (child.rb) the stack will ensure that child.rb handles the new
+ # constants.
+ #
+ # If child.rb is being autoloaded, its constants will be added to
+ # autoloaded_constants. If it was being `require`d, they will be discarded.
+ #
+ # This is handled by walking back up the watch stack and adding the constants
+ # found by child.rb to the list of original constants in parent.rb
+ class WatchStack < Hash
+ # @watching is a stack of lists of constants being watched. For instance,
+ # if parent.rb is autoloaded, the stack will look like [[Object]]. If parent.rb
+ # then requires namespace/child.rb, the stack will look like [[Object], [Namespace]].
+
def initialize
- @mutex = Mutex.new
+ @watching = []
+ super { |h,k| h[k] = [] }
end
- def self.locked(*methods)
- methods.each { |m| class_eval "def #{m}(*) lock { super } end", __FILE__, __LINE__ }
- end
+ # return a list of new constants found since the last call to watch_modules
+ def new_constants
+ constants = []
- locked :concat, :each, :delete_if, :<<
+ # Grab the list of namespaces that we're looking for new constants under
+ @watching.last.each do |namespace|
+ # Retrieve the constants that were present under the namespace when watch_modules
+ # was originally called
+ original_constants = self[namespace].last
- def new_constants_for(frames)
- constants = []
- frames.each do |mod_name, prior_constants|
- mod = Inflector.constantize(mod_name) if Dependencies.qualified_const_defined?(mod_name)
+ mod = Inflector.constantize(namespace) if Dependencies.qualified_const_defined?(namespace)
next unless mod.is_a?(Module)
- new_constants = mod.local_constant_names - prior_constants
-
- # If we are checking for constants under, say, :Object, nested under something
- # else that is checking for constants also under :Object, make sure the
- # parent knows that we have found, and taken care of, the constant.
- #
- # In particular, this means that since Kernel.require discards the constants
- # it finds, parents will be notified that about those constants, and not
- # consider them "new". As a result, they will not be added to the
- # autoloaded_constants list.
- each do |key, value|
- value.concat(new_constants) if key == mod_name
+ # Get a list of the constants that were added
+ new_constants = mod.local_constant_names - original_constants
+
+ # self[namespace] returns an Array of the constants that are being evaluated
+ # for that namespace. For instance, if parent.rb requires child.rb, the first
+ # element of self[Object] will be an Array of the constants that were present
+ # before parent.rb was required. The second element will be an Array of the
+ # constants that were present before child.rb was required.
+ self[namespace].each do |namespace_constants|
+ namespace_constants.concat(new_constants)
end
+ # Normalize the list of new constants, and add them to the list we will return
new_constants.each do |suffix|
- constants << ([mod_name, suffix] - ["Object"]).join("::")
+ constants << ([namespace, suffix] - ["Object"]).join("::")
end
end
constants
+ ensure
+ # A call to new_constants is always called after a call to watch_modules
+ pop_modules(@watching.pop)
end
# Add a set of modules to the watch stack, remembering the initial constants
- def add_modules(modules)
- list = modules.map do |desc|
- name = Dependencies.to_constant_name(desc)
- consts = Dependencies.qualified_const_defined?(name) ?
- Inflector.constantize(name).local_constant_names : []
- [name, consts]
+ def watch_namespaces(namespaces)
+ watching = []
+ namespaces.map do |namespace|
+ module_name = Dependencies.to_constant_name(namespace)
+ original_constants = Dependencies.qualified_const_defined?(module_name) ?
+ Inflector.constantize(module_name).local_constant_names : []
+
+ watching << module_name
+ self[module_name] << original_constants
end
- concat(list)
- list
+ @watching << watching
end
- def lock
- @mutex.synchronize { yield self }
+ def pop_modules(modules)
+ modules.each { |mod| self[mod].pop }
end
end
@@ -563,14 +583,15 @@ module ActiveSupport #:nodoc:
# and will be removed immediately.
def new_constants_in(*descs)
log_call(*descs)
- watch_frames = constant_watch_stack.add_modules(descs)
+ constant_watch_stack.watch_namespaces(descs)
aborting = true
+
begin
yield # Now yield to the code that is to define new constants.
aborting = false
ensure
- new_constants = constant_watch_stack.new_constants_for(watch_frames)
+ new_constants = constant_watch_stack.new_constants
log "New constants: #{new_constants * ', '}"
return new_constants unless aborting
@@ -580,9 +601,6 @@ module ActiveSupport #:nodoc:
end
return []
- ensure
- # Remove the stack frames that we added.
- watch_frames.each {|f| constant_watch_stack.delete(f) } if watch_frames.present?
end
class LoadingModule #:nodoc:
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
index eec5d4cf47..e8215bc566 100644
--- a/activesupport/lib/active_support/hash_with_indifferent_access.rb
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -1,4 +1,3 @@
-require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/keys'
# This class has dubious semantics and we only have it so that
@@ -28,6 +27,12 @@ module ActiveSupport
end
end
+ def self.new_from_hash_copying_default(hash)
+ ActiveSupport::HashWithIndifferentAccess.new(hash).tap do |new_hash|
+ new_hash.default = hash.default
+ end
+ end
+
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
alias_method :regular_update, :update unless method_defined?(:regular_update)
@@ -102,7 +107,7 @@ module ActiveSupport
# Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
# This overloaded definition prevents returning a regular hash, if reverse_merge is called on a HashWithDifferentAccess.
def reverse_merge(other_hash)
- super other_hash.with_indifferent_access
+ super self.class.new_from_hash_copying_default(other_hash)
end
def reverse_merge!(other_hash)
@@ -133,9 +138,9 @@ module ActiveSupport
def convert_value(value)
case value
when Hash
- value.with_indifferent_access
+ self.class.new_from_hash_copying_default(value)
when Array
- value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
+ value.collect { |e| e.is_a?(Hash) ? self.class.new_from_hash_copying_default(e) : e }
else
value
end
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index f98d823f00..77b885dc3d 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -576,14 +576,14 @@ class DependenciesTest < Test::Unit::TestCase
def test_new_contants_in_without_constants
assert_equal [], (ActiveSupport::Dependencies.new_constants_in(Object) { })
- assert ActiveSupport::Dependencies.constant_watch_stack.empty?
+ assert ActiveSupport::Dependencies.constant_watch_stack.all? {|k,v| v.empty? }
end
def test_new_constants_in_with_a_single_constant
assert_equal ["Hello"], ActiveSupport::Dependencies.new_constants_in(Object) {
Object.const_set :Hello, 10
}.map(&:to_s)
- assert ActiveSupport::Dependencies.constant_watch_stack.empty?
+ assert ActiveSupport::Dependencies.constant_watch_stack.all? {|k,v| v.empty? }
ensure
Object.class_eval { remove_const :Hello }
end
@@ -600,7 +600,7 @@ class DependenciesTest < Test::Unit::TestCase
end
assert_equal ["OuterAfter", "OuterBefore"], outer.sort.map(&:to_s)
- assert ActiveSupport::Dependencies.constant_watch_stack.empty?
+ assert ActiveSupport::Dependencies.constant_watch_stack.all? {|k,v| v.empty? }
ensure
%w(OuterBefore Inner OuterAfter).each do |name|
Object.class_eval { remove_const name if const_defined?(name) }
@@ -621,7 +621,7 @@ class DependenciesTest < Test::Unit::TestCase
M.const_set :OuterAfter, 30
end
assert_equal ["M::OuterAfter", "M::OuterBefore"], outer.sort
- assert ActiveSupport::Dependencies.constant_watch_stack.empty?
+ assert ActiveSupport::Dependencies.constant_watch_stack.all? {|k,v| v.empty? }
ensure
Object.class_eval { remove_const :M }
end
@@ -639,7 +639,7 @@ class DependenciesTest < Test::Unit::TestCase
M.const_set :OuterAfter, 30
end
assert_equal ["M::OuterAfter", "M::OuterBefore"], outer.sort
- assert ActiveSupport::Dependencies.constant_watch_stack.empty?
+ assert ActiveSupport::Dependencies.constant_watch_stack.all? {|k,v| v.empty? }
ensure
Object.class_eval { remove_const :M }
end
diff --git a/ci/ci_build.rb b/ci/ci_build.rb
index e75f91cd3b..3591e45fcf 100755
--- a/ci/ci_build.rb
+++ b/ci/ci_build.rb
@@ -27,7 +27,7 @@ cd root_dir do
puts
puts "[CruiseControl] Bundling RubyGems"
puts
- build_results[:bundle] = system 'rm -rf ~/.bundle; env CI=1 bundle update'
+ build_results[:bundle] = system 'bundle update'
end
cd "#{root_dir}/activesupport" do
diff --git a/railties/Rakefile b/railties/Rakefile
index 8e78d2ff4a..9ef6637c1e 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -1,8 +1,5 @@
-gem 'rdoc', '>= 2.5.9'
-require 'rdoc'
require 'rake'
require 'rake/testtask'
-require 'rdoc/task'
require 'rake/gempackagetask'
require 'date'
@@ -58,19 +55,6 @@ task :validate_guides do
ruby "guides/w3c_validator.rb"
end
-# Generate documentation ------------------------------------------------------------------
-
-RDoc::Task.new { |rdoc|
- rdoc.rdoc_dir = 'doc'
- rdoc.title = "Railties -- Gluing the Engine to the Rails"
- rdoc.options << '-f' << 'horo'
- rdoc.options << '--main' << 'README.rdoc'
- rdoc.options << '--charset' << 'utf-8'
- rdoc.rdoc_files.include('README.rdoc', 'CHANGELOG')
- rdoc.rdoc_files.include('lib/**/*.rb')
- rdoc.rdoc_files.exclude('lib/rails/generators/**/templates/*')
-}
-
# Generate GEM ----------------------------------------------------------------------------
spec = eval(File.read('railties.gemspec'))
diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile
index 4e257d2e00..0a2f60c30a 100644
--- a/railties/guides/source/initialization.textile
+++ b/railties/guides/source/initialization.textile
@@ -150,7 +150,7 @@ Here the only two gems we need are +rails+ and +sqlite3-ruby+, so it seems. This
* nokogiri-1.4.3.1.gem
* polyglot-0.3.1.gem
* rack-1.2.1.gem
-* rack-mount-0.6.9.gem
+* rack-mount-0.6.10.gem
* rack-test-0.5.4.gem
* rails-3.0.0.beta4.gem
* railties-3.0.0.beta4.gem
@@ -160,7 +160,7 @@ Here the only two gems we need are +rails+ and +sqlite3-ruby+, so it seems. This
* text-hyphen-1.0.0.gem
* thor-0.13.7.gem
* treetop-1.4.8.gem
-* tzinfo-0.3.22.gem
+* tzinfo-0.3.23.gem
TODO: Prettify when it becomes more stable.