Use _read_attribute to properly query id?

Support primary key dirty tracking when ID is a composite
primary key with an id column.

Introduces `ActiveRecord::AttributeMethods::Query#_query_attribute`
to bypass id reader.
This commit is contained in:
Gannon McGibbon 2023-06-22 23:24:47 -05:00
parent 16a5bdc511
commit abb6b207c0
2 changed files with 30 additions and 19 deletions

View File

@ -41,9 +41,9 @@ module ActiveRecord
# Queries the primary key column's value.
def id?
if self.class.composite_primary_key?
@primary_key.all? { |col| query_attribute(col) }
@primary_key.all? { |col| _query_attribute(col) }
else
query_attribute(@primary_key)
_query_attribute(@primary_key)
end
end

View File

@ -13,27 +13,38 @@ module ActiveRecord
def query_attribute(attr_name)
value = self.public_send(attr_name)
case value
when true then true
when false, nil then false
else
if !type_for_attribute(attr_name) { false }
if Numeric === value || !value.match?(/[^0-9]/)
!value.to_i.zero?
else
return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value)
!value.blank?
end
elsif value.respond_to?(:zero?)
!value.zero?
else
!value.blank?
end
end
query_cast_attribute(attr_name, value)
end
def _query_attribute(attr_name) # :nodoc:
value = self._read_attribute(attr_name.to_s)
query_cast_attribute(attr_name, value)
end
alias :attribute? :query_attribute
private :attribute?
private
def query_cast_attribute(attr_name, value)
case value
when true then true
when false, nil then false
else
if !type_for_attribute(attr_name) { false }
if Numeric === value || !value.match?(/[^0-9]/)
!value.to_i.zero?
else
return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value)
!value.blank?
end
elsif value.respond_to?(:zero?)
!value.zero?
else
!value.blank?
end
end
end
end
end
end