PageRenderTime 443ms CodeModel.GetById 181ms app.highlight 1ms RepoModel.GetById 160ms app.codeStats 0ms

/wheels/model/transactions.cfm

http://cfwheels.googlecode.com/
ColdFusion | 90 lines | 75 code | 10 blank | 5 comment | 1 complexity | 177b167c82a6e3a2a8aefba40ed56bbf MD5 | raw file
 1<cffunction name="invokeWithTransaction" returntype="any" access="public" output="false" hint="Runs the specified method within a single database transaction."
 2	examples=
 3	'
 4		<!--- This is the method to be run inside a transaction --->
 5		<cffunction name="tranferFunds" returntype="boolean" output="false">
 6			<cfargument name="personFrom">
 7			<cfargument name="personTo">
 8			<cfargument name="amount">
 9			<cfif arguments.personFrom.withdraw(arguments.amount) and arguments.personTo.deposit(arguments.amount)>
10				<cfreturn true>
11			<cfelse>
12				<cfreturn false>
13			</cfif>
14		</cffunction>
15
16		<cfset david = model("Person").findOneByName("David")>
17		<cfset mary = model("Person").findOneByName("Mary")>
18		<cfset invokeWithTransaction(method="transferFunds", personFrom=david, personTo=mary, amount=100)>
19	'
20	categories="model-class" chapters="transactions" functions="new,create,save,update,updateByKey,updateOne,updateAll,delete,deleteByKey,deleteOne,deleteAll">
21	<cfargument name="method" type="string" required="true" hint="Model method to run.">
22	<cfargument name="transaction" type="string" default="commit" hint="See documentation for @save.">
23	<cfargument name="isolation" type="string" default="read_committed" hint="Isolation level to be passed through to the `cftransaction` tag. See your CFML engine's documentation for more details about `cftransaction`'s `isolation` attribute.">
24	
25	<cfset var loc = {} />
26	
27	<cfset loc.methodArgs = $setProperties(properties=StructNew(), argumentCollection=arguments, filterList="method,transaction,isolation", setOnModel=false, $useFilterLists=false)>
28	<cfset loc.connectionArgs = this.$hashedConnectionArgs()>
29	<cfset loc.closeTransaction = true>
30	
31	<cfif not StructKeyExists(variables, arguments.method)>
32		<cfset $throw(type="Wheels", message="Model method not found!", extendedInfo="The method `#arguments.method#` does not exist in this model.")>
33	</cfif>
34	
35	<!--- create the marker for an open transaction if it doesn't already exist --->
36	<cfif not StructKeyExists(request.wheels.transactions, loc.connectionArgs)>
37		<cfset request.wheels.transactions[loc.connectionArgs] = false>
38	</cfif>
39	
40	<!--- if a transaction is already marked as open, change the mode to 'none', otherwise open one --->
41	<cfif request.wheels.transactions[loc.connectionArgs]>	
42		<cfset arguments.transaction = "none">
43		<cfset loc.closeTransaction = false>
44	<cfelse>
45		<cfset request.wheels.transactions[loc.connectionArgs] = true>
46	</cfif>
47	
48	<!--- run the method ---> 
49	<cfswitch expression="#arguments.transaction#">
50		<cfcase value="commit,rollback">
51			<cftransaction action="begin" isolation="#arguments.isolation#">
52				<cftry>
53					<cfset loc.returnValue = $invoke(method=arguments.method, componentReference=this, invokeArgs=loc.methodArgs)>
54					<cfif IsBoolean(loc.returnValue) and loc.returnValue>
55						<cftransaction action="#arguments.transaction#" />
56					<cfelse>
57						<cftransaction action="rollback" />
58					</cfif>
59					<cfcatch type="any">
60						<cftransaction action="rollback" />
61						<cfset request.wheels.transactions[loc.connectionArgs] = false>
62						<cfrethrow />
63					</cfcatch>
64				</cftry>
65			</cftransaction>
66		</cfcase>
67		<cfcase value="none">
68			<cfset loc.returnValue = $invoke(method=arguments.method, componentReference=this, invokeArgs=loc.methodArgs)>
69		</cfcase>
70		<cfdefaultcase>
71			<cfset $throw(type="Wheels", message="Invalid transaction type", extendedInfo="The transaction type of `#arguments.transaction#` is invalid. Please use `commit`, `rollback` or `none`.")>
72		</cfdefaultcase>
73	</cfswitch>
74	
75	<!--- close the connection --->
76	<cfif loc.closeTransaction>
77		<cfset request.wheels.transactions[loc.connectionArgs] = false>
78	</cfif>
79
80	<!--- check the return type --->
81	<cfif not IsBoolean(loc.returnValue)>
82		<cfset $throw(type="Wheels", message="Invalid return type", extendedInfo="Methods invoked using `invokeWithTransaction` must return a boolean value.")>
83	</cfif>
84	
85	<cfreturn loc.returnValue />
86</cffunction>
87
88<cffunction name="$hashedConnectionArgs" returntype="string" access="public" output="false">
89	<cfreturn Hash(variables.wheels.class.connection.datasource & variables.wheels.class.connection.username & variables.wheels.class.connection.password)>
90</cffunction>