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”
#{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’
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…
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!
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!
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 forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.