diff options
Diffstat (limited to 'activerecord/lib')
7 files changed, 37 insertions, 15 deletions
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index ced15bc330..0aff2562b8 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -207,8 +207,8 @@ module ActiveRecord value end - def arel_attributes_with_values_for_create(pk_attribute_allowed) - arel_attributes_with_values(attributes_for_create(pk_attribute_allowed)) + def arel_attributes_with_values_for_create(attribute_names) + arel_attributes_with_values(attributes_for_create(attribute_names)) end def arel_attributes_with_values_for_update(attribute_names) @@ -242,9 +242,9 @@ module ActiveRecord # Filters out the primary keys, from the attribute names, when the primary # key is to be generated (e.g. the id attribute has no value). - def attributes_for_create(pk_attribute_allowed) - @attributes.keys.select do |name| - column_for_attribute(name) && (pk_attribute_allowed || !pk_attribute?(name)) + def attributes_for_create(attribute_names) + attribute_names.select do |name| + column_for_attribute(name) && !(pk_attribute?(name) && id.nil?) end end diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 60e5b0e2bb..6204e4172d 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -64,15 +64,29 @@ module ActiveRecord end def update(*) + partial_updates? ? super(keys_for_partial_update) : super + end + + def create(*) if partial_updates? - # Serialized attributes should always be written in case they've been - # changed in place. - super(changed | (attributes.keys & self.class.serialized_attributes.keys)) + keys = keys_for_partial_update + + # This is an extremely bloody annoying necessity to work around mysql being crap. + # See test_mysql_text_not_null_defaults + keys.concat self.class.columns.select(&:explicit_default?).map(&:name) + + super keys else super end end + # Serialized attributes should always be written in case they've been + # changed in place. + def keys_for_partial_update + changed | (attributes.keys & self.class.serialized_attributes.keys) + end + def _field_changed?(attr, old, value) if column = column_for_attribute(attr) if column.number? && (changes_from_nil_to_empty_string?(column, old, value) || diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 793f58d4d3..0d7046a705 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -299,7 +299,7 @@ module ActiveRecord end def empty_insert_statement_value - "VALUES(DEFAULT)" + "DEFAULT VALUES" end def case_sensitive_equality_operator 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 1783b036a2..8c83c4f5db 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -30,6 +30,10 @@ module ActiveRecord super end + def explicit_default? + !null && (sql_type =~ /blob/i || type == :text) + end + # Must return the relevant concrete adapter def adapter raise NotImplementedError @@ -320,6 +324,10 @@ module ActiveRecord end end + def empty_insert_statement_value + "VALUES ()" + end + # SCHEMA STATEMENTS ======================================== def structure_dump #:nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 816b5e17c1..2028abf6f0 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -53,6 +53,10 @@ module ActiveRecord !default.nil? end + def explicit_default? + false + end + # Returns the Ruby class that corresponds to the abstract data type. def klass case type diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 4a48812807..4d5cb72c67 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -490,10 +490,6 @@ module ActiveRecord alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s}) end - def empty_insert_statement_value - "VALUES(NULL)" - end - protected def select(sql, name = nil, binds = []) #:nodoc: exec_query(sql, name, binds) diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 2eaad1d469..f81eb5f5d1 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -385,8 +385,8 @@ module ActiveRecord # Creates a record with values matching those of the instance attributes # and returns its id. - def create - attributes_values = arel_attributes_with_values_for_create(!id.nil?) + def create(attribute_names = @attributes.keys) + attributes_values = arel_attributes_with_values_for_create(attribute_names) new_id = self.class.unscoped.insert attributes_values self.id ||= new_id if self.class.primary_key |