From 803523fb932cae1b26fd7aa81ed000f7e8656ea2 Mon Sep 17 00:00:00 2001 From: Reuben Pereira Date: Mon, 2 Aug 2021 11:28:37 +0530 Subject: [PATCH] Do not overwrite the database default value When a new database record has a column that is set to its database default value, the "#{attribute}_changed?" method returns false, which causes default_value_for to overwrite the database default. This commit changes this behavior to not overwrite when the column is being set by the initialization attributes. --- lib/default_value_for.rb | 14 ++++++++++++++ test.rb | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib/default_value_for.rb b/lib/default_value_for.rb index fc5b573..3aa6ad7 100644 --- a/lib/default_value_for.rb +++ b/lib/default_value_for.rb @@ -171,6 +171,20 @@ def set_default_values end next unless connection_default_value_defined || attribute_blank + is_present = -> (value) do + if [true, false].include?(value) + !value.nil? + else + value.present? + end + end + + attribute_init_value_defined = @initialization_attributes.is_a?(Hash) && + @initialization_attributes.has_key?(attribute) && + is_present.call(@initialization_attributes[attribute]) + + next if attribute_init_value_defined + # allow explicitly setting nil through allow nil option next if @initialization_attributes.is_a?(Hash) && ( diff --git a/test.rb b/test.rb index 361c6a3..4d73f35 100644 --- a/test.rb +++ b/test.rb @@ -90,6 +90,7 @@ class ToSql < (Arel::VERSION[/\A\d+/].to_i >= 6 ? Arel::Visitors::Reduce : Arel: t.string :type t.integer :number t.integer :count, :null => false, :default => 1 + t.boolean :flag2, :null => false, :default => false t.integer :user_id t.timestamp :timestamp t.text :stuff @@ -168,6 +169,16 @@ def test_overwrites_db_default assert_equal 1234, Book.new.count end + def test_does_not_overwrite_db_default_if_provided_by_mass_assignment + Book.default_value_for(:count, :allows_nil => false) { 1234 } + assert_equal Book.column_defaults['count'], Book.new(count: Book.column_defaults['count']).count + end + + def test_does_not_overwrite_db_default_boolean_value_if_provided_by_mass_assignment + Book.default_value_for(:flag2, :allows_nil => false) { true } + assert_equal Book.column_defaults['flag2'], Book.new(flag2: Book.column_defaults['flag2']).flag2 + end + def test_doesnt_overwrite_values_provided_by_mass_assignment Book.default_value_for :number, 1234 assert_equal 1, Book.new(:number => 1, :count => 2).number @@ -199,6 +210,11 @@ def test_overwrites_explicitly_provided_nil_values_in_mass_assignment assert_equal 1234, Book.new(:number => nil).number end + def test_overwrites_string_blank_value_in_mass_assignment + Book.default_value_for(:type, :allows_nil => false) { 'string' } + assert_equal 'string', Book.new(type: '').type + end + def test_default_values_are_inherited Book.default_value_for :number, 1234 assert_equal 1234, Novel.new.number