提交 f437f110 编写于 作者: R Rafael Mendonça França

Merge pull request #15924 from sgrif/sg-write-unknown-column

Move writing unknown column exception to null attribute
* Fix subtle bugs regarding attribute assignment on models with no primary
key. `'id'` will no longer be part of the attributes hash.
*Sean Griffin*
* Deprecate automatic counter caches on `has_many :through`. The behavior was * Deprecate automatic counter caches on `has_many :through`. The behavior was
broken and inconsistent. broken and inconsistent.
......
...@@ -90,6 +90,11 @@ def initialize(name) ...@@ -90,6 +90,11 @@ def initialize(name)
def value def value
nil nil
end end
def with_value_from_database(value)
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{name}`"
end
alias_method :with_value_from_user, :with_value_from_database
end end
class Uninitialized < Attribute # :nodoc: class Uninitialized < Attribute # :nodoc:
......
...@@ -83,12 +83,9 @@ def reset_primary_key #:nodoc: ...@@ -83,12 +83,9 @@ def reset_primary_key #:nodoc:
end end
def get_primary_key(base_name) #:nodoc: def get_primary_key(base_name) #:nodoc:
return 'id' if base_name.blank? if base_name && primary_key_prefix_type == :table_name
case primary_key_prefix_type
when :table_name
base_name.foreign_key(false) base_name.foreign_key(false)
when :table_name_with_underscore elsif base_name && primary_key_prefix_type == :table_name_with_underscore
base_name.foreign_key base_name.foreign_key
else else
if ActiveRecord::Base != self && table_exists? if ActiveRecord::Base != self && table_exists?
......
...@@ -70,10 +70,6 @@ def write_attribute_with_type_cast(attr_name, value, should_type_cast) ...@@ -70,10 +70,6 @@ def write_attribute_with_type_cast(attr_name, value, should_type_cast)
attr_name = attr_name.to_s attr_name = attr_name.to_s
attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
unless has_attribute?(attr_name) || self.class.columns_hash.key?(attr_name)
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'"
end
if should_type_cast if should_type_cast
@attributes.write_from_user(attr_name, value) @attributes.write_from_user(attr_name, value)
else else
......
...@@ -381,7 +381,7 @@ def tables(name = nil, database = nil, like = nil) #:nodoc: ...@@ -381,7 +381,7 @@ def tables(name = nil, database = nil, like = nil) #:nodoc:
end end
def table_exists?(name) def table_exists?(name)
return false unless name return false unless name.present?
return true if tables(nil, nil, name).any? return true if tables(nil, nil, name).any?
name = name.to_s name = name.to_s
......
...@@ -521,7 +521,7 @@ def to_ary # :nodoc: ...@@ -521,7 +521,7 @@ def to_ary # :nodoc:
def init_internals def init_internals
pk = self.class.primary_key pk = self.class.primary_key
unless @attributes.include?(pk) if pk && !@attributes.include?(pk)
@attributes.write_from_database(pk, nil) @attributes.write_from_database(pk, nil)
end end
......
...@@ -253,6 +253,15 @@ def test_case_sensitive_attributes_hash ...@@ -253,6 +253,15 @@ def test_case_sensitive_attributes_hash
assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.first.attributes assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.first.attributes
end end
def test_attributes_without_primary_key
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'developers_projects'
end
assert_equal klass.column_names, klass.new.attributes.keys
assert_not klass.new.attributes.key?('id')
end
def test_hashes_not_mangled def test_hashes_not_mangled
new_topic = { :title => "New Topic" } new_topic = { :title => "New Topic" }
new_topic_values = { :title => "AnotherTopic" } new_topic_values = { :title => "AnotherTopic" }
......
...@@ -134,14 +134,22 @@ def test_supports_primary_key ...@@ -134,14 +134,22 @@ def test_supports_primary_key
end end
def test_primary_key_returns_value_if_it_exists def test_primary_key_returns_value_if_it_exists
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'developers'
end
if ActiveRecord::Base.connection.supports_primary_key? if ActiveRecord::Base.connection.supports_primary_key?
assert_equal 'id', ActiveRecord::Base.connection.primary_key('developers') assert_equal 'id', klass.primary_key
end end
end end
def test_primary_key_returns_nil_if_it_does_not_exist def test_primary_key_returns_nil_if_it_does_not_exist
klass = Class.new(ActiveRecord::Base) do
self.table_name = 'developers_projects'
end
if ActiveRecord::Base.connection.supports_primary_key? if ActiveRecord::Base.connection.supports_primary_key?
assert_nil ActiveRecord::Base.connection.primary_key('developers_projects') assert_nil klass.primary_key
end end
end end
......
...@@ -8,6 +8,7 @@ def self.extended(base) ...@@ -8,6 +8,7 @@ def self.extended(base)
table_name => 'id' table_name => 'id'
} }
column :id, :integer
column :name, :string column :name, :string
column :age, :integer column :age, :integer
column :avatar, :binary column :avatar, :binary
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册