diff options
46 files changed, 495 insertions, 177 deletions
diff --git a/.gitignore b/.gitignore index ab0950d7dd..aa14cee911 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,23 @@ -pkg -.bundle -Gemfile.lock +# Don't put *.swp, *.bak, etc here; those belong in a global ~/.gitignore. +# Check out http://help.github.com/ignore-files/ for how to set that up. + debug.log -doc/rdoc -activemodel/doc -activeresource/doc -activerecord/doc -activerecord/sqlnet.log -actionpack/doc -actionmailer/doc -activesupport/doc -activesupport/test/tmp -activemodel/test/fixtures/fixture_database.sqlite3 -actionpack/test/tmp -activesupport/test/fixtures/isolation_test -dist -railties/test/500.html -railties/test/fixtures/tmp -railties/test/initializer/root/log -railties/doc -railties/guides/output -railties/tmp -.rvmrc -.rbenv-version -RDOC_MAIN.rdoc +/.bundle +/.rbenv-version +/.rvmrc +/Gemfile.lock +/pkg +/dist +/doc/rdoc +/*/doc +/*/test/tmp +/activerecord/sqlnet.log +/activemodel/test/fixtures/fixture_database.sqlite3 +/activesupport/test/fixtures/isolation_test +/railties/test/500.html +/railties/test/fixtures/tmp +/railties/test/initializer/root/log +/railties/doc +/railties/guides/output +/railties/tmp +/RDOC_MAIN.rdoc diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index e7886facb9..a7a47bf930 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.2.0 (unreleased)* +* Responders now return 204 No Content for API requests without a response body (as in the new scaffold) [José Valim] + * Added ActionDispatch::RequestId middleware that'll make a unique X-Request-Id header available to the response and enables the ActionDispatch::Request#uuid method. This makes it easy to trace requests from end-to-end in the stack and to identify individual requests in mixed logs like Syslog [DHH] * Limit the number of options for select_year to 1000. diff --git a/actionpack/RUNNING_UNIT_TESTS b/actionpack/RUNNING_UNIT_TESTS index 1e3ba7abe7..1b29abd2d1 100644 --- a/actionpack/RUNNING_UNIT_TESTS +++ b/actionpack/RUNNING_UNIT_TESTS @@ -18,7 +18,7 @@ which can be further narrowed down to one test: == Dependency on Active Record and database setup -Test cases in the test/controller/active_record/ directory depend on having +Test cases in the test/active_record/ directory depend on having activerecord and sqlite installed. If Active Record is not in actionpack/../activerecord directory, or the sqlite rubygem is not installed, these tests are skipped. diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb index c7827309dd..b932302a60 100644 --- a/actionpack/lib/action_controller/metal/responder.rb +++ b/actionpack/lib/action_controller/metal/responder.rb @@ -202,10 +202,8 @@ module ActionController #:nodoc: display resource elsif post? display resource, :status => :created, :location => api_location - elsif has_empty_resource_definition? - display empty_resource, :status => :ok else - head :ok + head :no_content end end @@ -269,24 +267,6 @@ module ActionController #:nodoc: @action ||= ACTIONS_FOR_VERBS[request.request_method_symbol] end - # Check whether resource needs a specific definition of empty resource to be valid - # - def has_empty_resource_definition? - respond_to?("empty_#{format}_resource") - end - - # Delegate to proper empty resource method - # - def empty_resource - send("empty_#{format}_resource") - end - - # Return a valid empty JSON resource - # - def empty_json_resource - "{}" - end - def resource_errors respond_to?("#{format}_resource_errors") ? send("#{format}_resource_errors") : resource.errors end diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index d636702111..f895cad058 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -579,7 +579,12 @@ module ActionView def to_select_tag(choices, options, html_options) selected_value = options.has_key?(:selected) ? options[:selected] : value(object) - if !choices.empty? && Array === choices.first + # Grouped choices look like this: + # + # [nil, []] + # { nil => [] } + # + if !choices.empty? && Array === choices.first.last option_tags = grouped_options_for_select(choices, :selected => selected_value, :disabled => options[:disabled]) else option_tags = options_for_select(choices, :selected => selected_value, :disabled => options[:disabled]) diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 13b9dc8553..1424a3584d 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -582,7 +582,7 @@ module ActionView # # ==== Examples # number_field_tag 'quantity', nil, :in => 1...10 - # => <input id="quantity" name="quantity" min="1" max="9" /> + # => <input id="quantity" name="quantity" min="1" max="9" type="number" /> def number_field_tag(name, value = nil, options = {}) options = options.stringify_keys options["type"] ||= "number" diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index 2aa73f1650..76a8c89e60 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -656,7 +656,9 @@ class RespondWithControllerTest < ActionController::TestCase @request.accept = "application/json" get :using_hash_resource assert_equal "application/json", @response.content_type - assert_equal %Q[{"result":{"name":"david","id":13}}], @response.body + assert @response.body.include?("result") + assert @response.body.include?('"name":"david"') + assert @response.body.include?('"id":13') end def test_using_hash_resource_with_post @@ -794,21 +796,21 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_for_put_with_xml_yields_ok_on_success + def test_using_resource_for_put_with_xml_yields_no_content_on_success @request.accept = "application/xml" put :using_resource assert_equal "application/xml", @response.content_type - assert_equal 200, @response.status + assert_equal 204, @response.status assert_equal " ", @response.body end - def test_using_resource_for_put_with_json_yields_ok_on_success + def test_using_resource_for_put_with_json_yields_no_content_on_success Customer.any_instance.stubs(:to_json).returns('{"name": "David"}') @request.accept = "application/json" put :using_resource assert_equal "application/json", @response.content_type - assert_equal 200, @response.status - assert_equal "{}", @response.body + assert_equal 204, @response.status + assert_equal " ", @response.body end def test_using_resource_for_put_with_xml_yields_unprocessable_entity_on_failure @@ -844,23 +846,23 @@ class RespondWithControllerTest < ActionController::TestCase end end - def test_using_resource_for_delete_with_xml_yields_ok_on_success + def test_using_resource_for_delete_with_xml_yields_no_content_on_success Customer.any_instance.stubs(:destroyed?).returns(true) @request.accept = "application/xml" delete :using_resource assert_equal "application/xml", @response.content_type - assert_equal 200, @response.status + assert_equal 204, @response.status assert_equal " ", @response.body end - def test_using_resource_for_delete_with_json_yields_ok_on_success + def test_using_resource_for_delete_with_json_yields_no_content_on_success Customer.any_instance.stubs(:to_json).returns('{"name": "David"}') Customer.any_instance.stubs(:destroyed?).returns(true) @request.accept = "application/json" delete :using_resource assert_equal "application/json", @response.content_type - assert_equal 200, @response.status - assert_equal "{}", @response.body + assert_equal 204, @response.status + assert_equal " ", @response.body end def test_using_resource_for_delete_with_html_redirects_on_failure diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index d3e0cc41a9..469718e1bd 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -596,6 +596,15 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_list_of_lists + @post = Post.new + @post.category = "" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\">Please select</option>\n<option value=\"\"></option>\n<option value=\"number\">Number</option>\n<option value=\"text\">Text</option>\n<option value=\"boolean\">Yes/No</option></select>", + select("post", "category", [["Number", "number"], ["Text", "text"], ["Yes/No", "boolean"]], :prompt => true, :include_blank => true) + ) + end + def test_select_with_selected_value @post = Post.new @post.category = "<mus>" diff --git a/actionpack/test/template/html-scanner/tag_node_test.rb b/actionpack/test/template/html-scanner/tag_node_test.rb index 0d87f1bd42..3b72243e7d 100644 --- a/actionpack/test/template/html-scanner/tag_node_test.rb +++ b/actionpack/test/template/html-scanner/tag_node_test.rb @@ -55,7 +55,12 @@ class TagNodeTest < Test::Unit::TestCase def test_to_s node = tag("<a b=c d='f' g=\"h 'i'\" />") - assert_equal %(<a b="c" d="f" g="h 'i'" />), node.to_s + node = node.to_s + assert node.include?('a') + assert node.include?('b="c"') + assert node.include?('d="f"') + assert node.include?('g="h') + assert node.include?('i') end def test_tag diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 0ef3239f83..77659918f7 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -429,7 +429,7 @@ class LazyViewRenderTest < ActiveSupport::TestCase if '1.9'.respond_to?(:force_encoding) def test_render_utf8_template_with_magic_comment with_external_encoding Encoding::ASCII_8BIT do - result = @view.render(:file => "test/utf8_magic.html", :layouts => "layouts/yield") + result = @view.render(:file => "test/utf8_magic", :formats => [:html], :layouts => "layouts/yield") assert_equal Encoding::UTF_8, result.encoding assert_equal "\nРусский \nтекст\n\nUTF-8\nUTF-8\nUTF-8\n", result end @@ -437,7 +437,7 @@ class LazyViewRenderTest < ActiveSupport::TestCase def test_render_utf8_template_with_default_external_encoding with_external_encoding Encoding::UTF_8 do - result = @view.render(:file => "test/utf8.html", :layouts => "layouts/yield") + result = @view.render(:file => "test/utf8", :formats => [:html], :layouts => "layouts/yield") assert_equal Encoding::UTF_8, result.encoding assert_equal "Русский текст\n\nUTF-8\nUTF-8\nUTF-8\n", result end @@ -446,7 +446,7 @@ class LazyViewRenderTest < ActiveSupport::TestCase def test_render_utf8_template_with_incompatible_external_encoding with_external_encoding Encoding::SHIFT_JIS do begin - @view.render(:file => "test/utf8.html", :layouts => "layouts/yield") + @view.render(:file => "test/utf8", :formats => [:html], :layouts => "layouts/yield") flunk 'Should have raised incompatible encoding error' rescue ActionView::Template::Error => error assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message @@ -457,7 +457,7 @@ class LazyViewRenderTest < ActiveSupport::TestCase def test_render_utf8_template_with_partial_with_incompatible_encoding with_external_encoding Encoding::SHIFT_JIS do begin - @view.render(:file => "test/utf8_magic_with_bare_partial.html", :layouts => "layouts/yield") + @view.render(:file => "test/utf8_magic_with_bare_partial", :formats => [:html], :layouts => "layouts/yield") flunk 'Should have raised incompatible encoding error' rescue ActionView::Template::Error => error assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index 0e444738ba..35ec98c822 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -57,7 +57,7 @@ module ActiveModel #:nodoc: # To add behavior to the initialize method, use the following signature: # # class MyValidator < ActiveModel::Validator - # def initialize(record, options) + # def initialize(options) # super # @my_custom_field = options[:field_name] || :first_name # end diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 46076dac61..798d875034 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,8 @@ *Rails 3.2.0 (unreleased)* +* In development mode the db:drop task also drops the test database. For symmetry with + the db:create task. [Dmitriy Kiriyenko] + * Added ActiveRecord::Base.store for declaring simple single-column key/value stores [DHH] class User < ActiveRecord::Base diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 3d084bb178..e8a43e7bce 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -922,12 +922,14 @@ module ActiveRecord # Example: # rename_table('octopuses', 'octopi') def rename_table(name, new_name) + clear_cache! execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}" end # Adds a new column to the named table. # See TableDefinition#column for details of the options you can use. def add_column(table_name, column_name, type, options = {}) + clear_cache! add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" add_column_options!(add_column_sql, options) @@ -936,6 +938,7 @@ module ActiveRecord # Changes the column of a table. def change_column(table_name, column_name, type, options = {}) + clear_cache! quoted_table_name = quote_table_name(table_name) execute "ALTER TABLE #{quoted_table_name} ALTER COLUMN #{quote_column_name(column_name)} TYPE #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" @@ -946,10 +949,12 @@ module ActiveRecord # Changes the default value of a table column. def change_column_default(table_name, column_name, default) + clear_cache! execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DEFAULT #{quote(default)}" end def change_column_null(table_name, column_name, null, default = nil) + clear_cache! unless null || default.nil? execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL") end @@ -958,6 +963,7 @@ module ActiveRecord # Renames a column in a table. def rename_column(table_name, column_name, new_column_name) + clear_cache! execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}" end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 4fb19b14ea..44848b3391 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -37,11 +37,7 @@ db_namespace = namespace :db do desc 'Create the database from config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)' task :create => :load_config do - # Make the test database at the same time as the development one, if it exists - if Rails.env.development? && ActiveRecord::Base.configurations['test'] - create_database(ActiveRecord::Base.configurations['test']) - end - create_database(ActiveRecord::Base.configurations[Rails.env]) + configs_for_environment.each { |config| create_database(config) } end def mysql_creation_options(config) @@ -138,12 +134,7 @@ db_namespace = namespace :db do desc 'Drops the database for the current Rails.env (use db:drop:all to drop all databases)' task :drop => :load_config do - config = ActiveRecord::Base.configurations[Rails.env || 'development'] - begin - drop_database(config) - rescue Exception => e - $stderr.puts "Couldn't drop #{config['database']} : #{e.inspect}" - end + configs_for_environment.each { |config| drop_database_and_rescue(config) } end def local_database?(config, &block) @@ -548,6 +539,20 @@ def drop_database(config) end end +def drop_database_and_rescue(config) + begin + drop_database(config) + rescue Exception => e + $stderr.puts "Couldn't drop #{config['database']} : #{e.inspect}" + end +end + +def configs_for_environment + environments = [Rails.env] + environments << 'test' if Rails.env.development? + ActiveRecord::Base.configurations.values_at(*environments).compact.reject { |config| config['database'].blank? } +end + def session_table_name ActiveRecord::SessionStore::Session.table_name end diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb index d5910df891..8cc84f81d0 100644 --- a/activerecord/lib/active_record/store.rb +++ b/activerecord/lib/active_record/store.rb @@ -37,6 +37,7 @@ module ActiveRecord Array(keys).flatten.each do |key| define_method("#{key}=") do |value| send(store_attribute)[key] = value + send("#{store_attribute}_will_change!") end define_method(key) do diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 4d5e469a7f..0c760e9850 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -33,7 +33,7 @@ module ActiveRecord extend ActiveSupport::Concern included do - class_attribute :record_timestamps, :instance_writer => false + class_attribute :record_timestamps self.record_timestamps = true end diff --git a/activerecord/test/cases/mass_assignment_security_test.rb b/activerecord/test/cases/mass_assignment_security_test.rb index ef35f3341e..9fff50edcb 100644 --- a/activerecord/test/cases/mass_assignment_security_test.rb +++ b/activerecord/test/cases/mass_assignment_security_test.rb @@ -231,7 +231,9 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase def test_protection_against_class_attribute_writers [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, - :default_timezone, :schema_format, :lock_optimistically, :record_timestamps].each do |method| + :default_timezone, :schema_format, :lock_optimistically, :timestamped_migrations, :default_scopes, + :connection_handler, :nested_attributes_options, :_attr_readonly, :attribute_types_cached_by_default, + :attribute_method_matchers, :time_zone_aware_attributes, :skip_time_zone_conversion_for_attributes].each do |method| assert_respond_to Task, method assert_respond_to Task, "#{method}=" assert_respond_to Task.new, method diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index b2429d631f..9554386dcf 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -170,6 +170,18 @@ end class QueryCacheExpiryTest < ActiveRecord::TestCase fixtures :tasks, :posts, :categories, :categories_posts + def test_cache_gets_cleared_after_migration + # warm the cache + Post.find(1) + + # change the column definition + Post.connection.change_column :posts, :title, :string, :limit => 80 + assert_nothing_raised { Post.find(1) } + + # restore the old definition + Post.connection.change_column :posts, :title, :string + end + def test_find Task.connection.expects(:clear_query_cache).times(1) diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb index fb77220875..074fd39e65 100644 --- a/activerecord/test/cases/store_test.rb +++ b/activerecord/test/cases/store_test.rb @@ -26,4 +26,9 @@ class StoreTest < ActiveRecord::TestCase assert 'graeters', @john.reload.settings[:icecream] end + + test "updating the store will mark it as changed" do + @john.color = 'red' + assert @john.settings_changed? + end end diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb index 4445a12e1d..447aa29ffe 100644 --- a/activerecord/test/cases/timestamp_test.rb +++ b/activerecord/test/cases/timestamp_test.rb @@ -60,6 +60,16 @@ class TimestampTest < ActiveRecord::TestCase Developer.record_timestamps = true end + def test_saving_when_instance_record_timestamps_is_false_doesnt_update_its_timestamp + @developer.record_timestamps = false + assert Developer.record_timestamps + + @developer.name = "John Smith" + @developer.save! + + assert_equal @previously_updated_at, @developer.updated_at + end + def test_touching_an_attribute_updates_timestamp previously_created_at = @developer.created_at @developer.touch(:created_at) diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index d3a838cff0..8609198641 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,11 @@ *Rails 3.2.0 (unreleased)* +* Module#qualified_const_(defined?|get|set) are analogous to the corresponding methods + in the standard API, but accept qualified constant names. [fxn] + +* Added inflection #deconstantize which complements #demodulize. This inflection + removes the righmost segment in a qualified constant name. [fxn] + * Added ActiveSupport:TaggedLogging that can wrap any standard Logger class to provide tagging capabilities [DHH] Logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT)) diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 95d936b32f..8b45efaf2a 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -16,8 +16,6 @@ module ActiveSupport autoload :FileStore, 'active_support/cache/file_store' autoload :MemoryStore, 'active_support/cache/memory_store' autoload :MemCacheStore, 'active_support/cache/mem_cache_store' - autoload :SynchronizedMemoryStore, 'active_support/cache/synchronized_memory_store' - autoload :CompressedMemCacheStore, 'active_support/cache/compressed_mem_cache_store' # These options mean something to all cache implementations. Individual cache # implementations may support additional options. @@ -232,7 +230,7 @@ module ActiveSupport # <tt>:race_condition_ttl</tt> does not play any role. # # # Set all values to expire after one minute. - # cache = ActiveSupport::Cache::MemoryCache.new(:expires_in => 1.minute) + # cache = ActiveSupport::Cache::MemoryStore.new(:expires_in => 1.minute) # # cache.write("foo", "original value") # val_1 = nil @@ -561,7 +559,7 @@ module ActiveSupport @value = nil else @value = Marshal.dump(value) - if should_compress?(value, options) + if should_compress?(@value, options) @value = Zlib::Deflate.deflate(@value) @compressed = true end @@ -615,13 +613,10 @@ module ActiveSupport end private - def should_compress?(value, options) - if options[:compress] && value - unless value.is_a?(Numeric) - compress_threshold = options[:compress_threshold] || DEFAULT_COMPRESS_LIMIT - serialized_value = value.is_a?(String) ? value : Marshal.dump(value) - return true if serialized_value.size >= compress_threshold - end + def should_compress?(serialized_value, options) + if options[:compress] + compress_threshold = options[:compress_threshold] || DEFAULT_COMPRESS_LIMIT + return true if serialized_value.size >= compress_threshold end false end diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index bc5d94b5a7..b431041b76 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -26,26 +26,11 @@ module ActiveSupport FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)}) end - # Cleanup the cache by removing old entries. By default this will delete entries - # that haven't been accessed in one day. You can change this behavior by passing - # in a +not_accessed_in+ option. Any entry not accessed in that number of seconds - # in the past will be deleted. Alternatively, you can pass in +:expired_only+ with - # +true+ to only delete expired entries. def cleanup(options = nil) options = merged_options(options) - expired_only = options[:expired_only] - timestamp = Time.now - (options[:not_accessed_in] || 1.day.to_i) - search_dir(cache_path) do |fname| - if expired_only - key = file_path_key(fname) - entry = read_entry(key, options) - delete_entry(key, options) if entry && entry.expired? - else - if File.atime(fname) <= timestamp - key = file_path_key(fname) - delete_entry(key, options) - end - end + each_key(options) do |key| + entry = read_entry(key, options) + delete_entry(key, options) if entry && entry.expired? end end diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb index 9fed346b7c..f399fce410 100644 --- a/activesupport/lib/active_support/core_ext/module.rb +++ b/activesupport/lib/active_support/core_ext/module.rb @@ -8,4 +8,5 @@ require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/module/synchronization' require 'active_support/core_ext/module/deprecation' require 'active_support/core_ext/module/remove_method' -require 'active_support/core_ext/module/method_names'
\ No newline at end of file +require 'active_support/core_ext/module/method_names' +require 'active_support/core_ext/module/qualified_const'
\ No newline at end of file diff --git a/activesupport/lib/active_support/core_ext/module/qualified_const.rb b/activesupport/lib/active_support/core_ext/module/qualified_const.rb new file mode 100644 index 0000000000..d1a0ee2f83 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/module/qualified_const.rb @@ -0,0 +1,64 @@ +require 'active_support/core_ext/string/inflections' + +#-- +# Allows code reuse in the methods below without polluting Module. +#++ +module QualifiedConstUtils + def self.raise_if_absolute(path) + raise NameError, "wrong constant name #$&" if path =~ /\A::[^:]+/ + end + + def self.names(path) + path.split('::') + end +end + +## +# Extends the API for constants to be able to deal with qualified names. Arguments +# are assumed to be relative to the receiver. +# +#-- +# Qualified names are required to be relative because we are extending existing +# methods that expect constant names, ie, relative paths of length 1. For example, +# Object.const_get("::String") raises NameError and so does qualified_const_get. +#++ +class Module + if method(:const_defined?).arity == 1 + def qualified_const_defined?(path) + QualifiedConstUtils.raise_if_absolute(path) + + QualifiedConstUtils.names(path).inject(self) do |mod, name| + return unless mod.const_defined?(name) + mod.const_get(name) + end + return true + end + else + def qualified_const_defined?(path, search_parents=true) + QualifiedConstUtils.raise_if_absolute(path) + + QualifiedConstUtils.names(path).inject(self) do |mod, name| + return unless mod.const_defined?(name, search_parents) + mod.const_get(name) + end + return true + end + end + + def qualified_const_get(path) + QualifiedConstUtils.raise_if_absolute(path) + + QualifiedConstUtils.names(path).inject(self) do |mod, name| + mod.const_get(name) + end + end + + def qualified_const_set(path, value) + QualifiedConstUtils.raise_if_absolute(path) + + const_name = path.demodulize + mod_name = path.deconstantize + mod = mod_name.empty? ? self : qualified_const_get(mod_name) + mod.const_set(const_name, value) + end +end diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb index fd91b3cacb..1e57b586d9 100644 --- a/activesupport/lib/active_support/core_ext/string/inflections.rb +++ b/activesupport/lib/active_support/core_ext/string/inflections.rb @@ -117,10 +117,25 @@ class String # # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections" # "Inflections".demodulize # => "Inflections" + # + # See also +deconstantize+. def demodulize ActiveSupport::Inflector.demodulize(self) end + # Removes the rightmost segment from the constant expression in the string. + # + # "Net::HTTP".deconstantize # => "Net" + # "::Net::HTTP".deconstantize # => "::Net" + # "String".deconstantize # => "" + # "::String".deconstantize # => "" + # "".deconstantize # => "" + # + # See also +demodulize+. + def deconstantize + ActiveSupport::Inflector.deconstantize(self) + end + # Replaces special characters in a string so that it may be used as part of a 'pretty' URL. # # ==== Examples diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index c072a8e646..b3ac271778 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -5,6 +5,7 @@ require 'active_support/core_ext/module/aliasing' require 'active_support/core_ext/module/attribute_accessors' require 'active_support/core_ext/module/introspection' require 'active_support/core_ext/module/anonymous' +require 'active_support/core_ext/module/qualified_const' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/load_error' require 'active_support/core_ext/name_error' @@ -357,12 +358,13 @@ module ActiveSupport #:nodoc: end # Is the provided constant path defined? - def qualified_const_defined?(path) - names = path.sub(/^::/, '').to_s.split('::') - - names.inject(Object) do |mod, name| - return false unless local_const_defined?(mod, name) - mod.const_get name + if Module.method(:const_defined?).arity == 1 + def qualified_const_defined?(path) + Object.qualified_const_defined?(path.sub(/^::/, '')) + end + else + def qualified_const_defined?(path) + Object.qualified_const_defined?(path.sub(/^::/, ''), false) end end diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 934529d496..e76ee60dd7 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -160,13 +160,32 @@ module ActiveSupport underscored_word.gsub(/_/, '-') end - # Removes the module part from the expression in the string. + # Removes the module part from the expression in the string: # - # Examples: # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections" # "Inflections".demodulize # => "Inflections" - def demodulize(class_name_in_module) - class_name_in_module.to_s.gsub(/^.*::/, '') + # + # See also +deconstantize+. + def demodulize(path) + path = path.to_s + if i = path.rindex('::') + path[(i+2)..-1] + else + path + end + end + + # Removes the rightmost segment from the constant expression in the string: + # + # "Net::HTTP".deconstantize # => "Net" + # "::Net::HTTP".deconstantize # => "::Net" + # "String".deconstantize # => "" + # "::String".deconstantize # => "" + # "".deconstantize # => "" + # + # See also +demodulize+. + def deconstantize(path) + path.to_s[0...(path.rindex('::') || 0)] # implementation based on the one in facets' Module#spacename end # Creates a foreign key name from a class name. diff --git a/activesupport/test/buffered_logger_test.rb b/activesupport/test/buffered_logger_test.rb index 8699862d9e..386006677b 100644 --- a/activesupport/test/buffered_logger_test.rb +++ b/activesupport/test/buffered_logger_test.rb @@ -233,7 +233,7 @@ class BufferedLoggerTest < Test::Unit::TestCase end keep_running = true - b = Thread.new do + Thread.new do @logger.info("b") while keep_running sleep(0.001) diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index 1b2f6d061c..cb5362525f 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -557,29 +557,6 @@ class FileStoreTest < ActiveSupport::TestCase key = @cache_with_pathname.send(:key_file_path, "views/index?id=1") assert_equal "views/index?id=1", @cache_with_pathname.send(:file_path_key, key) end - - def test_cleanup_with_not_accessed_in - @cache.write(1, "aaaaaaaaaa") - @cache.write(2, "bbbbbbbbbb") - @cache.write(3, "cccccccccc") - sleep(2) - @cache.read(2) - @cache.cleanup(:not_accessed_in => 1) - assert_equal false, @cache.exist?(1) - assert_equal true, @cache.exist?(2) - assert_equal false, @cache.exist?(3) - end - - def test_cleanup_with_expired_only - @cache.write(1, "aaaaaaaaaa", :expires_in => 0.001) - @cache.write(2, "bbbbbbbbbb") - @cache.write(3, "cccccccccc", :expires_in => 0.001) - sleep(0.002) - @cache.cleanup(:expired_only => 0.001) - assert_equal false, @cache.exist?(1) - assert_equal true, @cache.exist?(2) - assert_equal false, @cache.exist?(3) - end # Because file systems have a maximum filename size, filenames > max size should be split in to directories # If filename is 'AAAAB', where max size is 4, the returned path should be AAAA/B @@ -669,17 +646,6 @@ class MemoryStoreTest < ActiveSupport::TestCase assert_equal true, @cache.exist?(2) assert_equal false, @cache.exist?(1) end - - def test_cleanup_removes_expired_entries - @cache.write(1, "aaaaaaaaaa", :expires_in => 0.001) - @cache.write(2, "bbbbbbbbbb") - @cache.write(3, "cccccccccc", :expires_in => 0.001) - sleep(0.002) - @cache.cleanup - assert_equal false, @cache.exist?(1) - assert_equal true, @cache.exist?(2) - assert_equal false, @cache.exist?(3) - end end uses_memcached 'memcached backed store' do diff --git a/activesupport/test/core_ext/module/qualified_const_test.rb b/activesupport/test/core_ext/module/qualified_const_test.rb new file mode 100644 index 0000000000..8af0b9a023 --- /dev/null +++ b/activesupport/test/core_ext/module/qualified_const_test.rb @@ -0,0 +1,94 @@ +require 'abstract_unit' +require 'active_support/core_ext/module/qualified_const' + +module QualifiedConstTestMod + X = false + + module M + X = 1 + + class C + X = 2 + end + end + + module N + include M + end +end + +class QualifiedConstTest < ActiveSupport::TestCase + test "Object.qualified_const_defined?" do + assert Object.qualified_const_defined?("QualifiedConstTestMod") + assert !Object.qualified_const_defined?("NonExistingQualifiedConstTestMod") + + assert Object.qualified_const_defined?("QualifiedConstTestMod::X") + assert !Object.qualified_const_defined?("QualifiedConstTestMod::Y") + + assert Object.qualified_const_defined?("QualifiedConstTestMod::M::X") + assert !Object.qualified_const_defined?("QualifiedConstTestMod::M::Y") + + if Module.method(:const_defined?).arity == 1 + assert !Object.qualified_const_defined?("QualifiedConstTestMod::N::X") + else + assert Object.qualified_const_defined?("QualifiedConstTestMod::N::X") + assert !Object.qualified_const_defined?("QualifiedConstTestMod::N::X", false) + assert Object.qualified_const_defined?("QualifiedConstTestMod::N::X", true) + end + end + + test "mod.qualified_const_defined?" do + assert QualifiedConstTestMod.qualified_const_defined?("M") + assert !QualifiedConstTestMod.qualified_const_defined?("NonExistingM") + + assert QualifiedConstTestMod.qualified_const_defined?("M::X") + assert !QualifiedConstTestMod.qualified_const_defined?("M::Y") + + assert QualifiedConstTestMod.qualified_const_defined?("M::C::X") + assert !QualifiedConstTestMod.qualified_const_defined?("M::C::Y") + + if Module.method(:const_defined?).arity == 1 + assert !QualifiedConstTestMod.qualified_const_defined?("QualifiedConstTestMod::N::X") + else + assert QualifiedConstTestMod.qualified_const_defined?("N::X") + assert !QualifiedConstTestMod.qualified_const_defined?("N::X", false) + assert QualifiedConstTestMod.qualified_const_defined?("N::X", true) + end + end + + test "qualified_const_get" do + assert_equal false, Object.qualified_const_get("QualifiedConstTestMod::X") + assert_equal false, QualifiedConstTestMod.qualified_const_get("X") + assert_equal 1, QualifiedConstTestMod.qualified_const_get("M::X") + assert_equal 1, QualifiedConstTestMod.qualified_const_get("N::X") + assert_equal 2, QualifiedConstTestMod.qualified_const_get("M::C::X") + + assert_raise(NameError) { QualifiedConstTestMod.qualified_const_get("M::C::Y")} + end + + test "qualified_const_set" do + m = Module.new + assert_equal m, Object.qualified_const_set("QualifiedConstTestMod2", m) + assert_equal m, ::QualifiedConstTestMod2 + + # We are going to assign to existing constants on purpose, so silence warnings. + silence_warnings do + assert_equal true, QualifiedConstTestMod.qualified_const_set("QualifiedConstTestMod::X", true) + assert_equal true, QualifiedConstTestMod::X + + assert_equal 10, QualifiedConstTestMod::M.qualified_const_set("X", 10) + assert_equal 10, QualifiedConstTestMod::M::X + end + end + + test "reject absolute paths" do + assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_defined?("::X")} + assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_defined?("::X::Y")} + + assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_get("::X")} + assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_get("::X::Y")} + + assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_set("::X", nil)} + assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_set("::X::Y", nil)} + end +end diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 4d876954cf..ade09efc56 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -111,6 +111,10 @@ class StringInflectionsTest < Test::Unit::TestCase assert_equal "Account", "MyApplication::Billing::Account".demodulize end + def test_deconstantize + assert_equal "MyApplication::Billing", "MyApplication::Billing::Account".deconstantize + end + def test_foreign_key ClassNameToForeignKeyWithUnderscore.each do |klass, foreign_key| assert_equal(foreign_key, klass.foreign_key) diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb index 5c956e0075..6b7e839e43 100644 --- a/activesupport/test/inflector_test.rb +++ b/activesupport/test/inflector_test.rb @@ -194,6 +194,20 @@ class InflectorTest < Test::Unit::TestCase def test_demodulize assert_equal "Account", ActiveSupport::Inflector.demodulize("MyApplication::Billing::Account") + assert_equal "Account", ActiveSupport::Inflector.demodulize("Account") + assert_equal "", ActiveSupport::Inflector.demodulize("") + end + + def test_deconstantize + assert_equal "MyApplication::Billing", ActiveSupport::Inflector.deconstantize("MyApplication::Billing::Account") + assert_equal "::MyApplication::Billing", ActiveSupport::Inflector.deconstantize("::MyApplication::Billing::Account") + + assert_equal "MyApplication", ActiveSupport::Inflector.deconstantize("MyApplication::Billing") + assert_equal "::MyApplication", ActiveSupport::Inflector.deconstantize("::MyApplication::Billing") + + assert_equal "", ActiveSupport::Inflector.deconstantize("Account") + assert_equal "", ActiveSupport::Inflector.deconstantize("::Account") + assert_equal "", ActiveSupport::Inflector.deconstantize("") end def test_foreign_key diff --git a/railties/CHANGELOG b/railties/CHANGELOG index 7f7b24804d..404bc73b0b 100644 --- a/railties/CHANGELOG +++ b/railties/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.2.0 (unreleased)* +* Scaffold returns 204 No Content for API requests without content. This makes scaffold work with jQuery out of the box. [José Valim] + * Updated Rails::Rack::Logger middleware to apply any tags set in config.log_tags to the newly ActiveSupport::TaggedLogging Rails.logger. This makes it easy to tag log lines with debug information like subdomain and request id -- both very helpful in debugging multi-user production applications [DHH] * Default options to `rails new` can be set in ~/.railsrc [Guillermo Iguaran] diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile index c04e49281e..0941953d1c 100644 --- a/railties/guides/source/active_support_core_extensions.textile +++ b/railties/guides/source/active_support_core_extensions.textile @@ -725,6 +725,64 @@ WARNING: This method returns precise results in Ruby 1.9. In older versions of R NOTE: Defined in +active_support/core_ext/module/introspection.rb+. +h5. Qualified Constant Names + +The standard methods +const_defined?+, +const_get+ , and +const_set+ accept +bare constant names. Active Support extends this API to be able to pass +relative qualified constant reference expressions. + +The new methods are +qualified_const_defined?+, +qualified_const_get+, and ++qualified_const_set+. Their arguments are assumed to be qualified constant +names relative to their receiver: + +<ruby> +Object.qualified_const_defined?("Math::PI") # => true +Object.qualified_const_get("Math::PI") # => 3.141592653589793 +Object.qualified_const_set("Math::Phi", 1.618034) # => 1.618034 +</ruby> + +Arguments may be bare constant names: + +<ruby> +Math.qualified_const_get("E") # => 2.718281828459045 +</ruby> + +These methods are analogous to their builtin counterparts. In particular, ++qualified_constant_defined?+ accepts an optional second argument in 1.9 +to be able to say whether you want the predicate to look in the ancestors. +This flag is taken into account for each constant in the expression while +walking down the path. + +For example, given + +<ruby> +module M + X = 1 +end + +module N + class C + include M + end +end +</ruby> + ++qualified_const_defined?+ behaves this way: + +<ruby> +N.qualified_const_defined?("C::X", false) # => false (1.9 only) +N.qualified_const_defined?("C::X", true) # => true (1.9 only) +N.qualified_const_defined?("C::X") # => false in 1.8, true in 1.9 +</ruby> + +As the last example implies, in 1.9 the second argument defaults to true, +as in +const_defined?+. + +For coherence with the builtin methods only relative paths are accepted. +Absolute qualified constant names like +::Math::PI+ raise +NameError+. + +NOTE: Defined in +active_support/core_ext/module/qualified_const.rb+. + h4. Synchronization The +synchronize+ macro declares a method to be synchronized: @@ -1620,6 +1678,31 @@ end NOTE: Defined in +active_support/core_ext/string/inflections.rb+. +h5. +deconstantize+ + +Given a string with a qualified constant reference expression, +deconstantize+ removes the rightmost segment, generally leaving the name of the constant's container: + +<ruby> +"Product".deconstantize # => "" +"Backoffice::UsersController".deconstantize # => "Backoffice" +"Admin::Hotel::ReservationUtils".deconstantize # => "Admin::Hotel" +</ruby> + +Active Support for example uses this method in +Module#qualified_const_set+: + +<ruby> +def qualified_const_set(path, value) + QualifiedConstUtils.raise_if_absolute(path) + + const_name = path.demodulize + mod_name = path.deconstantize + mod = mod_name.empty? ? self : qualified_const_get(mod_name) + mod.const_set(const_name, value) +end +</ruby> + +NOTE: Defined in +active_support/core_ext/string/inflections.rb+. + h5. +parameterize+ The method +parameterize+ normalizes its receiver in a way that can be used in pretty URLs. diff --git a/railties/guides/source/caching_with_rails.textile b/railties/guides/source/caching_with_rails.textile index 721c791a33..4273d0dd64 100644 --- a/railties/guides/source/caching_with_rails.textile +++ b/railties/guides/source/caching_with_rails.textile @@ -289,11 +289,7 @@ ActionController::Base.cache_store = :file_store, "/path/to/cache/directory" With this cache store, multiple server processes on the same host can share a cache. Servers processes running on different hosts could share a cache by using a shared file system, but that set up would not be ideal and is not recommended. The cache store is appropriate for low to medium traffic sites that are served off one or two hosts. -Note that the cache will grow until the disk is full unless you periodically clear out old entries. You can call +ActiveSupport::Cache::FileStore#cleanup+ to remove entries older than a specified time. - -<ruby> -Rails.cache.cleanup(:not_accessed_in => 2.days) -</ruby> +Note that the cache will grow until the disk is full unless you periodically clear out old entries. h4. ActiveSupport::Cache::MemCacheStore diff --git a/railties/lib/rails/application/route_inspector.rb b/railties/lib/rails/application/route_inspector.rb index 8c6911e6bb..8252f21aa7 100644 --- a/railties/lib/rails/application/route_inspector.rb +++ b/railties/lib/rails/application/route_inspector.rb @@ -10,20 +10,21 @@ module Rails end routes = all_routes.collect do |route| + route_reqs = route.requirements - reqs = route.requirements.dup rack_app = route.app unless route.app.class.name.to_s =~ /^ActionDispatch::Routing/ - endpoint = rack_app ? rack_app.inspect : "#{reqs[:controller]}##{reqs[:action]}" - constraints = reqs.except(:controller, :action) + controller = route_reqs[:controller] || ':controller' + action = route_reqs[:action] || ':action' - reqs = endpoint == '#' ? '' : endpoint + endpoint = rack_app ? rack_app.inspect : "#{controller}##{action}" + constraints = route_reqs.except(:controller, :action) - unless constraints.empty? - reqs = reqs.empty? ? constraints.inspect : "#{reqs} #{constraints.inspect}" - end + reqs = endpoint + reqs += " #{constraints.inspect}" unless constraints.empty? verb = route.verb.source.gsub(/[$^]/, '') + {:name => route.name.to_s, :verb => verb, :path => route.path.spec.to_s, :reqs => reqs} end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 2d25273050..1c9627734e 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -488,7 +488,7 @@ module Rails # Blog::Engine.load_seed def load_seed seed_file = paths["db/seeds"].existent.first - load(seed_file) if File.exist?(seed_file) + load(seed_file) if seed_file && File.exist?(seed_file) end # Add configured load paths to ruby load paths and remove duplicates. diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index 32b961d9fc..4ff15fd288 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -62,7 +62,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| if @<%= orm_instance.update_attributes("params[:#{singular_table_name}]") %> format.html { redirect_to @<%= singular_table_name %>, <%= key_value :notice, "'#{human_name} was successfully updated.'" %> } - format.json { head :ok } + format.json { head :no_content } else format.html { render <%= key_value :action, '"edit"' %> } format.json { render <%= key_value :json, "@#{orm_instance.errors}" %>, <%= key_value :status, ':unprocessable_entity' %> } @@ -78,7 +78,7 @@ class <%= controller_class_name %>Controller < ApplicationController respond_to do |format| format.html { redirect_to <%= index_helper %>_url } - format.json { head :ok } + format.json { head :no_content } end end end diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb index 01fe6dda7a..9ec2e34545 100644 --- a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb +++ b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb @@ -26,23 +26,23 @@ class <%= controller_class_name %>ControllerTest < ActionController::TestCase end test "should show <%= singular_table_name %>" do - get :show, <%= key_value :id, "@#{singular_table_name}.to_param" %> + get :show, <%= key_value :id, "@#{singular_table_name}" %> assert_response :success end test "should get edit" do - get :edit, <%= key_value :id, "@#{singular_table_name}.to_param" %> + get :edit, <%= key_value :id, "@#{singular_table_name}" %> assert_response :success end test "should update <%= singular_table_name %>" do - put :update, <%= key_value :id, "@#{singular_table_name}.to_param" %>, <%= key_value singular_table_name, "@#{singular_table_name}.attributes" %> + put :update, <%= key_value :id, "@#{singular_table_name}" %>, <%= key_value singular_table_name, "@#{singular_table_name}.attributes" %> assert_redirected_to <%= singular_table_name %>_path(assigns(:<%= singular_table_name %>)) end test "should destroy <%= singular_table_name %>" do assert_difference('<%= class_name %>.count', -1) do - delete :destroy, <%= key_value :id, "@#{singular_table_name}.to_param" %> + delete :destroy, <%= key_value :id, "@#{singular_table_name}" %> end assert_redirected_to <%= index_helper %>_path diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index fa01f42c5b..3d87529ad4 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -61,6 +61,7 @@ end # Recreated here from Active Support because :uncommitted needs it before Rails is available module Kernel + remove_method :silence_stderr # Removing old method to prevent method redefined warning def silence_stderr old_stderr = STDERR.dup STDERR.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null') diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 97ad47ac14..f356805d6e 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -476,7 +476,7 @@ module ApplicationTests app_file 'app/controllers/posts_controller.rb', <<-RUBY class PostsController < ApplicationController - def index + def create render :text => params[:post].inspect end end diff --git a/railties/test/application/rack/logger_test.rb b/railties/test/application/rack/logger_test.rb index 8b2b2f1802..387eb25525 100644 --- a/railties/test/application/rack/logger_test.rb +++ b/railties/test/application/rack/logger_test.rb @@ -12,6 +12,8 @@ module ApplicationTests build_app require "#{app_path}/config/environment" super + @logger = MockLogger.new + Rails.stubs(:logger).returns(@logger) end def teardown diff --git a/railties/test/application/route_inspect_test.rb b/railties/test/application/route_inspect_test.rb index add8256b5d..78980705ed 100644 --- a/railties/test/application/route_inspect_test.rb +++ b/railties/test/application/route_inspect_test.rb @@ -49,12 +49,20 @@ module ApplicationTests assert_equal ["root / pages#main"], output end + def test_inspect_routes_shows_dynamic_action_route + @set.draw do + match 'api/:action' => 'api' + end + output = @inspector.format @set.routes + assert_equal [" /api/:action(.:format) api#:action"], output + end + def test_inspect_routes_shows_controller_and_action_only_route @set.draw do match ':controller/:action' end output = @inspector.format @set.routes - assert_equal [" /:controller/:action(.:format) "], output + assert_equal [" /:controller/:action(.:format) :controller#:action"], output end def test_inspect_routes_shows_controller_and_action_route_with_constraints @@ -62,7 +70,7 @@ module ApplicationTests match ':controller(/:action(/:id))', :id => /\d+/ end output = @inspector.format @set.routes - assert_equal [" /:controller(/:action(/:id))(.:format) {:id=>/\\d+/}"], output + assert_equal [" /:controller(/:action(/:id))(.:format) :controller#:action {:id=>/\\d+/}"], output end def test_rake_routes_shows_route_with_defaults diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 4b74bd6a4b..955ed09361 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -143,6 +143,16 @@ class AppGeneratorTest < Rails::Generators::TestCase end end + def test_config_postgresql_database + run_generator([destination_root, "-d", "postgresql"]) + assert_file "config/database.yml", /postgresql/ + unless defined?(JRUBY_VERSION) + assert_file "Gemfile", /^gem\s+["']pg["']$/ + else + assert_file "Gemfile", /^gem\s+["']activerecord-jdbcpostgresql-adapter["']$/ + end + end + def test_config_jdbcmysql_database run_generator([destination_root, "-d", "jdbcmysql"]) assert_file "config/database.yml", /mysql/ diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 06a60cd858..22dbcf9644 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -455,12 +455,18 @@ module RailtiesTest Rails.application.load_seed assert Rails.application.config.app_seeds_loaded - assert_raise(NoMethodError) do Bukkits::Engine.config.bukkits_seeds_loaded end + assert_raise(NoMethodError) { Bukkits::Engine.config.bukkits_seeds_loaded } Bukkits::Engine.load_seed assert Bukkits::Engine.config.bukkits_seeds_loaded end + test "skips nonexistent seed data" do + FileUtils.rm "#{app_path}/db/seeds.rb" + boot_rails + assert_nil Rails.application.load_seed + end + test "using namespace more than once on one module should not overwrite _railtie method" do @plugin.write "lib/bukkits.rb", <<-RUBY module AppTemplate |