Set_table_name and self.table_name


#1

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:inmethod_missing’

Thanks :slight_smile:

~

~


#2

table_name is a class method - you need to use Contacts.table_name


#3

Mick S. 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/ExtendingActiveRecordExample

and put the get_next_id method in there, is there a way I could get the
model class name by some variable?


#4

Jeremy K. 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


#5

On May 15, 2006, at 1:33 PM, Nola S. 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


#6

On May 15, 2006, at 11:35 AM, Nola S. 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


#7

On May 16, 2006, at 10:27 AM, Nola S. 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! :slight_smile:

http://codesnipers.com/?q=node/303

Thanks for the summary!

jeremy


#8

Jeremy K. wrote:

On May 15, 2006, at 1:33 PM, Nola S. 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! :slight_smile:

http://codesnipers.com/?q=node/303


#9

Jeremy K. 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