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 :) ~ ~ -- Posted via http://www.ruby-forum.com/.
table_name is a class method - you need to use Contacts.table_name -- Posted via http://www.ruby-forum.com/.
Mick Sharpe wrote:> table_name is a class method - you need to use Contacts.table_nameI 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? -- Posted via http://www.ruby-forum.com/.
On May 15, 2006, at 11:35 AM, Nola Stowe wrote:> 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.Use self.class.table_name. You also have self.class.sequence_name (both reader and writer) available to you. Best, jeremy
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 -- Posted via http://www.ruby-forum.com/.
On May 15, 2006, at 1:33 PM, Nola Stowe wrote:> 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"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
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, > jeremyThanks 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 -- Posted via http://www.ruby-forum.com/.
On May 16, 2006, at 10:27 AM, Nola Stowe wrote:> 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.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/303Thanks for the summary! jeremy
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 + 1ok.. thanks ... Except I had to convert the id to an int first model.id = current_id.to_i + 1 -- Posted via http://www.ruby-forum.com/.