diff options
23 files changed, 132 insertions, 32 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 9eb68db101..787e6d68be 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,7 @@ +* Use `set_backtrace` instead of instance variable `@backtrace` in ActionView exceptions + + *Shimpei Makimoto* + * Fix `simple_format` escapes own output when passing `sanitize: true` *Paul Seidemann* diff --git a/actionview/lib/action_view/helpers/tag_helper.rb b/actionview/lib/action_view/helpers/tag_helper.rb index 11e41ec056..3528381781 100644 --- a/actionview/lib/action_view/helpers/tag_helper.rb +++ b/actionview/lib/action_view/helpers/tag_helper.rb @@ -151,7 +151,7 @@ module ActionView attrs << tag_option(key, value, escape) end end - " #{attrs.sort! * ' '}".html_safe unless attrs.empty? + " #{attrs.sort! * ' '}" unless attrs.empty? end def data_tag_option(key, value, escape) diff --git a/actionview/lib/action_view/template/error.rb b/actionview/lib/action_view/template/error.rb index a89d51221e..7b4b5e13e0 100644 --- a/actionview/lib/action_view/template/error.rb +++ b/actionview/lib/action_view/template/error.rb @@ -56,13 +56,13 @@ module ActionView class Error < ActionViewError #:nodoc: SOURCE_CODE_RADIUS = 3 - attr_reader :original_exception, :backtrace + attr_reader :original_exception def initialize(template, original_exception) super(original_exception.message) @template, @original_exception = template, original_exception @sub_templates = nil - @backtrace = original_exception.backtrace + set_backtrace(original_exception.backtrace) end def file_name diff --git a/actionview/test/template/template_error_test.rb b/actionview/test/template/template_error_test.rb index 91424daeed..3971ec809c 100644 --- a/actionview/test/template/template_error_test.rb +++ b/actionview/test/template/template_error_test.rb @@ -6,6 +6,13 @@ class TemplateErrorTest < ActiveSupport::TestCase assert_equal "original", error.message end + def test_provides_original_backtrace + original_exception = Exception.new + original_exception.set_backtrace(%W[ foo bar baz ]) + error = ActionView::Template::Error.new("test", original_exception) + assert_equal %W[ foo bar baz ], error.backtrace + end + def test_provides_useful_inspect error = ActionView::Template::Error.new("test", Exception.new("original")) assert_equal "#<ActionView::Template::Error: original>", error.inspect diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 4cb7066c1f..b549f594bb 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Exit with non-zero status for failed database rake tasks. + + *Jay Hayes* + * Added `ActiveRecord::Base.to_param` for convenient "pretty" URLs derived from a model's attribute or method. Example: diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index ee6ca4fb6f..dcbc3466b2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -320,27 +320,19 @@ module ActiveRecord def begin_db_transaction execute "BEGIN" - rescue - # Transactions aren't supported end def begin_isolated_db_transaction(isolation) execute "SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}" begin_db_transaction - rescue - # Transactions aren't supported end def commit_db_transaction #:nodoc: execute "COMMIT" - rescue - # Transactions aren't supported end def rollback_db_transaction #:nodoc: execute "ROLLBACK" - rescue - # Transactions aren't supported end # In the simple case, MySQL allows us to place JOINs directly into the UPDATE diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 7b18b95c44..c4dcba0501 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -462,8 +462,6 @@ module ActiveRecord def begin_db_transaction #:nodoc: exec_query "BEGIN" - rescue Mysql::Error - # Transactions aren't supported end private diff --git a/activerecord/lib/active_record/integration.rb b/activerecord/lib/active_record/integration.rb index 951db5b756..27576b1e61 100644 --- a/activerecord/lib/active_record/integration.rb +++ b/activerecord/lib/active_record/integration.rb @@ -81,6 +81,13 @@ module ActiveRecord # user.id # => 123 # user_path(user) # => "/users/123-fancy-pants" # + # Values longer than 20 characters will be truncated. The value + # is truncated word by word. + # + # user = User.find_by(name: 'David HeinemeierHansson') + # user.id # => 125 + # user_path(user) # => "/users/125-david" + # # Because the generated param begins with the record's +id+, it is # suitable for passing to +find+. In a controller, for example: # diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 52b3d3e5e6..3ca66223b6 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -8,31 +8,47 @@ db_namespace = namespace :db do namespace :create do task :all => :load_config do - ActiveRecord::Tasks::DatabaseTasks.create_all + begin + ActiveRecord::Tasks::DatabaseTasks.create_all + rescue + exit(1) + end end end desc 'Create the database from DATABASE_URL or config/database.yml for the current Rails.env (use db:create:all to create all databases in the config)' task :create => [:load_config] do - if ENV['DATABASE_URL'] - ActiveRecord::Tasks::DatabaseTasks.create_database_url - else - ActiveRecord::Tasks::DatabaseTasks.create_current + begin + if ENV['DATABASE_URL'] + ActiveRecord::Tasks::DatabaseTasks.create_database_url + else + ActiveRecord::Tasks::DatabaseTasks.create_current + end + rescue + exit(1) end end namespace :drop do task :all => :load_config do - ActiveRecord::Tasks::DatabaseTasks.drop_all + begin + ActiveRecord::Tasks::DatabaseTasks.drop_all + rescue + exit(1) + end end end desc 'Drops the database using DATABASE_URL or the current Rails.env (use db:drop:all to drop all databases)' task :drop => [:load_config] do - if ENV['DATABASE_URL'] - ActiveRecord::Tasks::DatabaseTasks.drop_database_url - else - ActiveRecord::Tasks::DatabaseTasks.drop_current + begin + if ENV['DATABASE_URL'] + ActiveRecord::Tasks::DatabaseTasks.drop_database_url + else + ActiveRecord::Tasks::DatabaseTasks.drop_current + end + rescue + exit(1) end end diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index be7d496d15..0b6a49ac85 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -69,9 +69,11 @@ module ActiveRecord class_for_adapter(configuration['adapter']).new(*arguments).create rescue DatabaseAlreadyExists $stderr.puts "#{configuration['database']} already exists" + raise rescue Exception => error $stderr.puts error, *(error.backtrace) $stderr.puts "Couldn't create database for #{configuration.inspect}" + raise end def create_all @@ -95,6 +97,7 @@ module ActiveRecord rescue Exception => error $stderr.puts error, *(error.backtrace) $stderr.puts "Couldn't drop #{configuration['database']}" + raise end def drop_all diff --git a/activerecord/test/cases/adapters/mysql/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb index a61d61eef7..a1b41b6991 100644 --- a/activerecord/test/cases/adapters/mysql/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql/connection_test.rb @@ -40,6 +40,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase @connection.update('set @@wait_timeout=1') sleep 2 assert !@connection.active? + + # Repair all fixture connections so other tests won't break. + @fixture_connections.each do |c| + c.verify! + end end def test_successful_reconnection_after_timeout_with_manual_reconnect diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index 679c515e8c..8dc1df1851 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -18,6 +18,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase @connection.update('set @@wait_timeout=1') sleep 2 assert !@connection.active? + + # Repair all fixture connections so other tests won't break. + @fixture_connections.each do |c| + c.verify! + end end def test_successful_reconnection_after_timeout_with_manual_reconnect diff --git a/activerecord/test/cases/integration_test.rb b/activerecord/test/cases/integration_test.rb index 8097f6e36e..07ffcef875 100644 --- a/activerecord/test/cases/integration_test.rb +++ b/activerecord/test/cases/integration_test.rb @@ -34,6 +34,12 @@ class IntegrationTest < ActiveRecord::TestCase assert_equal '4-a-a-a-a-a-a-a-a-a', firm.to_param end + def test_to_param_class_method_truncates_edge_case + firm = Firm.find(4) + firm.name = 'David HeinemeierHansson' + assert_equal '4-david', firm.to_param + end + def test_to_param_class_method_squishes firm = Firm.find(4) firm.name = "ab \n" * 100 diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index f74e903348..7c3988859f 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -63,6 +63,7 @@ class MigrationTest < ActiveRecord::TestCase def test_migrator_versions migrations_path = MIGRATIONS_ROOT + "/valid" + old_path = ActiveRecord::Migrator.migrations_paths ActiveRecord::Migrator.migrations_paths = migrations_path ActiveRecord::Migrator.up(migrations_path) @@ -74,6 +75,8 @@ class MigrationTest < ActiveRecord::TestCase assert_equal 0, ActiveRecord::Migrator.current_version assert_equal 3, ActiveRecord::Migrator.last_version assert_equal true, ActiveRecord::Migrator.needs_migration? + ensure + ActiveRecord::Migrator.migrations_paths = old_path end def test_create_table_with_force_true_does_not_drop_nonexisting_table diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb index 3e3a2828f3..d16cf40555 100644 --- a/activerecord/test/cases/tasks/mysql_rake_test.rb +++ b/activerecord/test/cases/tasks/mysql_rake_test.rb @@ -61,7 +61,9 @@ module ActiveRecord ActiveRecord::StatementInvalid.new("Can't create database 'dev'; database exists:") ) - ActiveRecord::Tasks::DatabaseTasks.create @configuration + assert_raises(ActiveRecord::Tasks::DatabaseAlreadyExists) do + ActiveRecord::Tasks::DatabaseTasks.create @configuration + end end end diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb index 6ea225178f..88ce666619 100644 --- a/activerecord/test/cases/tasks/postgresql_rake_test.rb +++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb @@ -59,7 +59,9 @@ module ActiveRecord $stderr.expects(:puts). with("Couldn't create database for #{@configuration.inspect}") - ActiveRecord::Tasks::DatabaseTasks.create @configuration + assert_raises(Exception) do + ActiveRecord::Tasks::DatabaseTasks.create @configuration + end end def test_create_when_database_exists_outputs_info_to_stderr @@ -69,7 +71,9 @@ module ActiveRecord ActiveRecord::StatementInvalid.new('database "my-app-db" already exists') ) - ActiveRecord::Tasks::DatabaseTasks.create @configuration + assert_raises(ActiveRecord::Tasks::DatabaseAlreadyExists) do + ActiveRecord::Tasks::DatabaseTasks.create @configuration + end end end diff --git a/activerecord/test/cases/tasks/sqlite_rake_test.rb b/activerecord/test/cases/tasks/sqlite_rake_test.rb index da3471adf9..eecc3527d2 100644 --- a/activerecord/test/cases/tasks/sqlite_rake_test.rb +++ b/activerecord/test/cases/tasks/sqlite_rake_test.rb @@ -27,7 +27,9 @@ module ActiveRecord $stderr.expects(:puts).with("#{@database} already exists") - ActiveRecord::Tasks::DatabaseTasks.create @configuration, '/rails/root' + assert_raises(ActiveRecord::Tasks::DatabaseAlreadyExists) do + ActiveRecord::Tasks::DatabaseTasks.create @configuration, '/rails/root' + end end def test_db_create_with_file_does_nothing @@ -36,7 +38,9 @@ module ActiveRecord ActiveRecord::Base.expects(:establish_connection).never - ActiveRecord::Tasks::DatabaseTasks.create @configuration, '/rails/root' + assert_raises(ActiveRecord::Tasks::DatabaseAlreadyExists) do + ActiveRecord::Tasks::DatabaseTasks.create @configuration, '/rails/root' + end end def test_db_create_establishes_a_connection @@ -52,7 +56,9 @@ module ActiveRecord $stderr.expects(:puts). with("Couldn't create database for #{@configuration.inspect}") - ActiveRecord::Tasks::DatabaseTasks.create @configuration, '/rails/root' + assert_raises(Exception) do + ActiveRecord::Tasks::DatabaseTasks.create @configuration, '/rails/root' + end end end diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index bb66b0ffa2..95253567c0 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,14 @@ +* Unify `cattr_*` interface: allow to pass a block to `cattr_reader`. + + Example: + + class A + cattr_reader(:defr) { 'default_reader_value' } + end + A.defr # => 'default_reader_value' + + *Alexey Chernenkov* + * Improved compatibility with the stdlib JSON gem. Previously, calling `::JSON.{generate,dump}` sometimes causes unexpected diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb index 34859617c9..6daa828b24 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb @@ -29,6 +29,16 @@ class Class # end # # Person.new.hair_colors # => NoMethodError + # + # Also, you can pass a block to set up the attribute with a default value. + # + # class Person + # cattr_reader :hair_colors do + # [:brown, :black, :blonde, :red] + # end + # end + # + # Person.hair_colors # => [:brown, :black, :blonde, :red] def cattr_reader(*syms) options = syms.extract_options! syms.each do |sym| @@ -50,6 +60,7 @@ class Class end EOS end + class_variable_set("@@#{sym}", yield) if block_given? end end diff --git a/activesupport/test/core_ext/class/attribute_accessor_test.rb b/activesupport/test/core_ext/class/attribute_accessor_test.rb index 0d5f39a72b..3bc948f3a6 100644 --- a/activesupport/test/core_ext/class/attribute_accessor_test.rb +++ b/activesupport/test/core_ext/class/attribute_accessor_test.rb @@ -8,6 +8,9 @@ class ClassAttributeAccessorTest < ActiveSupport::TestCase cattr_accessor :bar, :instance_writer => false cattr_reader :shaq, :instance_reader => false cattr_accessor :camp, :instance_accessor => false + cattr_accessor(:defa) { 'default_accessor_value' } + cattr_reader(:defr) { 'default_reader_value' } + cattr_writer(:defw) { 'default_writer_value' } end @object = @class.new end @@ -58,4 +61,10 @@ class ClassAttributeAccessorTest < ActiveSupport::TestCase end assert_equal "invalid class attribute name: 1nvalid", exception.message end + + def test_should_use_default_value_if_block_passed + assert_equal 'default_accessor_value', @class.defa + assert_equal 'default_reader_value', @class.defr + assert_equal 'default_writer_value', @class.class_variable_get('@@defw') + end end diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md index 57e8e080f4..cf0249a400 100644 --- a/guides/source/active_record_querying.md +++ b/guides/source/active_record_querying.md @@ -1301,7 +1301,7 @@ especially useful if a `default_scope` is specified in the model and should not applied for this particular query. ```ruby -Client.unscoped.all +Client.unscoped.load ``` This method removes all scoping and will do a normal query on the table. diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index 648036fb3f..84a169b3b9 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -1093,6 +1093,15 @@ end we can access `field_error_proc` in views. +Also, you can pass a block to `cattr_*` to set up the attribute with a default value: + +```ruby +class MysqlAdapter < AbstractAdapter + # Generates class methods to access @@emulate_booleans with default value of true. + cattr_accessor(:emulate_booleans) { true } +end +``` + The generation of the reader instance method can be prevented by setting `:instance_reader` to `false` and the generation of the writer instance method can be prevented by setting `:instance_writer` to `false`. Generation of both methods can be prevented by setting `:instance_accessor` to `false`. In all cases, the value must be exactly `false` and not any false value. ```ruby diff --git a/guides/source/command_line.md b/guides/source/command_line.md index 1b0b93c3bc..3b80faec7f 100644 --- a/guides/source/command_line.md +++ b/guides/source/command_line.md @@ -56,8 +56,6 @@ Rails will set you up with what seems like a huge amount of stuff for such a tin The `rails server` command launches a small web server named WEBrick which comes bundled with Ruby. You'll use this any time you want to access your application through a web browser. -INFO: WEBrick isn't your only option for serving Rails. We'll get to that [later](#server-with-different-backends). - With no further work, `rails server` will run our new shiny Rails app: ```bash |