Discussion:
ActiveRecord aliases 'id' to primary key
Pete Campbell
2010-12-10 18:50:30 UTC
Permalink
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 $ irb
>> 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>

--
Posted via http://www.ruby-forum.com/.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
E. Litwin
2010-12-10 20:30:55 UTC
Permalink
On Dec 10, 10:50 am, Pete Campbell <li...-***@public.gmane.org> 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

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Pete Campbell
2010-12-10 21:31:27 UTC
Permalink
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

--
Posted via http://www.ruby-forum.com/.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Ar Chron
2010-12-10 21:52:47 UTC
Permalink
Pete Campbell 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.

--
Posted via http://www.ruby-forum.com/.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Rob Biedenharn
2010-12-10 22:05:20 UTC
Permalink
On Dec 10, 2010, at 4:52 PM, Ar Chron wrote:

> Pete Campbell 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.

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 Biedenharn
Rob-***@public.gmane.org http://AgileConsultingLLC.com/
rab-/VpnD74mH8+00s0LW7PaslaTQe2KTcn/@public.gmane.org http://GaslightSoftware.com/

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Pete Campbell
2010-12-11 02:19:21 UTC
Permalink
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)

--
Posted via http://www.ruby-forum.com/.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
E. Litwin
2010-12-10 22:42:39 UTC
Permalink
On Dec 10, 1:31 pm, Pete Campbell <li...-***@public.gmane.org> wrote:
> 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.

[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

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+***@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Pete Campbell
2010-12-11 02:24:51 UTC
Permalink
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

--
Posted via http://www.ruby-forum.com/.

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Colin Law
2010-12-10 20:33:41 UTC
Permalink
On 10 December 2010 18:50, Pete Campbell <lists-***@public.gmane.org> 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

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/***@public.gmane.org
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Loading...