diff options
-rw-r--r-- | actionpack/lib/action_controller/test_case.rb | 2 | ||||
-rw-r--r-- | actionview/lib/action_view/digestor.rb | 3 | ||||
-rw-r--r-- | actionview/test/template/digestor_test.rb | 20 | ||||
-rw-r--r-- | activerecord/CHANGELOG.md | 10 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/enum.rb | 42 | ||||
-rw-r--r-- | activerecord/test/cases/enum_test.rb | 50 | ||||
-rw-r--r-- | activerecord/test/fixtures/books.yml | 4 | ||||
-rw-r--r-- | activerecord/test/models/book.rb | 4 | ||||
-rw-r--r-- | activerecord/test/schema/schema.rb | 4 | ||||
-rw-r--r-- | guides/source/active_record_migrations.md | 3 | ||||
-rw-r--r-- | railties/test/application/rake_test.rb | 2 |
12 files changed, 135 insertions, 16 deletions
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index d34149143f..96f161fb09 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -165,7 +165,7 @@ module ActionController # class BooksControllerTest < ActionController::TestCase # def test_create # # Simulate a POST response with the given HTTP parameters. - # post(:create, book: { title: "Love Hina" }) + # post(:create, params: { book: { title: "Love Hina" }}) # # # Assert that the controller tried to redirect us to # # the created book's URI. diff --git a/actionview/lib/action_view/digestor.rb b/actionview/lib/action_view/digestor.rb index 1f103786cb..b29eb48425 100644 --- a/actionview/lib/action_view/digestor.rb +++ b/actionview/lib/action_view/digestor.rb @@ -70,7 +70,8 @@ module ActionView def dependencies DependencyTracker.find_dependencies(name, template) rescue ActionView::MissingTemplate - [] # File doesn't exist, so no dependencies + logger.try :error, " '#{name}' file doesn't exist, so no dependencies" + [] end def nested_dependencies diff --git a/actionview/test/template/digestor_test.rb b/actionview/test/template/digestor_test.rb index c2b8439df3..f0afcdb5ae 100644 --- a/actionview/test/template/digestor_test.rb +++ b/actionview/test/template/digestor_test.rb @@ -111,6 +111,18 @@ class TemplateDigestorTest < ActionView::TestCase end end + def test_logging_of_missing_template_for_dependencies + assert_logged "'messages/something_missing' file doesn't exist, so no dependencies" do + dependencies("messages/something_missing") + end + end + + def test_logging_of_missing_template_for_nested_dependencies + assert_logged "'messages/something_missing' file doesn't exist, so no dependencies" do + nested_dependencies("messages/something_missing") + end + end + def test_nested_template_directory assert_digest_difference("messages/show") do change_template("messages/actions/_move") @@ -298,6 +310,14 @@ class TemplateDigestorTest < ActionView::TestCase ActionView::Digestor.digest({ name: template_name, finder: finder }.merge(options)) end + def dependencies(template_name) + ActionView::Digestor.new({ name: template_name, finder: finder }).dependencies + end + + def nested_dependencies(template_name) + ActionView::Digestor.new({ name: template_name, finder: finder }).nested_dependencies + end + def finder @finder ||= FixtureFinder.new end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 76d65e41de..14906e441b 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,8 +1,14 @@ -* Make remove_foreign_key invertible. Any foreign key options must be - specified, similar to remove_column. +* Make `remove_foreign_key` reversible. Any foreign key options must be + specified, similar to `remove_column`. *Aster Ryan* +* Add `:enum_prefix`/`:enum_suffix` option to `enum` definition. + + Fixes #17511 and #17415 + + *Igor Kapkov* + * Correctly handle decimal arrays with defaults in the schema dumper. Fixes #20515. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index a89886721a..c8be038d76 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -777,8 +777,8 @@ module ActiveRecord execute schema_creation.accept(at) end - # Removes the given foreign key from the table. Any options parameters provided - # will be used to re-add the foreign key in case of a migration reversion. + # Removes the given foreign key from the table. Any option parameters provided + # will be used to re-add the foreign key in case of a migration rollback. # It is recommended that you provide any options used when creating the foreign # key so that the migration can be reverted properly. # @@ -794,8 +794,7 @@ module ActiveRecord # # remove_foreign_key :accounts, name: :special_fk_name # - # The +options+ hash can include all keys that can be used in add_foreign_key. - # Please refer to the add_foreign_key documentation for a full list + # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key. def remove_foreign_key(from_table, options_or_to_table = {}) return unless supports_foreign_keys? diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index 2b99899e42..ad33c84dbc 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -75,6 +75,22 @@ module ActiveRecord # # Conversation.where("status <> ?", Conversation.statuses[:archived]) # + # You can use <tt>:enum_prefix</tt>/<tt>:enum_suffix</tt> option then you need + # to define multiple enums with same values. If option value is <tt>true</tt>, + # the methods are prefixed/suffixed with the name of the enum. + # + # class Invoice < ActiveRecord::Base + # enum verification: [:done, :fail], enum_prefix: true + # end + # + # It is also possible to supply a custom prefix. + # + # class Invoice < ActiveRecord::Base + # enum verification: [:done, :fail], enum_prefix: :verification_status + # end + # + # Note that <tt>:enum_prefix</tt>/<tt>:enum_postfix</tt> are reserved keywords + # and can not be used as an enum name. module Enum def self.extended(base) # :nodoc: @@ -121,6 +137,8 @@ module ActiveRecord def enum(definitions) klass = self + enum_prefix = definitions.delete(:enum_prefix) + enum_suffix = definitions.delete(:enum_suffix) definitions.each do |name, values| # statuses = { } enum_values = ActiveSupport::HashWithIndifferentAccess.new @@ -138,19 +156,31 @@ module ActiveRecord _enum_methods_module.module_eval do pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index pairs.each do |value, i| + if enum_prefix == true + prefix = "#{name}_" + elsif enum_prefix + prefix = "#{enum_prefix}_" + end + if enum_suffix == true + suffix = "_#{name}" + elsif enum_suffix + suffix = "_#{enum_suffix}" + end + + value_method_name = "#{prefix}#{value}#{suffix}" enum_values[value] = i # def active?() status == 0 end - klass.send(:detect_enum_conflict!, name, "#{value}?") - define_method("#{value}?") { self[name] == value.to_s } + klass.send(:detect_enum_conflict!, name, "#{value_method_name}?") + define_method("#{value_method_name}?") { self[name] == value.to_s } # def active!() update! status: :active end - klass.send(:detect_enum_conflict!, name, "#{value}!") - define_method("#{value}!") { update! name => value } + klass.send(:detect_enum_conflict!, name, "#{value_method_name}!") + define_method("#{value_method_name}!") { update! name => value } # scope :active, -> { where status: 0 } - klass.send(:detect_enum_conflict!, name, value, true) - klass.scope value, -> { klass.where name => value } + klass.send(:detect_enum_conflict!, name, value_method_name, true) + klass.scope value_method_name, -> { klass.where name => value } end end defined_enums[name.to_s] = enum_values diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb index 3641826daa..769b171717 100644 --- a/activerecord/test/cases/enum_test.rb +++ b/activerecord/test/cases/enum_test.rb @@ -14,16 +14,26 @@ class EnumTest < ActiveRecord::TestCase assert_not @book.proposed? assert @book.read? + assert @book.in_english? + assert @book.author_visibility_visible? + assert @book.illustrator_visibility_visible? + assert @book.with_medium_font_size? end test "query state with strings" do assert_equal "published", @book.status assert_equal "read", @book.read_status + assert_equal "english", @book.language + assert_equal "visible", @book.author_visibility + assert_equal "visible", @book.illustrator_visibility end test "find via scope" do assert_equal @book, Book.published.first assert_equal @book, Book.read.first + assert_equal @book, Book.in_english.first + assert_equal @book, Book.author_visibility_visible.first + assert_equal @book, Book.illustrator_visibility_visible.first end test "find via where with values" do @@ -72,6 +82,10 @@ class EnumTest < ActiveRecord::TestCase test "update by declaration" do @book.written! assert @book.written? + @book.in_english! + assert @book.in_english? + @book.author_visibility_visible! + assert @book.author_visibility_visible? end test "update by setter" do @@ -96,42 +110,61 @@ class EnumTest < ActiveRecord::TestCase test "enum changed attributes" do old_status = @book.status + old_language = @book.language @book.status = :proposed + @book.language = :spanish assert_equal old_status, @book.changed_attributes[:status] + assert_equal old_language, @book.changed_attributes[:language] end test "enum changes" do old_status = @book.status + old_language = @book.language @book.status = :proposed + @book.language = :spanish assert_equal [old_status, 'proposed'], @book.changes[:status] + assert_equal [old_language, 'spanish'], @book.changes[:language] end test "enum attribute was" do old_status = @book.status + old_language = @book.language @book.status = :published + @book.language = :spanish assert_equal old_status, @book.attribute_was(:status) + assert_equal old_language, @book.attribute_was(:language) end test "enum attribute changed" do @book.status = :proposed + @book.language = :french assert @book.attribute_changed?(:status) + assert @book.attribute_changed?(:language) end test "enum attribute changed to" do @book.status = :proposed + @book.language = :french assert @book.attribute_changed?(:status, to: 'proposed') + assert @book.attribute_changed?(:language, to: 'french') end test "enum attribute changed from" do old_status = @book.status + old_language = @book.language @book.status = :proposed + @book.language = :french assert @book.attribute_changed?(:status, from: old_status) + assert @book.attribute_changed?(:language, from: old_language) end test "enum attribute changed from old status to new status" do old_status = @book.status + old_language = @book.language @book.status = :proposed + @book.language = :french assert @book.attribute_changed?(:status, from: old_status, to: 'proposed') + assert @book.attribute_changed?(:language, from: old_language, to: 'french') end test "enum didn't change" do @@ -201,11 +234,15 @@ class EnumTest < ActiveRecord::TestCase test "building new objects with enum scopes" do assert Book.written.build.written? assert Book.read.build.read? + assert Book.in_spanish.build.in_spanish? + assert Book.illustrator_visibility_invisible.build.illustrator_visibility_invisible? end test "creating new objects with enum scopes" do assert Book.written.create.written? assert Book.read.create.read? + assert Book.in_spanish.create.in_spanish? + assert Book.illustrator_visibility_invisible.create.illustrator_visibility_invisible? end test "_before_type_cast returns the enum label (required for form fields)" do @@ -355,4 +392,17 @@ class EnumTest < ActiveRecord::TestCase book2 = klass.single.create! assert book2.single? end + + test "query state by predicate with prefix" do + assert @book.author_visibility_visible? + assert_not @book.author_visibility_invisible? + assert @book.illustrator_visibility_visible? + assert_not @book.illustrator_visibility_invisible? + end + + test "query state by predicate with custom prefix" do + assert @book.in_english? + assert_not @book.in_spanish? + assert_not @book.in_french? + end end diff --git a/activerecord/test/fixtures/books.yml b/activerecord/test/fixtures/books.yml index 380dd3dfca..93cfabd61c 100644 --- a/activerecord/test/fixtures/books.yml +++ b/activerecord/test/fixtures/books.yml @@ -5,6 +5,10 @@ awdr: format: "paperback" status: :published read_status: :read + language: :english + author_visibility: :visible + illustrator_visibility: :visible + font_size: :medium rfr: author_id: 1 diff --git a/activerecord/test/models/book.rb b/activerecord/test/models/book.rb index 2170018068..24bfe47bbf 100644 --- a/activerecord/test/models/book.rb +++ b/activerecord/test/models/book.rb @@ -10,6 +10,10 @@ class Book < ActiveRecord::Base enum status: [:proposed, :written, :published] enum read_status: {unread: 0, reading: 2, read: 3} enum nullable_status: [:single, :married] + enum language: [:english, :spanish, :french], enum_prefix: :in + enum author_visibility: [:visible, :invisible], enum_prefix: true + enum illustrator_visibility: [:visible, :invisible], enum_prefix: true + enum font_size: [:small, :medium, :large], enum_prefix: :with, enum_suffix: true def published! super diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 8b010f265c..dffccc9326 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -100,6 +100,10 @@ ActiveRecord::Schema.define do t.column :status, :integer, default: 0 t.column :read_status, :integer, default: 0 t.column :nullable_status, :integer + t.column :language, :integer, default: 0 + t.column :author_visibility, :integer, default: 0 + t.column :illustrator_visibility, :integer, default: 0 + t.column :font_size, :integer, default: 0 end create_table :booleans, force: true do |t| diff --git a/guides/source/active_record_migrations.md b/guides/source/active_record_migrations.md index 80b1bde1c7..ad069a112e 100644 --- a/guides/source/active_record_migrations.md +++ b/guides/source/active_record_migrations.md @@ -475,7 +475,8 @@ column names can not be derived from the table names, you can use the `:column` and `:primary_key` options. Rails will generate a name for every foreign key starting with -`fk_rails_` followed by 10 random characters. +`fk_rails_` followed by 10 character which is deterministically +generated from the `from_table` and `column`. There is a `:name` option to specify a different name if needed. NOTE: Active Record only supports single column foreign keys. `execute` and diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index a839a0b9b6..4c1913f0cc 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -209,7 +209,7 @@ module ApplicationTests bundle exec rake db:migrate test` end - assert_match(/5 runs, 8 assertions, 0 failures, 0 errors/, output) + assert_match(/5 runs, 7 assertions, 0 failures, 0 errors/, output) assert_no_match(/Errors running/, output) end |