Offentliggjort torsdag d. 28. november 2013 ('denglish' only) by Walther H. Diechmann
Rails 3.2 has served us just fine, thank you – but we were eager to load (sorry, couldn't resist it) the new Rails 4.0 and I must confess that I'm convinced! 4.0 has its fair share of newness but all in all it is a very polished experience, hands down!
This article is not streaming cheers though; it is how to dodge the NoMethodError on ActiveRecord::ConnectionAdapters::ClosedTransaction
TL;DR; use Threads :)
We use Rails for a number of applications and in particular ERP. One issue with ERP is the requirement for unique IDs in documents and not just any random IDs but sequential IDs!
In a single-user environment you'd solve that easily with:
SystemParameter.next_number('a sequential counter')
and implement it somewhat along the lines of
def next_number(lbl) rec=SystemParameter.find_by_system_label(lbl) val=rec.value rec.value = rec.value.to_i + 1 rec.save val end
– but in a multi-user environment you'll have to watch out for race-conditions and what not! Here you're better of doing something like
def next_number(lbl) begin ActiveRecord::Base.connection .execute( "CALL IncrementNumber('%s')" % lbl ).first rescue return nil ensure ActiveRecord::Base.connection .reconnect! unless ActiveRecord::Base.connection.active? end end
with the ensure part only being necessary because the execute method tends to close the current connection on the mysql2 adaptor!
Well – 4.0 leaves you with this badass console output, should you ever dare calling that next_number
NoMethodError - undefined method rollback for #<ActiveRecord::ConnectionAdapters::ClosedTransaction:0x007f835c1f58b0>:
The solution is to make sure that this particular call gets its own connection – and then it can close it all it likes :)
def next_number(lbl) bc = nil result = Thread.new do begin sc = SystemParameter.connection sc.reconnect! unless sc.active? bc = sc.execute( "CALL IncrementNumber('%s')" % lbl ).first sc.close rescue end end.join bc end