Class: DataMapper::Transaction
- Inherits:
-
Object
- Object
- DataMapper::Transaction
- Defined in:
- lib/dm-core/transaction.rb
Instance Attribute Summary collapse
-
#adapters ⇒ Object
readonly
Returns the value of attribute adapters.
-
#state ⇒ Object
readonly
Returns the value of attribute state.
-
#transaction_primitives ⇒ Object
readonly
Returns the value of attribute transaction_primitives.
Instance Method Summary collapse
-
#begin ⇒ Object
Begin the transaction.
-
#commit(&block) ⇒ Object
Commit the transaction.
-
#initialize(*things, &block) ⇒ Transaction
constructor
Create a new DataMapper::Transaction.
-
#link(*things, &block) ⇒ Object
Associate this Transaction with some things.
- #method_missing(meth, *args, &block) ⇒ Object
- #primitive_for(adapter) ⇒ Object
-
#rollback ⇒ Object
Rollback the transaction.
-
#within(&block) ⇒ Object
Execute a block within this Transaction.
Constructor Details
#initialize(*things, &block) ⇒ Transaction
Create a new DataMapper::Transaction
In fact, it just calls #link with the given arguments at the end of the constructor.
16 17 18 19 20 21 22 |
# File 'lib/dm-core/transaction.rb', line 16 def initialize(*things, &block) @transaction_primitives = {} @state = :none @adapters = {} link(*things) commit(&block) if block_given? end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args, &block) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/dm-core/transaction.rb', line 146 def method_missing(meth, *args, &block) if args.size == 1 && args.first.is_a?(DataMapper::Adapters::AbstractAdapter) if (match = meth.to_s.match(/^(.*)_if_(none|begin|prepare|rollback|commit)$/)) if self.respond_to?(match[1], true) self.send(match[1], args.first) if state_for(args.first).to_s == match[2] else super end elsif (match = meth.to_s.match(/^(.*)_unless_(none|begin|prepare|rollback|commit)$/)) if self.respond_to?(match[1], true) self.send(match[1], args.first) unless state_for(args.first).to_s == match[2] else super end else super end else super end end |
Instance Attribute Details
#adapters ⇒ Object (readonly)
Returns the value of attribute adapters.
6 7 8 |
# File 'lib/dm-core/transaction.rb', line 6 def adapters @adapters end |
#state ⇒ Object (readonly)
Returns the value of attribute state.
6 7 8 |
# File 'lib/dm-core/transaction.rb', line 6 def state @state end |
#transaction_primitives ⇒ Object (readonly)
Returns the value of attribute transaction_primitives.
6 7 8 |
# File 'lib/dm-core/transaction.rb', line 6 def transaction_primitives @transaction_primitives end |
Instance Method Details
#begin ⇒ Object
Begin the transaction
Before #begin is called, the transaction is not valid and can not be used.
68 69 70 71 72 73 |
# File 'lib/dm-core/transaction.rb', line 68 def begin raise "Illegal state for begin: #{@state}" unless @state == :none 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(&block) ⇒ Object
If no block is given, it will simply commit any changes made since the Transaction did #begin.
Commit the transaction
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/dm-core/transaction.rb', line 86 def commit(&block) if block_given? raise "Illegal state for commit with block: #{@state}" unless @state == :none begin self.begin rval = within(&block) self.commit if @state == :begin return rval rescue Exception => e self.rollback if @state == :begin raise e end else raise "Illegal state for commit without block: #{@state}" unless @state == :begin each_adapter(:prepare_adapter, [:rollback_and_close_adapter_if_begin, :rollback_prepared_and_close_adapter_if_prepare]) each_adapter(:commit_adapter, [:log_fatal_transaction_breakage]) each_adapter(:close_adapter, [:log_fatal_transaction_breakage]) @state = :commit end end |
#link(*things, &block) ⇒ Object
Associate this Transaction with some things.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/dm-core/transaction.rb', line 42 def link(*things, &block) raise "Illegal state for link: #{@state}" unless @state == :none things.each do |thing| if thing.is_a?(Array) link(*thing) elsif thing.is_a?(DataMapper::Adapters::AbstractAdapter) @adapters[thing] = :none elsif thing.is_a?(DataMapper::Repository) link(thing.adapter) elsif thing.is_a?(Class) && thing.ancestors.include?(DataMapper::Resource) link(*thing.repositories) elsif thing.is_a?(DataMapper::Resource) link(thing.model) else raise "Unknown argument to #{self}#link: #{thing.inspect}" end end return commit(&block) if block_given? return self end |
#primitive_for(adapter) ⇒ Object
168 169 170 171 172 |
# File 'lib/dm-core/transaction.rb', line 168 def primitive_for(adapter) raise "Unknown adapter #{adapter}" unless @adapters.include?(adapter) raise "No primitive for #{adapter}" unless @transaction_primitives.include?(adapter) @transaction_primitives[adapter] end |
#rollback ⇒ Object
Rollback the transaction
Will undo all changes made during the transaction.
112 113 114 115 116 117 118 |
# File 'lib/dm-core/transaction.rb', line 112 def rollback raise "Illegal state for rollback: #{@state}" unless @state == :begin each_adapter(:rollback_adapter_if_begin, [:rollback_and_close_adapter_if_begin, :close_adapter_if_none]) each_adapter(:rollback_prepared_adapter_if_prepare, [:rollback_prepared_and_close_adapter_if_begin, :close_adapter_if_none]) each_adapter(:close_adapter_if_open, [:log_fatal_transaction_breakage]) @state = :rollback end |
#within(&block) ⇒ Object
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.
Execute a block within this Transaction.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/dm-core/transaction.rb', line 131 def within(&block) raise "No block provided" unless block_given? raise "Illegal state for within: #{@state}" unless @state == :begin @adapters.each do |adapter, state| adapter.push_transaction(self) end begin return yield(self) ensure @adapters.each do |adapter, state| adapter.pop_transaction end end end |