Class: DataMapper::Transaction
- Inherits:
-
Object
- Object
- DataMapper::Transaction
- Extended by:
- Chainable
- Defined in:
- lib/dm-core/transaction.rb
Defined Under Namespace
Modules: Adapter, Model, Repository, Resource
Instance Method Summary collapse
-
#begin ⇒ Object
private
Begin the transaction.
-
#commit ⇒ Object
private
Commit the transaction.
-
#initialize(*things) ⇒ Transaction
constructor
Create a new Transaction.
-
#link(*things) ⇒ Object
private
Associate this Transaction with some things.
-
#method_missing(meth, *args, &block) ⇒ Object
private
TODO: document.
-
#primitive_for(adapter) ⇒ Object
private
TODO: document.
-
#rollback ⇒ Object
private
Rollback the transaction.
-
#within ⇒ Object
private
Execute a block within this Transaction.
Methods included from Chainable
Constructor Details
#initialize(*things) ⇒ Transaction
Create a new Transaction
In fact, it just calls #link with the given arguments at the end of the constructor.
15 16 17 18 19 20 21 22 23 24 |
# File 'lib/dm-core/transaction.rb', line 15 def initialize(*things) @transaction_primitives = {} @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 |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args, &block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
TODO: document
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/dm-core/transaction.rb', line 177 def method_missing(meth, *args, &block) if args.size == 1 && args.first.kind_of?(Adapters::AbstractAdapter) if (match = meth.to_s.match(/^(.*)_if_(none|begin|rollback|commit)$/)) if self.respond_to?(match[1], true) if state_for(args.first).to_s == match[2] self.send(match[1], args.first) end else super end elsif (match = meth.to_s.match(/^(.*)_unless_(none|begin|rollback|commit)$/)) if self.respond_to?(match[1], true) unless state_for(args.first).to_s == match[2] self.send(match[1], args.first) end else super end else super end else super end end |
Instance Method Details
#begin ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Begin the transaction
Before #begin is called, the transaction is not valid and can not be used.
80 81 82 83 84 85 86 87 88 |
# File 'lib/dm-core/transaction.rb', line 80 def begin unless @state == :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]) @state = :begin end |
#commit ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Commit the transaction
If no block is given, it will simply commit any changes made since the
Transaction did #begin.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/dm-core/transaction.rb', line 100 def commit if block_given? unless @state == :none raise "Illegal state for commit with block: #{@state}" end begin self.begin rval = within { |*block_args| yield(*block_args) } if @state == :begin self.commit end return rval rescue Exception => exception if @state == :begin self.rollback end raise exception end else unless @state == :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]) @state = :commit end end |
#link(*things) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Associate this Transaction with some things.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/dm-core/transaction.rb', line 46 def link(*things) unless @state == :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 |
#primitive_for(adapter) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
TODO: document
205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/dm-core/transaction.rb', line 205 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 ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Rollback the transaction
Will undo all changes made during the transaction.
134 135 136 137 138 139 140 141 |
# File 'lib/dm-core/transaction.rb', line 134 def rollback unless @state == :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]) @state = :rollback end |
#within ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
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.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/dm-core/transaction.rb', line 153 def within unless block_given? raise 'No block provided' end unless @state == :begin raise "Illegal state for within: #{@state}" end @adapters.each do |adapter, state| adapter.push_transaction(self) end begin yield self ensure @adapters.each do |adapter, state| adapter.pop_transaction end end end |