Object
Create a new Transaction
@see Transaction#link
In fact, it just calls link with the given arguments at the end of the constructor.
@api public
# File lib/dm-transactions.rb, line 38 def initialize(*things) @transaction_primitives = {} self.state = :none @adapters = {} link(*things) if block_given? warn "Passing block to #{self.class.name}.new is deprecated (#{caller[0]})" commit { |*block_args| yield(*block_args) } end end
Begin the transaction
Before begin is called, the transaction is not valid and can not be used.
@api private
# File lib/dm-transactions.rb, line 103 def begin unless none? raise "Illegal state for begin: #{state}" end each_adapter(:connect_adapter, [:log_fatal_transaction_breakage]) each_adapter(:begin_adapter, [:rollback_and_close_adapter_if_begin, :close_adapter_if_none]) self.state = :begin end
@api private
# File lib/dm-transactions.rb, line 16 def begin? state == :begin end
Commit the transaction
If no block is given, it will simply commit any changes made since the Transaction did #begin.
@param block<Block> a block (taking the one argument, the Transaction) to
execute within this transaction. The transaction will begin and commit around the block, and roll back if an exception is raised.
@api private
# File lib/dm-transactions.rb, line 123 def commit if block_given? unless none? raise "Illegal state for commit with block: #{state}" end begin self.begin rval = within { |*block_args| yield(*block_args) } rescue Exception => exception if begin? rollback end raise exception ensure unless exception if begin? commit end return rval end end else unless begin? raise "Illegal state for commit without block: #{state}" end each_adapter(:commit_adapter, [:log_fatal_transaction_breakage]) each_adapter(:close_adapter, [:log_fatal_transaction_breakage]) self.state = :commit end end
@api private
# File lib/dm-transactions.rb, line 26 def commit? state == :commit end
Associate this Transaction with some things.
@param [Object] things
the things you want this Transaction associated with: Adapters::AbstractAdapter subclasses will be added as adapters as is. Arrays will have their elements added. Repository will have it's own @adapters added. Resource subclasses will have all the repositories of all their properties added. Resource instances will have all repositories of all their properties added.
@param [Proc] block
a block (taking one argument, the Transaction) to execute within this transaction. The transaction will begin and commit around the block, and rollback if an exception is raised.
@api private
# File lib/dm-transactions.rb, line 69 def link(*things) unless none? raise "Illegal state for link: #{state}" end things.each do |thing| case thing when DataMapper::Adapters::AbstractAdapter @adapters[thing] = :none when DataMapper::Repository link(thing.adapter) when DataMapper::Model link(*thing.repositories) when DataMapper::Resource link(thing.model) when Array link(*thing) else raise "Unknown argument to #{self.class}#link: #{thing.inspect} (#{thing.class})" end end if block_given? commit { |*block_args| yield(*block_args) } else self end end
@api private
# File lib/dm-transactions.rb, line 204 def method_missing(method, *args, &block) first_arg = args.first return super unless args.size == 1 && first_arg.kind_of?(Adapters::AbstractAdapter) return super unless match = method.to_s.match(/\A(.*)_(if|unless)_(none|begin|rollback|commit)\z/) action, condition, expected_state = match.captures return super unless respond_to?(action, true) state = state_for(first_arg).to_s execute = (condition == 'if') == (state == expected_state) send(action, first_arg) if execute end
@api private
# File lib/dm-transactions.rb, line 11 def none? state == :none end
@api private
# File lib/dm-transactions.rb, line 220 def primitive_for(adapter) unless @adapters.include?(adapter) raise "Unknown adapter #{adapter}" end unless @transaction_primitives.include?(adapter) raise "No primitive for #{adapter}" end @transaction_primitives[adapter] end
Rollback the transaction
Will undo all changes made during the transaction.
@api private
# File lib/dm-transactions.rb, line 160 def rollback unless begin? raise "Illegal state for rollback: #{state}" end each_adapter(:rollback_adapter_if_begin, [:rollback_and_close_adapter_if_begin, :close_adapter_if_none]) each_adapter(:close_adapter_if_open, [:log_fatal_transaction_breakage]) self.state = :rollback end
@api private
# File lib/dm-transactions.rb, line 21 def rollback? state == :rollback end
Execute a block within this Transaction.
No begin, commit or rollback is performed in within, but this Transaction will pushed on the per thread stack of transactions for each adapter it is associated with, and it will ensures that it will pop the Transaction away again after the block is finished.
@param block<Block> the block of code to execute.
@api private
# File lib/dm-transactions.rb, line 179 def within unless block_given? raise 'No block provided' end unless begin? raise "Illegal state for within: #{state}" end adapters = @adapters adapters.each_key do |adapter| adapter.push_transaction(self) end begin yield self ensure adapters.each_key do |adapter| adapter.pop_transaction end end end
Generated with the Darkfish Rdoc Generator 2.