Struggling with ActiveRecord auto assigning the :id attribute as the primary key even though it is a separate column.
Table - legacy-table
id - int
pk_id - int (primary key)
name - varchar2
info - varchar2
Model
class LegacyModel < ActiveRecord::Base
self.table_name = 'legacy-table'
self.primary_key = 'pk_id'
default_scope {order(:name => :asc)}
alias_attribute :other_id, :id
end
I don't care that ActiveRecord automatically assigns the primary key (pk_id) to the :id attribute however I lose all access to the actual id column. Trying to use the alias simply points me back at the primary key.
However one caveat to this issues is that from the view i can access the id column by using @legacymodel[:id]. But again when calling @legacymodel.id I get the value of the pk_id column. What i want is to be able to call @legacymodel.other_id and have it point to the id column. Instead @legacymodel.service_id, @legacymodel.id, and @legacymodel.pk_id all point to the same column pk_id
Please note that this is a legacy db and modifying the columns are out of the question. I am using Rails 4 with MySql.
Is there anyway to code around this? Why does @legacymodel[:id] give me different results then @legacymodel.id?
The answer by @cschroed did not work for me in the latest Rails (v4.2). Digging into the Rails source code, it appears that read_attribute
will also use the primary key value if the key passed equals 'id':
ID = 'id'.freeze
# Returns the value of the attribute identified by <tt>attr_name</tt> after
# it has been typecast (for example, "2004-12-12" in a date column is cast
# to a date object, like Date.new(2004, 12, 12)).
def read_attribute(attr_name, &block)
name = attr_name.to_s
name = self.class.primary_key if name == ID
_read_attribute(name, &block)
end
https://github.com/rails/rails/blob/4-2-stable/activerecord/lib/active_record/attribute_methods/read.rb
Since, the [] method uses read_attribute
, this no longer works.
I found that directly reading from the attributes hash worked instead:
# LegacyModel class
def other_id
@attributes.fetch_value('id')
end
This provided a means of bypassing read_attribute
by mimicking _read_attribute
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With