Export SVN Changes to zip file
June 5th, 2010
A co-worker of mine commented that Tortoise has an easy way to export out the diff between two revisions and wondered if there was an easy way to do this on his mac. I replied “well you could write a script to parse an svn diff”. So here it is, ready for you to snag from github.
http://github.com/zerium/export_svn_changes
Instructions attached below from the README in github.
This file is designed to export the files that were modified or added between two svn revisions. It will output a corresponding zip file with the directory structure intact. Useful for when you need to push code but the server you are pushing to doesn’t have access to your repository.
Recomendations
It is reccomended that you set this to executable and add it to your path in your .profile (otherwise you will have to copy it to each repo)
Requirements
OSX is not required but, it is a requirement that “svn” and “zip” are installed in the OS.
Example:
cd [/repo_root]
export_changes.rb 1550:1560
Produces: 1550_1560.zip
Textmate Bundle - Go to File and ColdFusion Help Docs
July 23rd, 2009
Coldfusion Help ⌥⌘L
This command is bound to option-command-L (lookup). Simply click on a coldfusion method (function) ie: StructAppend or a tag
There are support files required for this command which includes all of the html help for Coldfusion (the same html files that are part of the Homesite Help files for CF 8 Download). You can download just the part that is needed and extract them to the html folder in your Downloads folder as it is looking for the files in ”~/Downloads/html”
Go to File ⌥⌘G
This command is bound to option-command-G (goto) Simply click on a line that has a cfinclude, a javascript script src tag or a css link rel tag and whether it is a relative link ”../somefile.css” or if it is a link off of the root of your project (a project must be defined for this to work) the file will open after you execute the command.
Files
You can grab the files here Steven Ross Bundle and The Help documents for ColdFusion 8
Dynamic SQL jumping a hoop (with a loop)
April 15th, 2009
Ok ignore the title, SQL is all business so lets get back to the “serious” SQL train.
So maybe you have a table that is very flat, someone did something like data1, data2, data3 as column names and you want to loop over it and insert it into a new table that can hold an infinite amount of meta-data with a relationship. Hey after all we are programming with relational databases these days.
So here are the basics, the loop (from 1 to 10):
DECLARE @intFlag INT
SET @intFlag = 1
WHILE (@intFlag <11)
BEGIN
-- DO LOOP STUFF HERE
SET @intFlag = @intFlag + 1
CONTINUE;
END
GO
So that is useful and all but, how do we create some dynamic sql with lovely concatenations?
Like so:
Declare @SQL VarChar(1000)
Select @SQL = 'INSERT new_table_name(description, status, date_due, date_complete, date_start, ref_id)'
Select @SQL = @SQL + ' SELECT descrip' + CAST(@intFlag AS varchar) + ', status' + CAST(@intFlag AS varchar) + ', due' + CAST(@intFlag AS varchar) + ', complete' + CAST(@intFlag AS varchar) + ', start' + CAST(@intFlag AS varchar) + ', old_id'
Select @SQL = @SQL + ' FROM old_table_name'
Select @SQL = @SQL + ' WHERE required_column' + CAST(@intFlag AS varchar) + ' IS NOT NULL'
Exec ( @SQL)
So now we just combine it all:
DECLARE @intFlag INT
SET @intFlag = 1
WHILE (@intFlag <11)
BEGIN
Declare @SQL VarChar(1000)
Select @SQL = 'INSERT new_table_name(description, status, date_due, date_complete, date_start, ref_id)'
Select @SQL = @SQL + ' SELECT descrip' + CAST(@intFlag AS varchar) + ', status' + CAST(@intFlag AS varchar) + ', due' + CAST(@intFlag AS varchar) + ', complete' + CAST(@intFlag AS varchar) + ', start' + CAST(@intFlag AS varchar) + ', old_id'
Select @SQL = @SQL + ' FROM old_table_name'
Select @SQL = @SQL + ' WHERE required_column' + CAST(@intFlag AS varchar) + ' IS NOT NULL'
Exec ( @SQL)
SET @intFlag = @intFlag + 1
CONTINUE;
END
GO
Ask away if there are any questions.
OOP - it's not perfect
March 13th, 2009
Ok, not trying to start a flame war but, I’m republishing this, it was from an interview with Rob Pike (works for google, really smart, had his hands in the early days of Unix). This is a great response to a question posed to him and for the record the original article is here Rob Pike Responds but, I am just publishing one part of it. I’d encourage you to read it as we should always try to solve a problem the best way possible and that is what this is about.
Question Hello!
Maybe this is an overly-asked question, but I still often ponder it. Does object-oriented design negate or diminish the future prospects of Unix’s continuing popularity?
I’ve developed in C (which I still love), but lately, I’ve been doing a lot of purely object-oriented development in Java. Using things like delegation and reusable classes have made life so much easier in many respects. Since the *nixes are so dependent upon C, I was wondering what future you see in C combined with Unix. Like I said, I love C and still enjoy developing in Unix, but there has to be a point where you build on your progress and the object-oriented languages, in my opinion, seem to be doing that.
Thank you for all your contributions!!!
Pike:
The future does indeed seem to have an OO hue. It may have bearing on Unix, but I doubt it; Unix in all its variants has become so important as the operating system of the internet that whatever the Java applications and desktop dances may lead to, Unix will still be pushing the packets around for a quite a while.
On a related topic, let me say that I’m not much of a fan of object-oriented design. I’ve seen some beautiful stuff done with OO, and I’ve even done some OO stuff myself, but it’s just one way to approach a problem. For some problems, it’s an ideal way; for others, it’s not such a good fit.
Here’s an analogy. If you want to make some physical artifact, you might decide to build it purely in wood because you like the way the grain of the wood adds to the beauty of the object. In fact many of the most beautiful things in the world are made of wood. But wood is not ideal for everything. No amount of beauty of the grain can make wood conduct electricity, or support a skyscraper, or absorb huge amounts of energy without breaking. Sometimes you need metal or plastic or synthetic materials; more often you need a wide range of materials to build something of lasting value. Don’t let the fact that you love wood blind you to the problems wood has as a material, or to the possibilities offered by other materials.
The promoters of object-oriented design sometimes sound like master woodworkers waiting for the beauty of the physical block of wood to reveal itself before they begin to work. “Oh, look; if I turn the wood this way, the grain flows along the angle of the seat at just the right angle, see?” Great, nice chair. But will you notice the grain when you’re sitting on it? And what about next time? Sometimes the thing that needs to be made is not hiding in any block of wood.
OO is great for problems where an interface applies naturally to a wide range of types, not so good for managing polymorphism (the machinations to get collections into OO languages are astounding to watch and can be hellish to work with), and remarkably ill-suited for network computing. That’s why I reserve the right to match the language to the problem, and even – often – to coordinate software written in several languages towards solving a single problem.
It’s that last point – different languages for different subproblems – that sometimes seems lost to the OO crowd. In a typical working day I probably use a half dozen languages – C, C++, Java, Python, Awk, Shell – and many more little languages you don’t usually even think of as languages – regular expressions, Makefiles, shell wildcards, arithmetic, logic, statistics, calculus – the list goes on.
Does object-oriented design have much to say to Unix? Sure, but no more than functions or concurrency or databases or pattern matching or little languages or….
Regardless of what I think, though, OO design is the way people are taught to think about computing these days. I guess that’s OK – the work does seem to get done, after all – but I wish the view was a little broader.
Learning git? This might help.
February 24th, 2009
I stumbled upon this after browsing some podcasts on rails the other day. The learning rails podcast has an episode on git (a distributed version control system). If you have heard the buzz (git is basically the new SVN, at least in hype). Go check it out
WDDXConfig - replaces SimpleConfig.cfc now with more simple!
January 20th, 2009
Well I know I just released the SimpleConfig.cfc but, I didn’t think it was as flexible as some might need. The new version uses one config file and can load any datatype that ColdFusion will understand in WDDX format, so if you already have configuration variables in your App Scope you can just write them out as a WDDX file and copy the values into “config.wddx” under the “Base” node and then just add your instances under the INSTANCES node in “config.wddx”
Click to download source files
I think this is pretty self explanatory when you take a peek at the code, I even simplified the required application.cfc code to be as easy as possible:
Application.cfc:
<cffunction name="OnApplicationStart">
<cflock type="exclusive" scope="Application" timeout="60">
<cfset WDDXConfig = createObject("component","org.ross.WDDXConfig") />
<!--- optional parameters to WDDXConfig are as follows:
WDDXConfig.init("/config/", "config.wddx", "config")
"/config/" is the mapping where your config files are
"config.wddx" is your configuration file name
"config" is the name of your Application variable where your configuration options are going
--->
<cfset WDDXConfig.init() />
</cflock>
</cffunction>
config.wddx
This file is pretty simple, if you need some help understanding what it will translate to when you run the app, just run it and see the dump of “Application”
<?xml version="1.0"?>
<wddxPacket version="1.0">
<header/>
<data>
<struct>
<var name="INSTANCES">
<!-- don't for get to iterate the length below as you add instances -->
<array length="1">
<struct>
<var name="instanceType"><string>QA</string></var>
<!-- because you could be running multiple instances on the same machine
and thus the physical name could be the same (and we can't rely on CGI variables to be clean)
we use an identifying directory name here and the identifier will be placed
into the app scope as "ACTUALPATH" incase you are unsure of the physical path to your Application.cfc
C:\mysites\steve\appname\Application.cfc or mac: /mysites/steve/appname/Application.cfc -->
<var name="identifier"><string>/Volumes/Case Sensitive/www/simpleconfig/html/</string></var>
<var name="OVER_RIDE">
<struct>
<!-- override your base settings here -->
<var name="DSNs">
<struct>
<var name="marketing"><string>marketingDSNLocal</string></var>
</struct>
</var>
</struct>
</var>
</struct>
</array>
</var>
<!-- all of your base configuration data will go here -->
<var name="BASE">
<struct>
<var name="instanceType"><string>Development</string></var>
<var name="DSNs">
<struct>
<var name="marketing"><string>marketingPROD</string></var>
</struct>
</var>
<var name="additionalConfigFiles">
<array length="1">
<!-- as an example I'm just reloading the config.wddx file into another struct,
you can do as many additional wddx based config files as you want
(structName is the substruct name and fileName is the file name)-->
<struct>
<var name="structName"><string>sample</string></var>
<var name="fileName"><string>config.wddx</string></var>
</struct>
</array>
</var>
</struct>
</var>
</struct>
</data>
</wddxPacket>
When it comes time to deploy your application it is often difficult to manage application variables that change per instance. SimpleConfig aim’s to reduce the pain in running different environments. It does this by reading two xml files and taking those variables and placing them into your application scope for you to reference by using the prefix: Application.Configuration anywhere in your application.
source files: click to download
Setup and Configuration
Ok so lets dig into the file structure. When you download the zip file you will find a few directories listed as such:
/simpleconfig/config_files
/simpleconfig/html
The “html” directory is where you want to point Apache/IIS as the web root of your application. All you need to do is add a mapping of “/config” and point it to wherever you want to put the “config_files” directory and you are ready to start tweaking your config files.
Ok so on to configuring this puppy. Point Apache/IIS to the extracted directory /simpleconfig/html as your web root (again you can skip that step for demonstration purposes and just drop the contents of the directory “simpleconfig” onto your existing web root).
Defining your environments
Now go take a look at the file: /simpleconfig/config_files/config-instances.xml:
<configuration>
<option>
<description>Local Instance</description>
<name><![CDATA[simpleconfig.local]]></name>
<value><![CDATA[config-dev.xml]]></value>
</option>
<option>
<description>Configuration Files that pertain to all instances</description>
<name><![CDATA[BASE_CONFIGURATION_FILES]]></name>
<value>
<key>
<name><![CDATA[Base Config File]]></name>
<value><![CDATA[config-base.xml]]></value>
</key>
</value>
</option>
</configuration>
As you can see there is just some xml in here that defines each environment that you will be running. When you want to add an environment you simply add another node with the appropriate details. So to edit this for your own local machine you probably want to change the node to the host name of your machine, because CGI can be mucked with too easily on the client side I opted to use the java way at getting the machine name, most likely you will just have to run the app and see the dump to get your machine’s name so you can put the appropriate name in the config-instances.xml file. Next after that is the config file that pertains to your local instance. In this case we have “config-dev.xml”.
The idea here is to use this configuration file to define any differences from your base-config for your application. So say you have an email address that you want to use in your application, you probably don’t want to use your production account info while you are developing locally. However you probably do want the same DSN name and that would be put in your config-base.xml and not overridden in your config-dev.xml.
You should also note that the first word in the description will be the name of that environment type. So if you put into the description “QA” the “CurrentMode” variable in the configuration would become “QA” instead of “Local”. This is useful when you have to add more environments that you didn’t account for initially.
Also, this gives you the ability to quickly switch and test configurations by simply changing the xml file that you are loading for that instance. So if you had a “config-qa.xml” you could easily test that configuration locally by specifying that xml file instead of the “config-dev.xml”
h2. Configuring each environment The config-base.xml file:
<configuration>
<option>
<description>Application Status Struct</description>
<name><![CDATA[applicationStatus]]></name>
<value>
<key>
<name><![CDATA[isAvailable]]></name>
<value><![CDATA[true]]></value>
</key>
<key>
<name><![CDATA[unAvailableMessageHeader]]></name>
<value><![CDATA[Website Unavailable]]></value>
</key>
<key>
<name><![CDATA[unAvailableMessageBody]]></name>
<value><![CDATA[Application is temporarily unavailable.]]></value>
</key>
</value>
</option>
<option>
<description>An application variable</description>
<name><![CDATA[somevariable]]></name>
<value><![CDATA[something you need in the app scope]]></value>
</option>
<option>
<description>Some struct that you want in the app scope</description>
<name><![CDATA[theStructName]]></name>
<value>
<key>
<name><![CDATA[structkeyOne]]></name>
<value><![CDATA[~now()]]></value>
</key>
<key>
<name><![CDATA[structKeyTwo]]></name>
<value><![CDATA[some string]]></value>
</key>
<key>
<name><![CDATA[structKeyThree]]></name>
<value><![CDATA[some other string]]></value>
</key>
</value>
</option>
</configuration>
This file is a bit bigger and it contains some interesting stuff. Basically you can put pretty much anything into your application scope. You can even put calls to coldfusion functions in your xml that will be called when the xml is read and placed into your application scope. You can see a few lines up where there is the coldfusion function “now()” being called on “structKeyThree”. You tell SimpleConfig to evaluate the function by placing a tilde (~) before the function. I think the other huge advantage here is being able to define a struct that will go into your Application.Configuration object.
You can see a struct being defined in the applicationstatus node. You see that the first node contains a node then what will be created is a struct. The first node will be the struct name ie: Application.Configuration.MyStruct and then the additional nodes under the nodes will be the key in the struct and the will be the value for that key. This is much easier to see in action. So make a change to one of the struct keys or their values and you can see it work.
About the applicationstatus node
I built this node into the guts of the application. If for some reason you need to take your application offline (some back-end system is down perhaps). You can edit the applicationstatus node and set the isAvailable node to false and the Application.cfc will throw an exception (for every request) which you can then catch and display to your users on your own custom error page. Granted you don’t have to go this route but, it is there for you to use.
Reloading your configuration files
To reload the application you simply tack on a ?reload to the query string. Note that this only works when the application is not in production mode and also when trusted cache is off.
SimpleConfig.cfc
If you take a look at org/ross/SimpleConfig.cfc there are two places for you to add in your own methods that can be called when the application is starting up. The first place is the setup() method and the second is the start() method. The setup method is designed to be used when you need to call some other code before variables are placed into the Application scope and the start() method is designed to be used after those variables have been placed into the Application scope. Both of these methods are called each time the Application is reloaded (which you can see in the Application.cfc).
I hope this is enough to get you started. It really is a simple and elegant way to handle configuration variables. I will be adding additional text as I get time that will explain how you can add more configuration data into the application scope just by adding your own xml files and editing the config-instances.xml. Here is a hint: The SimpleConfig.cfc will keep loading any of the defined xml files in the BASE_CONFIGURATION_FILES node, just make sure you structure them exactly like the other config files.
This software is licensed under the CC-GNU GPL.
Using onMissingMethod to create get/set methods
July 16th, 2008
If you create a lot of objects to store data in and are constantly creating get/set methods to handle the setting of those properties then, this will probably save you some time. Its a nice trick not to have to write all that code anymore (or even have to maintain that code if you use some sort of code generator).
Here is our component:
<!---
Author: Steve Ross http://blog.stevensross.com
Disclaimer: Free to use and distribute, please leave in the credit!
--->
<cfcomponent output="false" displayname="Simple on Missing Method Example" hint="Will let you do custom getters and setters w/o writing the code">
<cffunction name="OnMissingMethod" returnType="any" access="public" output="true" hint="Handles getters and setters">
<cfargument name="MissingMethodName" type="string" required="true" hint="The name of the missing method">
<cfargument name="MissingMethodArguments" type="struct" required="true" hint="The arguments passed in to the missing method">
<cfif LCase(arguments.MissingMethodName) CONTAINS "get">
<cfreturn getValue(replace(arguments.MissingMethodName, "get", ""))/>
<cfelseif LCase(arguments.MissingMethodName) CONTAINS "set">
<cfif StructKeyExists(arguments.MissingMethodArguments, "2")>
<cfelse>
<cfset setValue(replace(arguments.MissingMethodName, "set", ""), arguments.MissingMethodArguments)/>
</cfif>
</cfif>
</cffunction>
<cffunction name="setValue" returnType="void" access="private" output="true" hint="internal setter method" >
<cfargument name="name" type="string" required="true" hint="name of property to set">
<cfargument name="value" type="any" required="true" hint="value of property">
<cfset this[arguments.name] = arguments.value.1 />
</cffunction>
<cffunction name="getValue" returnType="any" access="private" output="true" hint="internal getter method" >
<cfargument name="name" type="string" required="true" hint="name of property to set">
<cfif StructKeyExists(this, arguments.name)>
<cfreturn this[arguments.name]>
<cfelse>
<cfreturn ""/>
</cfif>
</cffunction>
</cfcomponent>
I’m not really going to go into how this works, put simply all I am doing is a string replace to get the name and then I’m taking the argument and putting it as the data for that variable. Then when you call the getter I’m just striping out the word ‘get’ and finding your data. Now if you haven’t set the data we return empty string.
So save the above example and call it “Simple.cfc”
Create another CFM file in the same directory and call it “test.cfm”
Now you can see this work by putting this code in test.cfm:
<cfset testObj = CreateObject("Component", "Simple")/>
<cfset testStruct = {foo='bar'}/>
<cfset testObj.setTestStruct(testStruct)/>
<h4>We call the testObj.getTestStruct() Method</h4>
<cfdump var="#testObj.getTestStruct()#">
<h4>Notice the "testStruct" property</h4>
<cfdump var="#testObj#" label="dumping the entire object">
A more practical example:
<cfset User = CreateObject("Component", "Simple")/>
<cfset User.setFirstName('Steven')/>
<cfset User.setLastName('Ross')/>
<cfset tmpInfo = {password='dont do it', id='XXX'}/>
<cfset User.setInfo(tmpInfo)/>
<cfdump var="#User#" label="dumping the entire object">
Hope this helps someone out on what you can do with MissingMethod in ColdFusion 8
ColdFusion XMLSearch Behavior / Gotcha
April 21st, 2008
Just thought I’d point out that there is some odd behavior in XMLSearch() results. See the example below:
<cfxml variable="test">
<test>
<node>
<nodes>
<nodeline>node1</nodeline>
</nodes>
<nodes>
<nodeline>node2</nodeline>
</nodes>
<nodes>
<nodeline>node3</nodeline>
</nodes>
</node>
</test>
</cfxml>
<cfset results = XMLSearch(test, "//nodes")/>
<cfset results1 = results[1]/>
<cfdump var="#results1#">
Now if you run this you will see a dump that shows the root node as nodes but, if you try to reference the results as: results1.nodes.nodeline you will get an error. You have to reference the array as the root result. So the path to the nodelines becomes result.nodeline.
Hope that saves someone out there some headaches. I think that XMLSearch needs some major modification but, that may break backward compatibility so I guess Adobe is kinda locked in to how it works currently. For example, XMLSearch has some powerful features built in via XPath. However the way that ColdFusion returns the results is a bit bizzare. Well maybe not bizzare but, definately too verbose. So if you ask ColdFusion to return just the text assigned to the nodelines in the above example, it will return a full xml doc instead of just an array of values. So you end up parsing the data again. It would be really nice to just get an array of results back instead of an array of xml docs back. But, I digress.
If you want to learn XPath, just check out the docs here
ColdFusion 8 Caching Stored Procs bug?
April 18th, 2008
If you aren’t aware, yes you can cache the results of stored procs in ColdFusion 8 using cachedwithin. However, be aware that ColdFusion only caches the first result set so If you are returning multiple result sets you are only going to get the first result set. So if you happen to be thinking ahead while you are coding and start out by setting the cachedwithin parameter you will never see multiple result sets.
To give credit where credit is due, my co-worker, Matt Hintze discovered this yesterday when we were trying to figure out why we weren’t getting multiple result sets back from a proc that we knew returned multiple sets every time it ran.
Hopefully this will be addressed by Adobe as caching multiple result sets would be the expected behavior inside a proc.
Update: Coldfusion Help in Textmate livedocs
January 21st, 2008
I noticed that there was a bug in the code. If you had a function ie: <cfset Request.something = “something”> and you put your cursor on the “Request” it would send you to the docs for <cfset> I fixed it so that it correctly sends you to whatever your cursor is on. Here is the text file for the bundle and instructions on installing it.
You don’t need to get the CFTextmate Bundle for this to work in Textmate. Hopefully the command will be included in the next release.
How to add this command to Textmate:
- Copy the contents of this text file
- Load textmate and then select bunde > bundle editor > show bundle editor (ctrl option cmd B)
- Create a new command (you can just click on your bundle name and add it there) settings for the new command: Save: Nothing, command(s): Paste code here, Input: None, Output: Show as HTML, Key Equivilent (I chose option, cmd L), scope selector: text, html, cfm
- Open Bundles > Bundle Editor > Reload Bundles
Start Coldfusion 8 from the command line - OS X
January 17th, 2008
If you want to start CF from the command line instead of using the launcher just do this:
sudo /Applications/JRun4/bin/jrun -autorestart -nohup -start cfusion
No idea why that was so hard to find (really it wasn’t just had to dig though some shell scripts in the bin directory) Just figured I’d post it for those that would rather see std out in the terminal. I have trouble with the Coldfusion Launcher as well. Half the time it hangs on firing up the server.
Textmate Built-in Coldfusion 8 Help Docs (ie: F1 homesite)
January 15th, 2008
After looking over the shoulder of one of my peers after he downloaded the latest Coldfusion 8 support for Homesite (yes, I said Homesite), I saw him use the good old F1 on a tag/method to the help docs. Homesite! The product that refuses to die. Adobe is still supporting it so there must be a bunch of CF developers out there still refusing to give it up. Well I’m not switching back to windows for Homesite (I really didn’t use it then either).
After he installed the code support for CF 8 he simply placed his cursor over a tag and hit F1 and bang the help docs come up. It started to bug me that this wasn’t in Textmate and I thought it would be useful. After all its in Homesite! So I worked on this command for Textmate which does the same thing except it uses the CF 8 Livedocs as the source. It supports all the current tags and functions. So head on over to the CF Textmate Google group and grab a copy. Hopefully it will be in the next release of CFTextmate.
Below is the link and the instructions are included in the jump (4th message down). While your at it why don’t you jump in and contribute to the CFTextmate bundle?
Coldfusion 8 Help Docs for Textmate
Also, I hear everyone is looking for a new CF IDE from Adobe. I’m perfectly happy with Textmate, I’d rather them concentrate on adding features to CF than building an IDE. Just seems like a waste.
Enjoy the addition to Textmate!
Https, SSL Certs and Coldfusion
February 27th, 2007
So you are tasked with using SSL (either in cfhttp or some other protocol). Here are the issues: #1 you don't have the cert and #2 when you get the cert you find out that it has been generated in a way that CF doesn't approve of (the name doesn't match the dns entry or the name in the cert is something arbitrary and you are using the IP to connect to the server).
Read the rest of this entryColdfusion writing binary file to output stream
January 29th, 2007
I recently had a need to grab a binary file from an http response and write that back to the output stream instead of writing the file to the disk. The reason was because we were using the flash client to play the file and it was requesting the file from a cfc call.
Read the rest of this entry