Here is a script I use to monitor pages for changes that don't supply feeds. It features the ability to check only a subset of the page using regular expression filters. You feed it a YAML file of the pages you want to monitor and optionally the email address you wish to send the results to (if you are running it as a cron job). The links file might originally look something like this:
I say "originally" because the script will add some information to this file to keep track of whether or not the page has changed on subsequent invocations. Here is the script:
The script tries to use last modified and etag headers if the server supports them, but will fall back to creating an md5 hash of the page if necessary. To scrape just a portion of the page, pass in "start" and "end" regular expressions in the YAML to instruct the script where to start and stop scraping.
Tuesday, November 11, 2008
Tuesday, October 28, 2008
attachment_fu with Optional Attachment...again
I wrote about this previously...attachment_fu is not mean to be used to provide a file attachment as an optional attribute of a model with other attributes. If you want to combine a model with its own attributes and an attachment have a look at Paperclip. attachment_fu is a great plugin but the attachment is supposed to live in its own model.
So why am I writing about this again? Well, recently a project that I had worked on before where someone put the attachment directly in another model was updated and then had some plugin problems. I solved the problems by upgrading some of the plugins, including attachment_fu. This upgrade resulted in further breakage of this attachment_fu within another model / optional attachment problem. Now, attachment_fu calls attr_accessible :uploaded_data from the has_attachment directive so you will have to open up the model for your other attributes for bulk assignment. This will look something like this:
And as before, the plugin must be patched to prevent errors that would occur when updating or deleting a model that doesn't have an attachment. The patch is here which works against the current attachment_fu:
Now the real question is, why haven't I either 1) fixed this the right way or 2) switched to Paperclip by now? Lack of time and an already existing file structure laid out by attachment_fu I suppose...but this is getting ridiculous.
So why am I writing about this again? Well, recently a project that I had worked on before where someone put the attachment directly in another model was updated and then had some plugin problems. I solved the problems by upgrading some of the plugins, including attachment_fu. This upgrade resulted in further breakage of this attachment_fu within another model / optional attachment problem. Now, attachment_fu calls attr_accessible :uploaded_data from the has_attachment directive so you will have to open up the model for your other attributes for bulk assignment. This will look something like this:
And as before, the plugin must be patched to prevent errors that would occur when updating or deleting a model that doesn't have an attachment. The patch is here which works against the current attachment_fu:
Now the real question is, why haven't I either 1) fixed this the right way or 2) switched to Paperclip by now? Lack of time and an already existing file structure laid out by attachment_fu I suppose...but this is getting ridiculous.
Sunday, October 05, 2008
Picasa Web Album Command Line Upload
I wrote this code some time ago before Picasa Web Albums had a good uploading solution for Linux users. This code uses the the Google Data APIs. While there is a better upload solution for Linux now (Picasa for Linux) some of you, like me, might prefer a command line driven upload method. This allows you to upload a batch of photos by issuing a command like this:
So, for example, you might issue a command like this:
This would initiate an upload of all the jpg files in the current directory to my Picasa Web Albums under an album name of Honolulu with a throttling delay of 3 seconds. The picasa script, which calls my java code, is a simple script as follows:
And finally, the java code that does all the magic, note that you will need to compile / run against some Google Data API jar files as indicated in the comments:
So, for example, you might issue a command like this:
This would initiate an upload of all the jpg files in the current directory to my Picasa Web Albums under an album name of Honolulu with a throttling delay of 3 seconds. The picasa script, which calls my java code, is a simple script as follows:
And finally, the java code that does all the magic, note that you will need to compile / run against some Google Data API jar files as indicated in the comments:
Wednesday, October 01, 2008
Raphael Bakes a Nice Pie
Raphaƫl is a very cool Javascript library that provides an abstraction over the the vector graphics capabilities built into today's browsers. I cooked up a little example that demonstrates the usage of Raphael to make a pie chart component:
This example seems to work well on all modern browsers and will even work on IE back to at least version 6. It uses SVG on most browsers and VML on the IE line - this is some very impressive work by Dmitry Baranovskiy.
So what is so good about SVG and VML over a regular canvas? Events my friend, events!
This example seems to work well on all modern browsers and will even work on IE back to at least version 6. It uses SVG on most browsers and VML on the IE line - this is some very impressive work by Dmitry Baranovskiy.
So what is so good about SVG and VML over a regular canvas? Events my friend, events!
Saturday, September 27, 2008
Ext JS Custom TreeNodeUI
I wrote this some time ago and then noticed that Blogger blasted the indentation in the code snippets so I'm only posting it now.
Hey, this should be a good dump - I needed an Ext JS tree with a custom TreeNodeUI. In addition to the usual text, I wanted each TreeNode to feature a select box that would allow a selection (and Ajax saving of the selection) to be made for each node. While the Ext JS API Documentation is pretty good, it doesn't always provide the information needed when trying to "step outside the box." (This framework is just dying for someone to write a book about it...) After just a little head scratching I found writing such a custom TreeNodeUI to be fairly straight forward.
The first thing I needed to do was to define my SelectNodeUI having it call its parent constructor on instantiation:
After that, I needed to extend my SelectNodeUI, inheriting from the standard TreeNodeUI, while overriding the renderElements and onSelectChange methods. The renderElements method is overridden to add the select box (look for the sel variable). The onSelectChange method is overriden to prevent the normal focus change which would unfortunately cause the select box to close immediately when first selected. This looks like a lot of code but is primarily a copy of the TreeNodeUI renderElements method with the rendering of the select box added. I've marked the parts I've added / changed with // DJB: comments:
Take special note of the building of the selectHtml string from the COMMAND_HIERARCHY_TYPE_ARRAY which has been written into the page in the format of [["label text", id], ...] and how the correct option is selected after the selectHTML has been rendered into a select box DOM node.
Now that the custom tree node is defined and ready to use the loader for the TreePanel needs to be informed about which UI providers are available. This is done by setting the uiProviders property of the loader property of the TreePanel:
With this code in place, a mapping has been defined between the string "select" and the SelectNodeUI. If the JSON for a tree node comes back with the value uiProvider: "select", the SelectNodeUI will be used to render that tree node, otherwise, it will fall back to using a regular TreeNodeUI. Keep in mind that such a tree node will also need a typeId property so that the proper option can be selected in the select box. With Rails the JSON for these tree nodes might be rendered with a method like this:
Unfortunately, as the comment says in the code, Internet Exploder does not bubble change events. Thus each select node has its own change listener that calls selectChange (otherwise I could have wired up a single change listener at a level above these tree nodes in the DOM tree). selectChange is a fairly straight forward function which uses an Ajax call to save the new state for the tree node's underlying model:
Finally, the select boxes are slightly taller than the normal content held at a tree node and thus mess up the lines that are drawn connecting the + / - expanders along the left side of the tree. Instead of fixing this up to look write I would recommend just turning the tree lines off. This can be done with by setting up the TreePanel with either the lines: false or useArrows: true properties. With lines: false the tree will render with the same old + / - expanders but won't render the lines. With useArrows: true the tree will render with a look that is supposed to emulate "Vista," using small triangles and drawing no lines. I'm not sure what this "Vista" thing is and I couldn't seem sudo apt-get install it ;-).
Hey, this should be a good dump - I needed an Ext JS tree with a custom TreeNodeUI. In addition to the usual text, I wanted each TreeNode to feature a select box that would allow a selection (and Ajax saving of the selection) to be made for each node. While the Ext JS API Documentation is pretty good, it doesn't always provide the information needed when trying to "step outside the box." (This framework is just dying for someone to write a book about it...) After just a little head scratching I found writing such a custom TreeNodeUI to be fairly straight forward.
The first thing I needed to do was to define my SelectNodeUI having it call its parent constructor on instantiation:
After that, I needed to extend my SelectNodeUI, inheriting from the standard TreeNodeUI, while overriding the renderElements and onSelectChange methods. The renderElements method is overridden to add the select box (look for the sel variable). The onSelectChange method is overriden to prevent the normal focus change which would unfortunately cause the select box to close immediately when first selected. This looks like a lot of code but is primarily a copy of the TreeNodeUI renderElements method with the rendering of the select box added. I've marked the parts I've added / changed with // DJB: comments:
Take special note of the building of the selectHtml string from the COMMAND_HIERARCHY_TYPE_ARRAY which has been written into the page in the format of [["label text", id], ...] and how the correct option is selected after the selectHTML has been rendered into a select box DOM node.
Now that the custom tree node is defined and ready to use the loader for the TreePanel needs to be informed about which UI providers are available. This is done by setting the uiProviders property of the loader property of the TreePanel:
With this code in place, a mapping has been defined between the string "select" and the SelectNodeUI. If the JSON for a tree node comes back with the value uiProvider: "select", the SelectNodeUI will be used to render that tree node, otherwise, it will fall back to using a regular TreeNodeUI. Keep in mind that such a tree node will also need a typeId property so that the proper option can be selected in the select box. With Rails the JSON for these tree nodes might be rendered with a method like this:
Unfortunately, as the comment says in the code, Internet Exploder does not bubble change events. Thus each select node has its own change listener that calls selectChange (otherwise I could have wired up a single change listener at a level above these tree nodes in the DOM tree). selectChange is a fairly straight forward function which uses an Ajax call to save the new state for the tree node's underlying model:
Finally, the select boxes are slightly taller than the normal content held at a tree node and thus mess up the lines that are drawn connecting the + / - expanders along the left side of the tree. Instead of fixing this up to look write I would recommend just turning the tree lines off. This can be done with by setting up the TreePanel with either the lines: false or useArrows: true properties. With lines: false the tree will render with the same old + / - expanders but won't render the lines. With useArrows: true the tree will render with a look that is supposed to emulate "Vista," using small triangles and drawing no lines. I'm not sure what this "Vista" thing is and I couldn't seem sudo apt-get install it ;-).
Wednesday, September 24, 2008
Attach and Detach SQL Server Databases from the Command Line with osql
I'm usually working with MySQL but I also work on a project that uses SQL Server for a back end. Lately I've been writing a script that massages some data from a CSV dump from another system into our system. This led to a rather, rinse, repeat cycle of switching to SQL Server in VMWare, detaching the existing database, copying a fresh copy of the database into place, and re-attaching the data when doing sample runs of the script against the data. This got to be a real hassle! Finally I took the time to learn how to detach and attach a SQL Server database using command line osql commands. Here is an example of a script that detaches the database, copies clean files into position, and then re-attaches the database:
Enjoy!
Enjoy!
Sunday, September 21, 2008
Generating Combinations in Ruby and Javascript
Hey, time to dust off your discrete math text! (The one I used is Discrete Mathematics and Its Applications by Kenneth H. Rosen). The number of combinations of r items that can be selected from n items is given by the formula = n!/r!(n - r)! (note to self, render this with MathML). The following three code blocks show how to return those combinations in Ruby, Javascript, and Javascript with Prototype. Note that these functions yield (in Ruby) or do a callback with (Javascript) each combination. These could easily be modified to return an array of the combinations. After the three code snippets is a live example of the Javascript code.
First the Ruby:
Now the Javascript:
And finally Javascript with Prototype (wow, now like Ruby):
Wow, if that doesn't make you want to learn Prototype using Prototype and script.aculo.us: You Never Knew JavaScript Could Do This! then nothing will.
Subscribe to:
Posts (Atom)
