Forum: Ruby on Rails set_table_name and self.table_name

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
F3e0b49da3f2d0b35fe6236ac90b75c5?d=identicon&s=25 Nola Stowe (Guest)
on 2006-05-15 20:35
I have some legacy tables that I used set_table_name on, I'm attempting
to write a method that will get key value from a sequence table and then
update it and return a value. I'm hoping to put this in the base
ActiveRecord method so I would like to reference the table name with
self.table_name  or something...

class Contacts < ActiveRecord::Base
    set_table_name "contact_person"
    set_primary_key "p_key"

    def get_next_id
       ActiveRecord::Base.connection.execute("update
#{self.table_name}_seq SET id = id+1")
       res = ActiveRecord::Base.connection.select_value("SELECT * FROM
#{self.table_name}_seq");
       res['id']
    end

    def before_create
        self.id = get_next_id
    end
end

if I replace #{self.table_name} with the hard coded table name, this
works well.


The error I get is this:

NoMethodError: undefined method `table_name' for #<Contacts:0x408bd4f4>
        from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.2/lib/active_record/base.rb:1792:in
`method_missing'



Thanks :)

~

~
F5c118aaeb5bb7162db613a37e595be8?d=identicon&s=25 Mick Sharpe (micksharpe)
on 2006-05-15 20:44
table_name is a class method - you need to use Contacts.table_name
F3e0b49da3f2d0b35fe6236ac90b75c5?d=identicon&s=25 Nola Stowe (Guest)
on 2006-05-15 21:25
Mick Sharpe wrote:
> table_name is a class method - you need to use Contacts.table_name

I want to extend ActiveRecord similar to specified here:
http://wiki.rubyonrails.com/rails/pages/ExtendingA...

and put the get_next_id method in there, is there a way I could get the
model class name by some variable?
24d2f8804e6bb4b7ea6bd11e0a586470?d=identicon&s=25 Jeremy Kemper (Guest)
on 2006-05-15 22:01
(Received via mailing list)
On May 15, 2006, at 11:35 AM, Nola Stowe wrote:
>     set_primary_key "p_key"
>         self.id = get_next_id
>     end
> end
>
> if I replace #{self.table_name} with the hard coded table name, this
> works well.

Use self.class.table_name.  You also have self.class.sequence_name
(both reader and writer) available to you.

Best,
jeremy
F3e0b49da3f2d0b35fe6236ac90b75c5?d=identicon&s=25 Nola Stowe (Guest)
on 2006-05-15 22:33
Jeremy Kemper wrote:

> Use self.class.table_name.  You also have self.class.sequence_name
> (both reader and writer) available to you.

Thanks guys...

Here's the final code

class Contact < ActiveRecord::Base
    set_table_name "contact_person"
    set_primary_key "p_key"

    def get_next_id
       seq_table = self.class.table_name << "_seq"
       ActiveRecord::Base.connection.execute("update #{seq_table} SET id
= id+1")
       ActiveRecord::Base.connection.select_value("SELECT * FROM
#{seq_table}");
    end

    def before_create
        self.id = get_next_id
    end
end
24d2f8804e6bb4b7ea6bd11e0a586470?d=identicon&s=25 Jeremy Kemper (Guest)
on 2006-05-15 23:07
(Received via mailing list)
On May 15, 2006, at 1:33 PM, Nola Stowe wrote:
>     set_primary_key "p_key"
>
>     def get_next_id
>        seq_table = self.class.table_name << "_seq"

This appends _seq to table name then assigns it; you want
   seq_table = self.class.table_name + '_seq'

On a more topical note, this method of generating unique ids requires
an exclusive row lock before update; otherwise, the operation is not
atomic and clients will receive non-unique ids (consider clients 1 &
2: update 1, update 2, select 1, select 2. Now both have id + 2.)

What database are you using? Surely there is a better way..

Best,
jeremy
F3e0b49da3f2d0b35fe6236ac90b75c5?d=identicon&s=25 Nola Stowe (Guest)
on 2006-05-16 19:27
Jeremy Kemper wrote:
> On May 15, 2006, at 1:33 PM, Nola Stowe wrote:
>>     set_primary_key "p_key"
>>
>>     def get_next_id
>>        seq_table = self.class.table_name << "_seq"
>
> This appends _seq to table name then assigns it; you want
>    seq_table = self.class.table_name + '_seq'
>
> On a more topical note, this method of generating unique ids requires
> an exclusive row lock before update; otherwise, the operation is not
> atomic and clients will receive non-unique ids (consider clients 1 &
> 2: update 1, update 2, select 1, select 2. Now both have id + 2.)
>
> What database are you using? Surely there is a better way..
>
> Best,
> jeremy

Thanks Jeremy ... I didn't know that about << ...

Well, we've been using this sequence system for about 3 years now with
no incindent. I can see your point, but I don't think we will worry
about that..we don't have that much traffic. We will be dropping this
seq tables soon, this was just a "hack" to get things to work OK until
then.

I blogged about my experience here if anyone is interested ... post any
improvements please! :)

http://codesnipers.com/?q=node/303
24d2f8804e6bb4b7ea6bd11e0a586470?d=identicon&s=25 Jeremy Kemper (Guest)
on 2006-05-16 20:39
(Received via mailing list)
On May 16, 2006, at 10:27 AM, Nola Stowe wrote:
>> On a more topical note, this method of generating unique ids requires
>
> Well, we've been using this sequence system for about 3 years now with
> no incindent. I can see your point, but I don't think we will worry
> about that..we don't have that much traffic. We will be dropping this
> seq tables soon, this was just a "hack" to get things to work OK until
> then.

It's as easy as switching from
   ActiveRecord::Base.connection.execute("update #{seq_table} SET id
= id+1")
   model.id = ActiveRecord::Base.connection.select_value("SELECT *
FROM #{seq_table}")
to
   current_id = ActiveRecord::Base.connection.select_value("SELECT id
FROM #{seq_table} FOR UPDATE")
   ActiveRecord::Base.connection.execute("update #{seq_table} SET id
= id+1")
   model.id = current_id + 1


> I blogged about my experience here if anyone is interested ... post
> any
> improvements please! :)
>
> http://codesnipers.com/?q=node/303

Thanks for the summary!

jeremy
F3e0b49da3f2d0b35fe6236ac90b75c5?d=identicon&s=25 Nola Stowe (Guest)
on 2006-05-16 21:38
Jeremy Kemper wrote:
>    current_id = ActiveRecord::Base.connection.select_value("SELECT id
> FROM #{seq_table} FOR UPDATE")
>    ActiveRecord::Base.connection.execute("update #{seq_table} SET id
> = id+1")
>    model.id = current_id + 1

ok.. thanks ...

Except I had to convert the id to an int first

model.id = current_id.to_i + 1
This topic is locked and can not be replied to.