I have a legacy table with three fields: NAME, VALUE, ID. Naturally, the
primary key is NAME and not ID. The problem is that ActiveRecord updates
the NAME primary key when I try to set ID: object.id=1 will update the
NAME attribute and not the ID attribute. I can only update the ID
attribute via WRITE_ATTRIBUTE (see IRB example below).
I can work around this issue, but it breaks FactoryGirl (and presumably
others). Any thoughts on workarounds or if I’m doing something wrong?
Thanks!
Pete
class Sequence < ActiveRecord::Base
set_primary_key “name”
…
TiBook $ script/console
a = Sequence.first
=> #<Sequence name: “default”, value: 1001, id: 1>
a.id = 2
=> 2
a
=> #<Sequence name: 2, value: 1001, id: 1>
a.send(‘id=’, 3)
=> 3
a
=> #<Sequence name: 3, value: 1001, id: 1>
a.write_attribute(‘id’, 3)=> 3
a
=> #<Sequence name: 3, value: 1001, id: 3>
On Dec 10, 10:50am, Pete C. [email protected] wrote:
I have a legacy table with three fields: NAME, VALUE, ID. Naturally, the
primary key is NAME and not ID. The problem is that ActiveRecord updates
the NAME primary key when I try to set ID: object.id=1 will update the
NAME attribute and not the ID attribute. I can only update the ID
attribute via WRITE_ATTRIBUTE (see IRB example below).
Can you create a view in the legacy database to remap the field names?
If so, then your ActiveRecord model can just point to the view and
save you
a lot of headaches.
–
Eric
On 10 December 2010 18:50, Pete C. [email protected] wrote:
I have a legacy table with three fields: NAME, VALUE, ID. Naturally, the
primary key is NAME and not ID. The problem is that ActiveRecord updates
the NAME primary key when I try to set ID: object.id=1 will update the
NAME attribute and not the ID attribute. I can only update the ID
attribute via WRITE_ATTRIBUTE (see IRB example below).
Can you change the field names in the table or do you have a legacy
app to go with the legacy table that needs to keep working?
Colin
Its a good suggestion but sadly the answer is no. There is another app
that also accesses this data and so I probably can’t change it.
Is this behavior expected or not? It was a bit of a surprise to me.
E. Litwin wrote in post #967734:
Can you create a view in the legacy database to remap the field names?
If so, then your ActiveRecord model can just point to the view and
save you
a lot of headaches.
–
Eric
Pete C. wrote in post #967747:
Its a good suggestion but sadly the answer is no. There is another app
that also accesses this data and so I probably can’t change it.
Is this behavior expected or not? It was a bit of a surprise to me.
A little unexpected… but the source makes it obvious what is
happening.
module ActiveRecord
module AttributeMethods
module Write
blah blah blah
def write_attribute(attr_name, value)
attr_name = attr_name.to_s
attr_name = self.class.primary_key if attr_name == 'id'
Seems like it ought to check and see if
set_primary_key = something other than “id”
is set in the model and behave accordingly (if “id” is not the model’s
primary key, then don’t remap attr_name to self.class.primary_key).
Of course, I’ve just looked at this one small snippet of code, and there
may be other places in the AR code base that use ‘id’ as a name alias
for the primary key (whatever it is), so removing that bit of
redirection might totally hose up AR.
On Dec 10, 1:31pm, Pete C. [email protected] wrote:
If so, then your ActiveRecord model can just point to the view and
save you
a lot of headaches.
[Please post responses below, not above, i.e. no top posting]
My suggestion to create a view would not affect other applications.
The whole point of the view is to create an abstraction for your
application without a side effect. So I will ask again, can you create
a view in your legacy database?
–
Eric
Ar Chron wrote in post #967748:
module ActiveRecord
module AttributeMethods
module Write
blah blah blah
def write_attribute(attr_name, value)
attr_name = attr_name.to_s
attr_name = self.class.primary_key if attr_name == 'id'
Thanks for the dope-slap that I should have looked in the code itself. I
should also have mentioned that this is using Rails 2.3.5. Turns out
that object.id is always going to point to the primary key.
module ActiveRecord
class Base
# Sets the primary ID.
def id=(value)
write_attribute(self.class.primary_key, value)
end
(not sure if I showed the hierarchy to the function correctly)
E. Litwin wrote in post #967757:
My suggestion to create a view would not affect other applications.
The whole point of the view is to create an abstraction for your
application without a side effect. So I will ask again, can you create
a view in your legacy database?
Thanks for clarifying, I didn’t realize the distinction when I read your
message the first time. I don’t know the answer but it certainly seems
like it should work.
Thanks to everyone for your help, very good ideas and very informative.
Much appreciated!
Pete
On Dec 10, 2010, at 4:52 PM, Ar Chron wrote:
Seems like it ought to check and see if
set_primary_key = something other than “id”
is set in the model and behave accordingly (if “id” is not the model’s
primary key, then don’t remap attr_name to self.class.primary_key).
Of course, I’ve just looked at this one small snippet of code, and
there
may be other places in the AR code base that use ‘id’ as a name alias
for the primary key (whatever it is), so removing that bit of
redirection might totally hose up AR.
Just a very kludgy though on this Friday afternoon, but could you use
‘iD’ as your attribute?
The database adapter probably isn’t too kind, but you might just have
to define your own:
def iD
read_attribute(‘iD’)
end
def iD=(value)
write_attribute(‘iD’, value)
end
-Rob
(Hey, I said that it was a kludge! Oh, and it’s also completely
untested.)
Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/