<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:georss="http://www.georss.org/georss" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><id>tag:blogger.com,1999:blog-25066620</id><updated>2009-07-12T17:35:46.759-05:00</updated><title type="text">Ruby, Rails, Merb blog: Snakes, Gems &amp; Coffee</title><subtitle type="html">&lt;p&gt;Topics already covered in this blog: &lt;a href="http://snakesgemscoffee.blogspot.com/search/label/idioms"&gt;Ruby Idioms&lt;/a&gt;, &lt;a href="http://snakesgemscoffee.blogspot.com/search/label/rails"&gt;Ruby on Rails&lt;/a&gt;, &lt;a href="http://snakesgemscoffee.blogspot.com/search/label/restful"&gt;RESTful design&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Going forward you will see a lot of posts about: &lt;a href="http://snakesgemscoffee.blogspot.com/search/label/merb"&gt;Merb&lt;/a&gt;, Ruby 1.9, Server benchmarks, performance, tuning.&lt;/p&gt;</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://geek.susanpotter.net/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default?start-index=26&amp;max-results=25" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>115</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/SnakesGemsCoffee" type="application/atom+xml" /><feedburner:emailServiceId>SnakesGemsCoffee</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry><id>tag:blogger.com,1999:blog-25066620.post-5982449507200889600</id><published>2009-07-03T10:05:00.006-05:00</published><updated>2009-07-03T10:44:46.751-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="design patterns" /><title type="text">Design Patterns Book Club</title><content type="html">I just discovered that &lt;a href="http://www.ustream.tv/channel/hashrocket" target="_new"&gt;Hashrocket has a video book club&lt;/a&gt; where people can join in the conversation with a live videocast on USTREAM or watch older episodes on their own schedule.  They are currently going through &lt;a href="http://www.amazon.com/Design-Patterns-Ruby-Addison-Wesley-Professional/dp/0321490452/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1246633743&amp;sr=8-1&amp;tag=supo-20"&gt;Russ Olson's Design Patterns in Ruby&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is a great idea, kudos to Hashrocket.&lt;br /&gt;&lt;br /&gt;I watched the latest episode on the &lt;a href="http://www.ustream.tv/recorded/1700942" target="_new"&gt;Strategy pattern&lt;/a&gt; and had a couple of thoughts I would love Desi and the rest of Hashrocket to consider for subsequent episodes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I liked that this specific episode wasn't very long (I know you were a little worried)&lt;/li&gt;&lt;li&gt;I think discussing anti-patterns that could be solved with this pattern you are discussing the episode is very valid (as the person sitting next to Desi said).  Perhaps that could be explored more.  Note: I have only seen that one episode so perhaps you do this in other episodes much more, but if you don't please consider it, because I feel that anti-patterns are very important to identify.  &lt;strong&gt;&lt;em&gt;Think of the design patterns as the treatment or medicine and the anti-patterns as the symptoms.  Physicians need to be acutely aware of the symptoms and symptom combinations to be effective at prescribing the best course of treatment or medication.  Therefore we should be teaching software engineers in the same way.&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Also please consider putting the name of the design pattern under discussion in the title of the video for archival purposes.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Thanks goes to Hashrocket for the great idea and work of putting it together!  It's about time the Ruby community starts to mature w.r.t. language-neutral concepts and these efforts will hopefully help those that came into software development from a less formal software engineering education path (I used to be one of them and had to learn from scratch myself) with a little more assistance. It was pretty lonely bookwork and experimental projects for me to learn this stuff when I first started out.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-5982449507200889600?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/5982449507200889600/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=5982449507200889600" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/5982449507200889600" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/5982449507200889600" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/p40r110hrVM/design-patterns-book-club.html" title="Design Patterns Book Club" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/07/design-patterns-book-club.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-5308617635880711251</id><published>2009-05-29T13:00:00.013-05:00</published><updated>2009-06-02T10:16:47.337-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Jabber" /><category scheme="http://www.blogger.com/atom/ns#" term="SOA" /><category scheme="http://www.blogger.com/atom/ns#" term="HTTP" /><category scheme="http://www.blogger.com/atom/ns#" term="Google Wave" /><category scheme="http://www.blogger.com/atom/ns#" term="Service Oriented Architecture" /><category scheme="http://www.blogger.com/atom/ns#" term="web services" /><category scheme="http://www.blogger.com/atom/ns#" term="google" /><category scheme="http://www.blogger.com/atom/ns#" term="XMPP" /><title type="text">Google Wave is not the answer, XMPP is!</title><content type="html">Since yesterday afternoon (my time) all over the Twittersphere (and blogosphere) I kept hearing a ton of great reviews of the Google Wave API/protocol and how it will revolutionize communication and collaboration on the web.&lt;br /&gt;&lt;br /&gt;This morning I watched the Google Wave demonstration from yesterday and I have to say I am completely underwhelmed considering everyone else's reactions were ridiculously positive and had nothing measured or thoughtful to say about it.&lt;br /&gt;&lt;br /&gt;You can find my initial reaction of it, &lt;a href="http://tumblelog.susanpotter.net/post/114911182/google-wave-is-just-a-simple-xmpp-extension-shrink"&gt;&lt;em&gt;"Google Wave is just a simple &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; extnesion"&lt;/em&gt;, on my tumblelog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As someone that has had to write &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; extensions for clients and my own internal apps, servers, API interfaces (mostly distributed monitoring of services, but a few more for media processing) I am saddened that anyone would think the current Google Wave protocol (which is just an &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; extension) is extraordinarily ground breaking.  There have been a number of existing extensions that tried to do VERY VERY similar things already and specific features of Google Wave were already exactly defined.&lt;br /&gt;&lt;br /&gt;What made the demonstration of Google Wave yesterday &lt;em&gt;appear&lt;/em&gt; so impressive were the applications: the wave client and the web embedding.  The responsiveness of the web application really made it stand out, NOT the underlying Google Wave protocol/API.&lt;br /&gt;&lt;br /&gt;For those who have never really gotten their hands dirty with &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; in any real technical way, I expected they would not really know what it already provided in &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt;.  Many &lt;em&gt;"geeks"&lt;/em&gt; hyping up Google Wave seemed to think &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; only supported instant messaging.  That just happened to be the most popular and apparent &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; extension, which many people call Jabber.  &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; itself is a lot more far reaching than just an instant messaging protocol and the fact that Google Wave was based on top of &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; should tell you how flexible it is.  Yes that is right, Google may not have really made a big deal about it (why would they if they can get extra credit when it isn't due), but Google Wave &lt;strong&gt;is&lt;/strong&gt; just an &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; extension and compared to other extensions I have had to interface with, not a particularly complicated one.&lt;br /&gt;&lt;br /&gt;Sure the &lt;strong&gt;&lt;em&gt;applications&lt;/em&gt;&lt;/strong&gt; that Google demonstrated as part of the Google Wave presentation were nifty for personal communication, but are they really ground breaking, multipurpose, or ubiquitous?  No, it is only as ground breaking, multipurpose and ubiquitous as it's applications make it.&lt;br /&gt;&lt;br /&gt;Let us all now return to earth for a moment and praise Google for the things they do really well like web applications, but let us not pretend that Google is the mover and shaker in terms of the visionary of future underlying protocols.  They still advocate developing &lt;acronym title="HyperText Transfer Protocol"&gt;HTTP&lt;/acronym&gt; applications for the future.&lt;br /&gt;&lt;br /&gt;HyperText Transfer Protocol (&lt;acronym title="HyperText Transfer Protocol"&gt;HTTP&lt;/acronym&gt;) is virtually on every digital device made by man today, but does it really lend itself to providing the distributed service oriented architecture we should be striving for and the protocol of the &lt;em&gt;future&lt;/em&gt;?  REST is not about the &lt;acronym title="HyperText Transfer Protocol"&gt;HTTP&lt;/acronym&gt; protocol.  RESTful APIs can be creating in a number of ways and through a lot of different protocols.&lt;br /&gt;&lt;br /&gt;My take is (from a technical level) &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; ought to be the protocol of the future, NOT &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; on just the back-end and then adding tons of bloatware in between the client and the service just so that we can create an API or UI on top of an antiquated protocol (&lt;acronym title="HyperText Transfer Protocol"&gt;HTTP&lt;/acronym&gt;) that has seen better days.&lt;br /&gt;&lt;br /&gt;Anyone want to create a truly modular &lt;acronym title="Extensible Messaging and Presence Protocol"&gt;XMPP&lt;/acronym&gt; "browser" for the new &lt;em&gt;"web"&lt;/em&gt; with me?  Email &lt;code&gt;me&lt;/code&gt; at &lt;code&gt;susanpotter&lt;/code&gt; dot &lt;code&gt;net&lt;/code&gt; if you want to join the future.  &lt;br /&gt;&lt;br /&gt;UPDATE: Please subscribe to the &lt;a href="http://groups.google.com/group/jointhefuture" target="_new"&gt;"Join the Future" Google Group&lt;/a&gt; if you want to get involved in the XMPP browser project.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Related Links&lt;/h4&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://xmpp.org/" target="_new"&gt;XMPP Standards Foundation&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://xmpp.org/protocols/" target="_new"&gt;XMPP Protocols&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://xmpp.org/extensions/" target="_new"&gt;XMPP Open Extensions&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-5308617635880711251?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/5308617635880711251/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=5308617635880711251" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/5308617635880711251" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/5308617635880711251" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/OSee13OPVFM/google-wave-is-not-answer-xmpp-is.html" title="Google Wave is not the answer, XMPP is!" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">10</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/05/google-wave-is-not-answer-xmpp-is.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-9189369663339915909</id><published>2009-05-20T16:13:00.004-05:00</published><updated>2009-05-20T16:53:58.937-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="functional programming" /><category scheme="http://www.blogger.com/atom/ns#" term="currying" /><category scheme="http://www.blogger.com/atom/ns#" term="erlang" /><title type="text">Erlang doesn't support currying? News to me!</title><content type="html">I keep seeing developers who only glance at Erlang and think that &lt;strong&gt;currying&lt;/strong&gt; isn't supported.  &lt;strong&gt;Nothing could be further from the truth...&lt;/strong&gt;&lt;em&gt;unless you are defining &lt;strong&gt;currying&lt;/strong&gt; support only in terms of specific syntactic sugar in a language for currying.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;So let us step back and define what currying support really means:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Currying is the process of transforming a function that takes multiple arguments into a function that takes just a single argument and returns another function if any arguments are still needed.&lt;br /&gt;&lt;cite&gt;&lt;a href="http://www.haskell.org/haskellwiki/Currying" target="_new"&gt;http://www.haskell.org/haskellwiki/Currying&lt;/a&gt;&lt;/cite&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Let us look at a simple (but hopefully not too contrived, albeit it _slightly_ contrived) example:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;%% currying_example.erl&lt;br /&gt;-module(currying_example).&lt;br /&gt;&lt;br /&gt;-compile([export_all]).&lt;br /&gt;&lt;br /&gt;multiply(X, Y) -&gt; X*Y.&lt;br /&gt;doubler() -&gt; fun(X) -&gt; multiply(2, X) end.&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;In your erl shell try the following:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;1&gt; c(currying_example).&lt;br /&gt;{ok,currying_example}&lt;br /&gt;2&gt; D = currying_example:doubler().&lt;br /&gt;#Fun&lt;currying_example.0.96239340&gt;&lt;br /&gt;3&gt; D(6).&lt;br /&gt;12&lt;br /&gt;4&gt; q().&lt;br /&gt;ok&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see in the module code above, Erlang supports what is called &lt;em&gt;anonymous functions&lt;/em&gt; (e.g. fun (X) -&gt; somePredefineFunction(OtherVarOrConst, X) end), which then allows us to manufacture single argument functions in a way that is clear and expressive in the code IMO.&lt;br /&gt;&lt;br /&gt;For those that haven't been following the functional programming debates over the last week or two around the blogosphere, please see the following blog posts (some are pretty funny and will make you smile at least twice with their intended absurdity):&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://enfranchisedmind.com/blog/posts/scala-not-functional/" rel="nofollow" target="_new"&gt;Scala is not a functional programming language&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.reddit.com/goto?id=8krbo" rel="nofollow" target="_new"&gt;Erlang is not a programming language&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://conal.net/blog/posts/the-c-language-is-purely-functional/" rel="nofollow" target="_new"&gt;The C language is purely functional&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://12monkeys.co.uk/2009/05/16/erlang-is-pragmatic.html" rel="nofollow" target="_new"&gt;Erlang is pragmatic&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Previous posts on this blog that are related are:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://geek.susanpotter.net/2009/04/scala-vs-erlang-debate-part-1-managers.html"&gt;Scala vs Erlang Debate, Part 1: Manager's Overview&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://geek.susanpotter.net/2009/04/scala-vs-erlang-debate-part-2-geek-off.html"&gt;Scala vs Erlang Debate, Part 2: Geek Off&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I will try to put together a few snippets on currying support in Python, Javascript and Ruby tonight after my Greek class (which I am late for now) if I have time as a quick exercise:)&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-9189369663339915909?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/9189369663339915909/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=9189369663339915909" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/9189369663339915909" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/9189369663339915909" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/Eg5UrbGiCQY/erlang-doesnt-support-currying-news-to.html" title="Erlang doesn't support currying? News to me!" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/05/erlang-doesnt-support-currying-news-to.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-4349350825811956698</id><published>2009-05-18T12:16:00.005-05:00</published><updated>2009-05-18T12:39:49.008-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="open source" /><category scheme="http://www.blogger.com/atom/ns#" term="oss" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter twitter4r" /><category scheme="http://www.blogger.com/atom/ns#" term="REST" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter4r" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter" /><category scheme="http://www.blogger.com/atom/ns#" term="opensource" /><title type="text">Twitter4R 0.3.1 and the future</title><content type="html">Hi Twitter4R users,&lt;br /&gt;&lt;br /&gt;I know I have been rather absent in terms of my Twitter4R contributions and ongoing development, but despite my absence I have &lt;em&gt;_finally_&lt;/em&gt; officially released 0.3.1 with a lot more new features and a few bug fixes more than I initially expected to release 0.3.1 with.&lt;br /&gt;&lt;br /&gt;Some of the goodies included in the official 0.3.1 release are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Added &lt;em&gt;raw&lt;/em&gt; Twitter Search API support.  Meaning you can use any of the HTTP parameters the Twitter HTTP-based Search API will expect.  E.g. &lt;code&gt;twitter.search(:to =&gt; "twitter4r", :rpp =&gt; 10)&lt;/code&gt; or &lt;code&gt;twitter.search(:q =&gt; "twitter4r", :rpp =&gt; 15, :geocode =&gt; "40.112186,-88.207592,250km")&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Profile, theme API coverage on Twitter REST API.&lt;/li&gt;&lt;li&gt;Social Graphing API. E.g. &lt;code&gt;twitter.graph(:friends, user)&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Added "reply" support at all levels (low-level to model-level)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Bugfix:&lt;/strong&gt; the infamous &lt;code&gt;URI.encode&lt;/code&gt; to &lt;code&gt;CGI.escape&lt;/code&gt; change.&lt;/li&gt;&lt;li&gt;Rate limit information (still needs to be able to support the HTTP header method, which I actually suggested to Twitter developers some time back, but they only recently added it when my bandwidth for OSS contribution was minimal) :(&lt;/li&gt;&lt;li&gt;&lt;a href="http://wiki.github.com/mbbx6spp/twitter4r/twitter4r-0-3-1-development-release"&gt;much more&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Now the future of the Twitter4R project.  I have made a LOT of mistakes with this Twitter4R OSS project venture, so I am going to try to fix a bunch of these things:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a new set of Git repos on GitHub that separates the education portions (screencast, etc.) from the core source code of the project so that people do not need to download ridiculous amounts of data to their local drive just to fork Twitter4R on GitHub as it required at present.  &lt;strong&gt;Announcements about this will be coming soon!&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Have a consistent issue tracking system for Twitter4R.  Previously it has appeared inconsistent to users of the Twitter4R library where to submit defect reports or new feature requests to.  So I have had to field these requests from the Google Groups mailing list to personal emails and also @twitter4r replies on Twitter.  &lt;strong&gt;I plan on using GitHub's new issue tracking system for this as it seems a logical extension.&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;I plan on documenting things a little more obviously on the official website from now one.  It appears many users did not want to go to the RDoc unless specifically pointed to it, even though a large majority of the library is fairly well documented in the RDocs.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Please be patient while I fix these process/marketing/workflow issues of the project and in the mean time I will also be &lt;strong&gt;tackling OAuth support&lt;/strong&gt; as well.&lt;br /&gt;&lt;br /&gt;Again thanks for your patience thus far and tweet me on twitter at either &lt;a href="http://twitter.com/SusanPotter" target="_new"&gt;@SusanPotter&lt;/a&gt; or &lt;a href="http://twitter.com/twitter4r" target="_new"&gt;@twitter4r&lt;/a&gt; if you have suggestions or questions about the direction.  If you have specific queries on using the actual API, please join the twitter4r-users Google Groups mailing list and search the archives for a solution first and then if you can't find a solution, please post a message giving the group members your environment details and the version of Twitter4R you are using.&lt;br /&gt;&lt;br /&gt;Thanks!&lt;br /&gt;Susan&lt;br /&gt;Twitter4R Developer&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-4349350825811956698?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/4349350825811956698/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=4349350825811956698" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/4349350825811956698" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/4349350825811956698" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/n8S63x40eqA/twitter4r-031-and-future.html" title="Twitter4R 0.3.1 and the future" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/05/twitter4r-031-and-future.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-5726300406977243992</id><published>2009-04-20T15:47:00.020-05:00</published><updated>2009-04-22T16:24:52.636-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="functional programming" /><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="erlang" /><category scheme="http://www.blogger.com/atom/ns#" term="scalability" /><category scheme="http://www.blogger.com/atom/ns#" term="scala" /><category scheme="http://www.blogger.com/atom/ns#" term="jvm" /><category scheme="http://www.blogger.com/atom/ns#" term="concurrency" /><title type="text">The Scala vs Erlang Debate, Part 2: The Geek Off</title><content type="html">In the &lt;a href="http://geek.susanpotter.net/2009/04/scala-vs-erlang-debate-part-1-managers.html"&gt;first part of The Scala vs Erlang Debate&lt;/a&gt; article series, I discussed various ways to go about adopting either Scala or Erlang and in what scenarios it made sense to go with one over the other from the manager's perspective.  &lt;br /&gt;&lt;br /&gt;In summary the major advantage of Scala is that it runs on the &lt;acronym title="Java Virtual Machine"&gt;JVM&lt;/acronym&gt; so it can access pre-existing Java libraries your enterprise has already developed.  This is also Scala's major disadvantage because it makes a rather large assumption (which in my opinion would be incorrect the majority of the time) that the Java libraries being used are thread-safe.  Erlang on the other hand doesn't allow you to integrate in the same OS process with Java libraries, because Erlang was built from the ground up with scalability and fault-tolerence in mind and ideally you shouldn't put Java into the run-time stack because it compromises Erlang's fault-tolerance features significantly.  Instead the preferred approach when writing the biggest bottlenecks of your system in Erlang and integrating with pre-existing Java libraries/system is to use &lt;acronym title="Service Oriented Architecture"&gt;SOA&lt;/acronym&gt; to create separate, but integrated systems that are easy to swap out and upgrade at a later point.  In my view, you should be refactoring your enterprise architecture by defining services anyway, since this will decouple systems and remove a great deal of headaches in IT maintenance and deployment.&lt;br /&gt;&lt;br /&gt;Today I wanted to geek out and differentiate the two environments on a more technical level for the middle/technical managers.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Scala: Technical Overview&lt;/h4&gt;&lt;br /&gt;Scala is an objected oriented, statically typed language with many functional programming capabilities built-in.  However, it must be noted (because few Scala documents do this) that Scala is not a pure functional programming language and therefore many corollaries from &lt;em&gt;lambda calculus&lt;/em&gt; cannot be applied for optimization purposes.  So by being a hybrid functional language and not a pure functional programming language it losses some of the benefits.&lt;br /&gt;&lt;br /&gt;As well as it's Java run-time support on the &lt;acronym title="Java Virtual Machine"&gt;JVM&lt;/acronym&gt; it is also supported in Microsoft's Common Language Runtime (&lt;acronym title="Common Language Runtime"&gt;CLR&lt;/acronym&gt;) so .NET integration, in theory, is a breeze.  Again this also assumes that the .NET libraries you use from Scala are thread-safe.  On a related topic, .NET also has F# available, which is Microsoft's attempt at a &lt;em&gt;hybrid&lt;/em&gt; functional programming language also.  I have no comment on F# myself, since I have zero experience with it.  Please chime in on the comments section if you have experience with F# and are able to contrast it with Scala.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Erlang: Technical Overview&lt;/h4&gt;&lt;br /&gt;Erlang on the other hand is a dynamic, purer functional programming language that supports light-weight processes in its own run-time environment (separate from &lt;acronym title="Operating System"&gt;OS&lt;/acronym&gt; processes), which send messages to each other asynchronously.  One major side effect of being a pure functional programming language is that there is &lt;strong&gt;NO STATE&lt;/strong&gt;.  There is no way to pass "state" around, but there is a &lt;em&gt;lambda calculus&lt;/em&gt; optimization that can be taken advantage of that will ease away our troubles called &lt;em&gt;tail-recursion&lt;/em&gt;.  Tail-recursion only partially works in Scala due to it not being a pure functional language and running on a stack-based VM such as the &lt;acronym title="Java Virtual Machine"&gt;JVM&lt;/acronym&gt;.&lt;br /&gt;&lt;br /&gt;For many developers that only have experience in procedural and Object-Oriented (&lt;acronym title="Object Oriented"&gt;OO&lt;/acronym&gt;) programming languages like Java, Python, Ruby, C++, C, Perl, C# this sounds completely &lt;em&gt;insane&lt;/em&gt;.  Two years ago I may have agreed with you, but today life is much simpler without state in my Erlang travels than when I had to write thread-safe Java code and I wish I had discovered this concept earlier.  I will not pretend this notion didn't take some getting used to but today I see things a lot clearer and I am thankful for that clarity.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Scala: Concurrency&lt;/h4&gt;&lt;br /&gt;Concurrency in Scala is modeled using a concept of &lt;em&gt;actors&lt;/em&gt;, except there are two types of &lt;em&gt;actors&lt;/em&gt;: thread-based and event-based actors.&lt;br /&gt;&lt;br /&gt;Since Scala was implemented on top of the &lt;acronym title="Java Virtual Machine"&gt;JVM&lt;/acronym&gt;, which is stack-based, Scala had to compromise on Erlang's one actor approach.  This is because native threads, which the &lt;acronym title="Java Virtual Machine"&gt;JVM&lt;/acronym&gt; uses for concurrency support, are much heavier-weight than Erlang's lightweight processes thus reducing the number of thread-based actors that could be launched inside one &lt;acronym title="Java Virtual Machine"&gt;JVM&lt;/acronym&gt;.  So Scala created this concept of a very peared down event-based actor, which does not have all the functionality of thread-based actors but does not incur the penalty of needing to be backed by a native thread.&lt;br /&gt;&lt;br /&gt;To be as complete as I can be in this section I should also note that Scala treats everything as an object, even though it has these two types of actors.  Actors in Scala are just objects.  In turn this may create duplication between objects and actors.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Erlang: Concurrency&lt;/h4&gt;&lt;br /&gt;The Erlang &lt;acronym title="Virtual Machine"&gt;VM&lt;/acronym&gt; was built from the bottom up with lightweight processes (a.k.a. actors), therefore it is stackless and much better at lightweight concurrency.  Erlang also has a built-in mechanism for load balancing these lightweight processes across all available CPU cores.  This means Erlang has a massive advantage over JVM based functional programming languages at getting the most out of multi-core hardware, which is at the crux of the problem domain that software needs to address going forward.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Scala vs. Erlang: Performance&lt;/h4&gt;&lt;br /&gt;In terms of linear performance (sequential) Scala has been shown to beat Erlang in certain cases.  However, concurrent performance consistently shows Erlang beating Scala, sometimes by wide margins on multi-core hardware.  Not surprising considering what we learned in the concurrency sections above.&lt;br /&gt;&lt;br /&gt;When considering the problem we are trying to overcome - optimizing software on multi-core hardware - it seems clear which of these benchmarks are more important! :)&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;&lt;br /&gt;I think it is clear, which side of this debate I firmly stand, but I have tried to demonstrate both good and bad traits of each programming language from a technical perspective that might translate into a business case or reason for choosing one over the other in your organization.&lt;br /&gt;&lt;br /&gt;If I have time I might do a part 3, which will talk a little about syntax and DSL support.  This might round out the argument since it could be argued that Scala wins in the third part by a hair, but all is not lost for Erlang if the underlying problem you need to solve is related to optimizing software for modern hardware and building robust systems at the same time.  My vote still goes to Erlang despite the lack of built-in features that make designing &lt;acronym title="Domain Specific Language"&gt;DSL&lt;/acronym&gt;s easier, but it is not difficult to build your own &lt;acronym title="Domain Specific Language"&gt;DSL&lt;/acronym&gt; engine in Erlang either.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Limitations of this series:&lt;/h4&gt;&lt;br /&gt;There are quite a few topics I left out of this post that might be of interest for some applications or services.  Namely:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;strong&gt;Hot swapping:&lt;/strong&gt; Erlang has great hot swapping capabilities for production environments that minimizes or possibly eliminates downtime of systems.  This feature in Scala is not close in capability or reliability at this point.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;strong&gt;Garbage collection:&lt;/strong&gt; without getting into too many details Erlang probably wins this section by a hair (not significant to write home about).  Long sweeps will not be a problem in Erlang and only a problem in JVM languages on rare occasions.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;strong&gt;Distributed nodes:&lt;/strong&gt; The clear winner here would be Erlang because built-in to the environment are all the multi-node features that make distributed systems a breeze.  Scala on the other hand has different frameworks and libraries to facilitate distributing nodes of logic on different hosts.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Resources:&lt;/h4&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://geek.susanpotter.net/2009/04/scala-vs-erlang-debate-part-1-managers.html"&gt;The Scala vs Erlang Debate, Part 1: The Manager's Overview&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-5726300406977243992?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/5726300406977243992/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=5726300406977243992" title="25 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/5726300406977243992" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/5726300406977243992" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/-SZI4YxqZ5Y/scala-vs-erlang-debate-part-2-geek-off.html" title="The Scala vs Erlang Debate, Part 2: The Geek Off" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">25</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/04/scala-vs-erlang-debate-part-2-geek-off.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-9116860869510075065</id><published>2009-04-15T09:37:00.017-05:00</published><updated>2009-04-15T11:36:34.775-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="functional programming" /><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="erlang" /><category scheme="http://www.blogger.com/atom/ns#" term="scala" /><category scheme="http://www.blogger.com/atom/ns#" term="jvm" /><category scheme="http://www.blogger.com/atom/ns#" term="concurrency" /><title type="text">The Scala vs Erlang Debate, Part 1: The Managers Overview</title><content type="html">&lt;em&gt;Note: The discussion is primarily between Scala and Erlang, but other languages could potentially be substituted in the arguments for and against.  Scala stands for any language that attempts to solve the multi-core issue software developers face with threads and Erlang is a language that has light weight processes which solves the biggest issue of going with a multi-process solution in software.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The debate started with the realization that Moore's Law died a while ago.  Tomorrow (as we see it now) is destined for multi-cores.&lt;br /&gt;&lt;br /&gt;A problem of massive proportions now faces software engineers, since hardware engineers changed the rules on us.  Now I am not giving hardware engineers a hard time, I am simply pointing out that there has been a massive shift in the way hardware is built, which directly affects the performance and reliability of the software which runs on it.  It is not a transparent change that software engineers can ignore.&lt;br /&gt;&lt;br /&gt;With that background laid out, as software engineers, we must appreciate the problem we now have to tackle, both server-side and client-side developers alike will need to tackle these issues promptly.  However, this article only considers server-side software as there is where my specialized expertise lies.  This part of the article is the high-level.  I'll get into the specifics in the second part.&lt;br /&gt;&lt;br /&gt;So the question now is how do we leverage the advantage given to us by new hardware progress of multi-cores?&lt;br /&gt;&lt;br /&gt;There are two fundamentally different problems to solve: software products/projects that already have large complex systems already built in languages that support threads half-decently such as in Java and JVM languages including Scala; but there are also those startups that don't have baggage and can start with a better long-term solution by using a true concurrent language like Erlang.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Legacy Enterprise&lt;/h3&gt;&lt;br /&gt;The problem with utilizing JVM threading (whether directly in Java or via other languages built on the JVM such as Scala) is that third party code you use or existing Java/JVM code written isn't necessarily thread-safe.  You might have all your business entities and models defined in Java, but can it really be threaded?&lt;br /&gt;&lt;br /&gt;The pain of migrating or porting your existing system from a JVM language to another truly concurrent language like Erlang might be much greater than dealing with threading issues in just a few key bottleneck areas that will increase throughput and CPU utilization &lt;strong&gt;enough&lt;/strong&gt;.  In this case I doubt many pragmatic engineers or architects will advocate starting from scratch in a language you know little (if anything) about.  However, identifying those key pain points might take some time, but will be a necessary cost if you are serious about solving this problem in the near-term using a solution like Scala.&lt;br /&gt;&lt;br /&gt;However, what these engineers and architects should stress to management is that this is likely to become a monkey patch.  There will be a tipping point where moving to a pure concurrent language like Erlang would be more beneficial that sticking to the monkey patch and living on the JVM forever, no matter what Sun tries to tell you.&lt;br /&gt;&lt;br /&gt;There are hybrid solutions for the medium-term, that depending on the project/enterprise specifics may be a good solution until you are able to fully port the code to a langauge like Erlang (or whatever the trend may be at the time you get to it).  &lt;acronym title="Service Oriented Architecture"&gt;SOA&lt;/acronym&gt; principles can be used to design and define a meaningful architecture that will declutter the system and allow you to tackle just the bottlenecks of the system in an Erlang port/rewrite and still give you (the manager) a low risk &lt;acronym title="Proof of Concept"&gt;PoC&lt;/acronym&gt; project so you can evaluate Erlang in your enterprise.&lt;br /&gt;&lt;br /&gt;Having worked on a number of large enterprise projects where &lt;em&gt;upgrading&lt;/em&gt; the "legacy" system was the goal, I know full well that management are likely to prefer the monkey patches (i.e. Scala where the pain of rewriting components in a PoC way doesn't exceed the pain of threading your existing code at the bottlenecks), especially when the middle/technical managers do not highlight the drawbacks of the "solution" adequately.  Three to nine months later the management (especially middle management) are hurting big time, but it is not usually the most appropriate time to do your &lt;em&gt;"I told you so dance"&lt;/em&gt;.  Trust me!:)&lt;br /&gt;&lt;br /&gt;The the monkey patch isn't an ideal solution when you are simply trading one complexity of equal of greater value for the other and in 2-5 years the likelihood that there will be many more skilled engineers and architects that truly understand and have solid production experience in a truly concurrent language like Erlang is high in my estimation, so making a move to such a language/environment would not be as risky at that time.  However, for 2-5 years you have been getting little out of your hardware and software together unless you overbuy hardware.  In fact, in the case where legacy code already exists, there is never really an ideal solution.  However, starting out with meaningful &lt;acronym title="Proof of Concept"&gt;PoC&lt;/acronym&gt;s and structuring low risk exit points after conducting objective evaluations of these projects is key to the success of every "legacy solution".  If in doubt and your legacy system isn't showing signs of hurting yet, you might want to wait and beef up on hardware.  This is a transition period and if you are in a conservative IT enterprise this might be a better near-term approach.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Startups&lt;/h3&gt;&lt;br /&gt;Now for the startups or those starting afresh, there is mixed news: very good news and not-so-bad news.  &lt;br /&gt;&lt;br /&gt;Green field projects, in theory, are always the best.  You can get everything right from day one....well at least you can hope to do so (let us pretend for this article).  My advise for your team is to take the plunge to Erlang.  It is actually relatively low risk to do so for the following reasons:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;It is a mature language and environment already tested by large and complex real world systems at telcos where reliability and scalability were and are top priorities.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;There are a few good books out there on that will help you convert to Erlang and Functional Programming (see resources section below), although documentation and education on Erlang, generally, is somewhat lacking.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;A framework for services has been designed, developed and put into production called OTP, which stands for the Open Telephony Platform and actually nothing specific to Telephony applications in it, it was simply developed by a Telco.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Erlang's approach to concurrency is interesting and takes some getting used to as it is a pure functional programming language unlike Scala which is a hybrid.  &lt;br /&gt;&lt;br /&gt;Now the bad news is that there are very few people that know Erlang (or other pure concurrent languages), you need to hire at least one specialist with Erlang experience to guide your team to avoid the potholes and perhaps even stop you before you get to the edge of a cliff.  They might not be cheap, but starting out it will mitigate project risk significantly.&lt;br /&gt;&lt;br /&gt;Another negative on the Erlang side of the argument is that you will not be able to use your Java classes straight from within Erlang (in a meaningful way - I'll cover this in the next part).  The positive about this negative though is that you can encapsulate your Java code in an SOA way so that you can decouple and declutter subsystems within your enterprise, which is an important task to do regardless of which legacy solution you choose.&lt;br /&gt;&lt;br /&gt;Finally, good luck and let me know how it goes!&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Resources&lt;/h4&gt;&lt;br /&gt;&lt;h5&gt;&lt;a href="http://www.amazon.com/gp/product/193435600X?ie=UTF8&amp;tag=illinilistn09-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=193435600X"&gt;Programming Erlang: Software for a Concurrent World&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;l=as2&amp;o=1&amp;a=193435600X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; by Joe Armstrong&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;This book, for the moment, is the definitive guide for Erlang.  If you have already decided to go the Erlang route then you will not mind (or perhaps not even notice) the "selling" of Erlang throughout the book.  Overall this is an essential book to anyone learning Erlang at this point.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;&lt;a href="http://www.amazon.com/gp/product/0596514980?ie=UTF8&amp;tag=illinilistn09-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0596514980"&gt;Real World Haskell&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;l=as2&amp;o=1&amp;a=0596514980" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;&lt;/h5&gt;&lt;br /&gt;&lt;p&gt;While Haskell isn't either Scala or Erlang, if you do not come from a functional programming frame of mind you will need a good book to introduce you gently into the realm of functional programming.  This book does a pretty good job.  While the syntax for Haskell is different to both Erlang and Scala, the hardest part of moving to functional programming isn't the syntax.  Trust me on this one:)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Also consider me, &lt;a href="http://www.linkedin.com/in/susanpotter"&gt;Susan Potter&lt;/a&gt;, a resource if you need an Erlang software engineer with high-level enterprise architecture background in Java/J2EE/JEE and Ruby/Rails production environments.  I am developing a risk management product in Erlang right now and I am available as a consultant through my consulting firm &lt;a href="http://finsignia.com"&gt;Finsignia&lt;/a&gt;, which mostly works with financial services firms such as investment banks and hedge funds, which is where my business domain expertise lies, but also works on designing, building and deploying reliable and robust server-side solutions for any industry.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-9116860869510075065?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/9116860869510075065/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=9116860869510075065" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/9116860869510075065" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/9116860869510075065" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/034c2a7mtmk/scala-vs-erlang-debate-part-1-managers.html" title="The Scala vs Erlang Debate, Part 1: The Managers Overview" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/04/scala-vs-erlang-debate-part-1-managers.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-297445119338360086</id><published>2009-04-04T20:13:00.005-05:00</published><updated>2009-04-04T20:34:05.044-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chambana" /><category scheme="http://www.blogger.com/atom/ns#" term="BarCamp" /><category scheme="http://www.blogger.com/atom/ns#" term="champaign urbana" /><title type="text">CUBarCamp: Champaign-Urbana's Tech Meetup Update</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YUkA0L0Czls/SdgGQQ9SN4I/AAAAAAAAAHw/wgEm9qlUa_A/s1600-h/CUBarCamp.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 186px;" src="http://2.bp.blogspot.com/_YUkA0L0Czls/SdgGQQ9SN4I/AAAAAAAAAHw/wgEm9qlUa_A/s400/CUBarCamp.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5321009836237928322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is just an update blog post to let geeks in and around the Champaign-Urbana area know that the CU BarCamp is now scheduled for April 25th, 2009.  The meetup will start at 2pm CDT and will be located at the Collective Turf Coworking space:&lt;br /&gt;&lt;address&gt;110 W. Main Street&lt;br /&gt;Urbana, IL 61801&lt;/address&gt;&lt;br /&gt;&lt;br /&gt;It is right between the Heartland Gallery and Priceless Books and opposite the Urbana Business Association office and Crane Alley.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Want to participate?&lt;/h3&gt;&lt;br /&gt;If you want to volunteer, present or demo any topics at this BarCamp please update the &lt;A href="http://barcamp.org/CUBarCamp"&gt;CUBarCamp wiki page&lt;/a&gt; and join the &lt;a href="http://groups.google.com/group/cubarcamp"&gt;Google Group for the CU BarCamp event&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Hope to see you there!&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-297445119338360086?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/297445119338360086/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=297445119338360086" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/297445119338360086" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/297445119338360086" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/ICPaBOXSZyw/cubarcamp-champaign-urbanas-tech-meetup.html" title="CUBarCamp: Champaign-Urbana's Tech Meetup Update" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_YUkA0L0Czls/SdgGQQ9SN4I/AAAAAAAAAHw/wgEm9qlUa_A/s72-c/CUBarCamp.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/04/cubarcamp-champaign-urbanas-tech-meetup.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-7094876133553155591</id><published>2009-03-27T18:59:00.005-05:00</published><updated>2009-03-27T19:14:48.886-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="YUI" /><category scheme="http://www.blogger.com/atom/ns#" term="CSS" /><title type="text">YUI MenuBar: A Facebook-like Application Bar</title><content type="html">&lt;p&gt;Below is a snippet of HTML code with embedded Javascript code that will create a top anchored menu bar very similar to what you see at the bottom of the Facebook page:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;!-- Add the following to your HTML/HEAD --&amp;gt;&lt;br /&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;http://yui.yahooapis.com/2.7.0/build/fonts/fonts-min.css&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;http://yui.yahooapis.com/2.7.0/build/menu/assets/skins/sam/menu.css&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://yui.yahooapis.com/2.7.0/build/yahoo-dom-event/yahoo-dom-event.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://yui.yahooapis.com/2.7.0/build/container/container_core-min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://yui.yahooapis.com/2.7.0/build/menu/menu-min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;YAHOO.util.Event.onDOMReady(function () {&lt;br /&gt;  var oMenuBar = new YAHOO.widget.MenuBar(&amp;quot;menubar&amp;quot;);&lt;br /&gt;  oMenuBar.render();&lt;br /&gt;});&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- in your HTML/BODY modify the following for your own &amp;quot;Facebook Application Bar&amp;quot; menu --&amp;gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;menubar&amp;quot; class=&amp;quot;yuimenubar&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;div class=&amp;quot;bd&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;ul class=&amp;quot;first-of-type&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;li class=&amp;quot;yuimenubaritem first-of-type&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;a class=&amp;quot;yuimenubaritemlabel&amp;quot; href=&amp;quot;#file&amp;quot;&amp;gt;Applications&amp;lt;/a&amp;gt;&lt;br /&gt;        &amp;lt;div id=&amp;quot;file&amp;quot; class=&amp;quot;yuimenu&amp;quot;&amp;gt;&lt;br /&gt;          &amp;lt;div class=&amp;quot;bd&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;ul&amp;gt;&lt;br /&gt;              &amp;lt;li class=&amp;quot;yuimenuitem&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;a class=&amp;quot;yuimenuitemlabel&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;Notes&amp;lt;em class=&amp;quot;helptext&amp;quot;&amp;gt;Ctrl + N&amp;lt;/em&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;              &amp;lt;/li&amp;gt;&lt;br /&gt;              &amp;lt;li class=&amp;quot;yuimenuitem&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;a class=&amp;quot;yuimenuitemlabel&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;Links&amp;lt;em class=&amp;quot;helptext&amp;quot;&amp;gt;Ctrl + L&amp;lt;/em&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;              &amp;lt;/li&amp;gt;&lt;br /&gt;              &amp;lt;li class=&amp;quot;yuimenuitem&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;a class=&amp;quot;yuimenuitemlabel&amp;quot; href=&amp;quot;#open&amp;quot;&amp;gt;Photos&amp;lt;em class=&amp;quot;helptext&amp;quot;&amp;gt;Ctrl + P&amp;lt;/em&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;                &amp;lt;div id=&amp;quot;open&amp;quot; class=&amp;quot;yuimenu&amp;quot;&amp;gt;&lt;br /&gt;                  &amp;lt;div class=&amp;quot;bd&amp;quot;&amp;gt;&lt;br /&gt;                      &amp;lt;ul class=&amp;quot;first-of-type&amp;quot;&amp;gt;&lt;br /&gt;                        &amp;lt;li class=&amp;quot;yuimenuitem&amp;quot;&amp;gt;&lt;br /&gt;                            &amp;lt;a class=&amp;quot;yuimenuitemlabel&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;Upload Album&amp;lt;/a&amp;gt;&lt;br /&gt;                        &amp;lt;/li&amp;gt;&lt;br /&gt;                        &amp;lt;li class=&amp;quot;yuimenuitem&amp;quot;&amp;gt;&lt;br /&gt;                            &amp;lt;a class=&amp;quot;yuimenuitemlabel&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;Browse Albums&amp;lt;/a&amp;gt;&lt;br /&gt;                        &amp;lt;/li&amp;gt;&lt;br /&gt;                      &amp;lt;/ul&amp;gt;            &lt;br /&gt;                  &amp;lt;/div&amp;gt;&lt;br /&gt;                &amp;lt;/div&amp;gt;            &lt;br /&gt;              &amp;lt;/li&amp;gt;&lt;br /&gt;            &amp;lt;/ul&amp;gt;&lt;br /&gt;          &amp;lt;/div&amp;gt;&lt;br /&gt;        &amp;lt;/div&amp;gt;&lt;br /&gt;      &amp;lt;/li&amp;gt;&lt;br /&gt;      &amp;lt;li class=&amp;quot;yuimenubaritem first-of-type&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;a class=&amp;quot;yuimenubaritemlabel&amp;quot; href=&amp;quot;#&amp;quot;edit&amp;gt;Something Else&amp;lt;/a&amp;gt;&lt;br /&gt;        &amp;lt;div id=&amp;quot;pim&amp;quot; class=&amp;quot;yuimenu&amp;quot;&amp;gt;&lt;br /&gt;          &amp;lt;div class=&amp;quot;bd&amp;quot;&amp;gt;&lt;br /&gt;            &amp;lt;ul class=&amp;quot;first-of-type&amp;quot;&amp;gt;&lt;br /&gt;              &amp;lt;li class=&amp;quot;yuimenuitem&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;a class=&amp;quot;yuimenuitemlabel&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt; Bla 1&amp;lt;/a&amp;gt;&lt;br /&gt;              &amp;lt;/li&amp;gt;&lt;br /&gt;              &amp;lt;li class=&amp;quot;yuimenuitem&amp;quot;&amp;gt;&lt;br /&gt;                &amp;lt;a class=&amp;quot;yuimenuitemlabel&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt; Bla 2&amp;lt;/a&amp;gt;&lt;br /&gt;              &amp;lt;/li&amp;gt;&lt;br /&gt;            &amp;lt;/ul&amp;gt;            &lt;br /&gt;          &amp;lt;/div&amp;gt;&lt;br /&gt;        &amp;lt;/div&amp;gt;&lt;br /&gt;      &amp;lt;/li&amp;gt;&lt;br /&gt;    &amp;lt;/ul&amp;gt;&lt;br /&gt;  &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;For further details about customizing the YUI MenuBar look and feel you should visit the &lt;a href="http://developer.yahoo.com/yui/docs/YAHOO.widget.MenuBar.html"&gt;API documentation&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-7094876133553155591?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/7094876133553155591/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=7094876133553155591" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/7094876133553155591" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/7094876133553155591" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/x654Tz-8qxo/yui-menubar-facebook-like-application.html" title="YUI MenuBar: A Facebook-like Application Bar" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/03/yui-menubar-facebook-like-application.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-7685492460714769518</id><published>2009-02-24T00:04:00.003-06:00</published><updated>2009-02-24T00:12:43.241-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="urbana" /><category scheme="http://www.blogger.com/atom/ns#" term="champaign" /><category scheme="http://www.blogger.com/atom/ns#" term="chambana" /><category scheme="http://www.blogger.com/atom/ns#" term="BarCamp" /><category scheme="http://www.blogger.com/atom/ns#" term="champaign urbana" /><title type="text">CUBarCamp: Champaign-Urbana's Tech Meetup 4/22 (tentatively)</title><content type="html">Just a quick post to mention that with the assistance of &lt;a href="http://www.exampler.com/"&gt;Brian Marick&lt;/a&gt; and hopefully a few more people in the weeks to come, &lt;a href="http://barcamp.org"&gt;BarCamp&lt;/a&gt; is coming to the &lt;a href="http://barcamp.org/CUBarCamp"&gt;Champaign-Urbana area&lt;/a&gt; and is to be held at the Collective Turf Coworking space in downtown Urbana (110 W. Main Street, Urbana, IL - opposite Crane Alley and above Priceless Books).&lt;br /&gt;&lt;br /&gt;To keep updated on the latest developments and participate in the event organizing join the &lt;a href="http://groups.google.com/group/CUBarCamp"&gt;CUBarCamp Google Group&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Hope to see you there!&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-7685492460714769518?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/7685492460714769518/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=7685492460714769518" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/7685492460714769518" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/7685492460714769518" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/tqW3dXmT8GA/cubarcamp-champaign-urbanas-tech-meetup.html" title="CUBarCamp: Champaign-Urbana's Tech Meetup 4/22 (tentatively)" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/02/cubarcamp-champaign-urbanas-tech-meetup.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-7527602399441387632</id><published>2009-02-09T15:26:00.006-06:00</published><updated>2009-02-09T17:31:03.766-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="coworking" /><title type="text">Coworking Space in Champaign Urbana (Illinois)</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://twitter.com/SusanPotter/status/1193116121"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 222px;" src="http://1.bp.blogspot.com/_YUkA0L0Czls/SZC4RyhnKcI/AAAAAAAAAHg/Js4nD0qOQ4E/s400/tweet-coworking.png" border="0" alt="Tweet from @SusanPotter about starting a Champaign-Urbana Coworking environment/venue" id="BLOGGER_PHOTO_ID_5300939377175112130" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Since I moved to Champaign-Urbana, IL (aka CU) in 2005 I have been looking for work space that would provide me with a more productive environment and social yet professional outlet to work in since I work primarily on telecommute contracts and lack face time with clients.&lt;br /&gt;&lt;br /&gt;Today I decided that I will setup a local &lt;strong&gt;coworking&lt;/strong&gt; space for solo entrepreneurs and freelancers in and around the Champaign-Urbana area to fulfill my needs as a consultant and fulfill my new venture urge of late.&lt;br /&gt;&lt;br /&gt;Essentially &lt;strong&gt;coworking&lt;/strong&gt; is defined as the following:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;strong&gt;Coworking&lt;/strong&gt; is a movement to create cafe-like community/collaboration spaces for developers, writers and independents.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This is exactly how I imagined my dream work space since I work a lot in coffee shops all around town throughout the work week and even during the weekend sometimes and find it surprisingly (initially) productive.&lt;br /&gt;&lt;br /&gt;I have seen these types of office spaces in larger metro areas and the terminology used tends to be different from place to place.  Some terms used to mean a community of independent professionals sharing office space, facilities and amenities that I have come across on my travels include:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;strong&gt;Coworking&lt;/strong&gt; or Co-working (obviously)&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Collaborative work environments (not used in the context of a company job description:))&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Work Space Cooperative (this might be organized at the top levels slightly differently though)&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Shared Work Space&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Serviced Office Space&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;There are probably some slight variants on the definitions of these as compared to that of &lt;strong&gt;coworking&lt;/strong&gt;, so some places will have more structure and a more formal setting, whereas &lt;strong&gt;coworking&lt;/strong&gt; itself strives to create a more creative and collaborative environment for independent professionals.&lt;br /&gt;&lt;br /&gt;If you are in the &lt;acronym title="Champaign-Urbana"&gt;CU&lt;/acronym&gt; (East Central Illinois) area and would be interested in working in such a &lt;strong&gt;coworking&lt;/strong&gt; space, please drop me a line at any of the following locations:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;strong&gt;twitter:&lt;/strong&gt; &lt;a href="http://twitter.com/SusanPotter"&gt;@SusanPotter&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;strong&gt;email:&lt;/strong&gt; me at susanpotter dot net&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;strong&gt;facebook:&lt;/strong&gt; &lt;a href="http://www.facebook.com/people/Susan-Potter/706880787"&gt;My Profile&lt;/a&gt;&amp;nbsp|&amp;nbsp&lt;a href="http://www.facebook.com/group.php?gid=54723272076"&gt;Champaign-Urbana Coworking Group&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Are you a freelancer or entrepreneur in another area or region that is part of a coworking environment experience there?  What do you like about your coworking space and why?  What would you change about it if you could?&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-7527602399441387632?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/7527602399441387632/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=7527602399441387632" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/7527602399441387632" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/7527602399441387632" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/8nIkHPiyibU/coworking-space-in-champaign-urbana.html" title="Coworking Space in Champaign Urbana (Illinois)" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_YUkA0L0Czls/SZC4RyhnKcI/AAAAAAAAAHg/Js4nD0qOQ4E/s72-c/tweet-coworking.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/02/coworking-space-in-champaign-urbana.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-704071610769103721</id><published>2009-01-14T23:54:00.006-06:00</published><updated>2009-01-15T00:19:18.447-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="open source" /><category scheme="http://www.blogger.com/atom/ns#" term="gedit" /><category scheme="http://www.blogger.com/atom/ns#" term="oss" /><category scheme="http://www.blogger.com/atom/ns#" term="opensource" /><title type="text">GEdit Extensions Project</title><content type="html">Just a quick post from a long blogging hiatus to let people know that I launched gedit-extensions where I will maintain a set of commonly used GEdit snippets and eventually plugins and tools that others might find useful.&lt;br /&gt;&lt;br /&gt;You can view the snippet source at the &lt;a href="http://github.com/finsignia/gedit-extensions/tree/"&gt;GitHub gedit-extensions repository&lt;/a&gt;.  I plan on adding documentation to the &lt;a href="http://wiki.github.com/finsignia/gedit-extensions"&gt;gedit-extensions wiki&lt;/a&gt; in the next couple of days, but for now see the sneak peak in the Ruby example snippets at the end of the post.  &lt;br /&gt;&lt;br /&gt;The name in the comments directly above the example snippet is the shortcut you can use.  Type the first few characters of the shortcut and then &lt;tt&gt;Ctl+Space&lt;/tt&gt; key combination to pull up all shortcuts the characters match so far.  Choose the relevant shortcut from the drop down list.  If the snippet contains variables the first variable will be highlighted for your to fill in, then press &lt;tt&gt;TAB&lt;/tt&gt; to navigate to the next variable to fill in.&lt;br /&gt;&lt;br /&gt;As you will see most of the shortcuts so far are Ruby, Rails, RSpec or Cucumber specific since there are a few Python snippets I need to untangle from our in-house code references.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span class="comment"&gt;# shebang&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt;#!/usr/bin/env ruby&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt;# absrequire&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;require&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dirname&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;config&lt;/span&gt;&lt;span class="punct"&gt;",&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;enviornment&lt;/span&gt;&lt;span class="punct"&gt;")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# habtm&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;has_and_belongs_to_many&lt;/span&gt; &lt;span class="symbol"&gt;:idiots&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt;# unique&lt;/span&gt;&lt;br /&gt;&lt;span class="symbol"&gt;:unique&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt;# habtmthru&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;has_and_belongs_to_many&lt;/span&gt; &lt;span class="symbol"&gt;:idiots&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:through&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="symbol"&gt;:village&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# belongsto&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;belongs_to&lt;/span&gt; &lt;span class="symbol"&gt;:village&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# createtable&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;create_table&lt;/span&gt; &lt;span class="symbol"&gt;:sessions&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;column&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:string&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:limit&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="number"&gt;34&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;column&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:description&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:string&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:limit&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="number"&gt;255&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# addindex&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;add_index&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:sessions&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt;# changecolumn&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;change_column&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:sessions&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:limit&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="number"&gt;70&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# removecolumn&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;remove_column&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:sessions&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="comment"&gt;# irreversible&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;IrreversibleMigration&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;the reason the migration is irreversible&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# resource&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;PersonResource&lt;/span&gt; &lt;span class="punct"&gt;&lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveResource&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;site&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;http://domain.com:8080/&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;element_name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;contacts&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;prefix&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;v1_0&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;user&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;supo&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;password&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;geditrocks&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;timeout&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;60&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# describe&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;describe&lt;/span&gt; &lt;span class="constant"&gt;PersonResource&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;before&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:each&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;    &lt;span class="attribute"&gt;@resource&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;PersonResource&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;should bla&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="ident"&gt;after&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:each&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;    &lt;span class="attribute"&gt;@resource&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;&lt;br /&gt;  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specmodelerror&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;should have an error on name&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="attribute"&gt;@user&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;errors_on&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specmodelrecords&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;should have 50 records&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="attribute"&gt;@states&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;50&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;records&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# spectemplaterendered&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;should render 'common/user' on get '/user'&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;get&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;/user&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;render_template&lt;/span&gt;&lt;span class="punct"&gt;("&lt;/span&gt;&lt;span class="string"&gt;common/user&lt;/span&gt;&lt;span class="punct"&gt;"))&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specresponsetext&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;should return text 'You were signed out.' in response to post on '/signout'&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;/signout&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_text&lt;/span&gt;&lt;span class="punct"&gt;("&lt;/span&gt;&lt;span class="string"&gt;You were signed out.&lt;/span&gt;&lt;span class="punct"&gt;")&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specresponseredirect&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;should redirect to action 'index' on post '/users'&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;post&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;/users&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;redirect_to&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specroutefor&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;should map #index to '/users'&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;route_for&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:controller&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;users&lt;/span&gt;&lt;span class="punct"&gt;",&lt;/span&gt; &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;index&lt;/span&gt;&lt;span class="punct"&gt;").&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;/users&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specparamsfrom&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;it&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;should generate params for #update&lt;/span&gt;&lt;span class="punct"&gt;"&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;params_from&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:put&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;/users/1&lt;/span&gt;&lt;span class="punct"&gt;").&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;&lt;span class="symbol"&gt;:controller&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;users&lt;/span&gt;&lt;span class="punct"&gt;",&lt;/span&gt; &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;update&lt;/span&gt;&lt;span class="punct"&gt;",&lt;/span&gt; &lt;span class="symbol"&gt;:id&lt;/span&gt; &lt;span class="punct"&gt;=&gt;&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;"}&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# spectagexists&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_tag&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;ul.menu#sidebar&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specnestedtagexists&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_tag&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;ul.menu&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;with_tag&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;li&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;my menu item&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;br /&gt;  &lt;span class="comment"&gt;# specchildtagexists&lt;/span&gt;&lt;br /&gt;  &lt;span class="ident"&gt;with_tag&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;li&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;my second menu item&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;br /&gt;&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specblocktagexists&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:sidebar&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;have_tag&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;ul#sidebar&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# mockviewhelper&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;template&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should_receive&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:curent_user&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;and_return&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;User&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specsuccess&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;be_success&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# specredirect&lt;/span&gt;&lt;br /&gt;&lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;be_redirect&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="comment"&gt;# feature&lt;/span&gt;&lt;br /&gt;&lt;span class="constant"&gt;Feature&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="constant"&gt;Search&lt;/span&gt; &lt;span class="constant"&gt;Jobs&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;In&lt;/span&gt; &lt;span class="ident"&gt;order&lt;/span&gt; &lt;span class="ident"&gt;to&lt;/span&gt; &lt;span class="ident"&gt;find&lt;/span&gt; &lt;span class="ident"&gt;relevant&lt;/span&gt; &lt;span class="ident"&gt;jobs&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;As&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="constant"&gt;Job&lt;/span&gt; &lt;span class="constant"&gt;Seeker&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;I&lt;/span&gt; &lt;span class="ident"&gt;need&lt;/span&gt; &lt;span class="ident"&gt;to&lt;/span&gt; &lt;span class="ident"&gt;find&lt;/span&gt; &lt;span class="ident"&gt;jobs&lt;/span&gt; &lt;span class="ident"&gt;relevant&lt;/span&gt; &lt;span class="ident"&gt;to&lt;/span&gt; &lt;span class="ident"&gt;me&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class="constant"&gt;Scenario&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="constant"&gt;Location&lt;/span&gt; &lt;span class="constant"&gt;Search&lt;/span&gt;&lt;br /&gt;    &lt;span class="constant"&gt;Given&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="ident"&gt;search&lt;/span&gt; &lt;span class="ident"&gt;form&lt;/span&gt;&lt;br /&gt;    &lt;span class="constant"&gt;When&lt;/span&gt; &lt;span class="constant"&gt;I&lt;/span&gt; &lt;span class="ident"&gt;enter&lt;/span&gt; &lt;span class="ident"&gt;my&lt;/span&gt; &lt;span class="ident"&gt;zip&lt;/span&gt; &lt;span class="ident"&gt;code&lt;/span&gt;&lt;br /&gt;    &lt;span class="constant"&gt;Then&lt;/span&gt; &lt;span class="constant"&gt;I&lt;/span&gt; &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;see&lt;/span&gt; &lt;span class="ident"&gt;all&lt;/span&gt; &lt;span class="ident"&gt;jobs&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; &lt;span class="ident"&gt;around&lt;/span&gt; &lt;span class="ident"&gt;my&lt;/span&gt; &lt;span class="ident"&gt;zip&lt;/span&gt; &lt;span class="ident"&gt;code&lt;/span&gt;&lt;br /&gt;  &lt;span class="comment"&gt;# scenario&lt;/span&gt;&lt;br /&gt;  &lt;span class="constant"&gt;Scenario&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="constant"&gt;Skills&lt;/span&gt; &lt;span class="constant"&gt;Search&lt;/span&gt;&lt;br /&gt;    &lt;span class="constant"&gt;Given&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="ident"&gt;search&lt;/span&gt; &lt;span class="ident"&gt;form&lt;/span&gt;&lt;br /&gt;    &lt;span class="constant"&gt;When&lt;/span&gt; &lt;span class="constant"&gt;I&lt;/span&gt; &lt;span class="ident"&gt;enter&lt;/span&gt; &lt;span class="ident"&gt;skill&lt;/span&gt; &lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;br /&gt;    &lt;span class="constant"&gt;Then&lt;/span&gt; &lt;span class="constant"&gt;I&lt;/span&gt; &lt;span class="ident"&gt;should&lt;/span&gt; &lt;span class="ident"&gt;see&lt;/span&gt; &lt;span class="ident"&gt;all&lt;/span&gt; &lt;span class="ident"&gt;job&lt;/span&gt; &lt;span class="ident"&gt;descriptions&lt;/span&gt; &lt;span class="ident"&gt;that&lt;/span&gt; &lt;span class="ident"&gt;mention&lt;/span&gt; &lt;span class="ident"&gt;those&lt;/span&gt; &lt;span class="ident"&gt;keywords&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-704071610769103721?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/704071610769103721/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=704071610769103721" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/704071610769103721" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/704071610769103721" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/46r9Y3cN_Nk/gedit-extensions-project.html" title="GEdit Extensions Project" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2009/01/gedit-extensions-project.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-4336889545077205436</id><published>2008-11-03T10:50:00.008-06:00</published><updated>2008-11-03T11:03:10.239-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="coffee" /><category scheme="http://www.blogger.com/atom/ns#" term="election" /><category scheme="http://www.blogger.com/atom/ns#" term="merb" /><category scheme="http://www.blogger.com/atom/ns#" term="vote" /><title type="text">Free Coffee for Voting</title><content type="html">As if anyone needs any more enticement to vote this election season, Starbucks has decided to reward people who cast their vote Tuesday November 4th, 2008 with a free Tall coffee.  I do not believe you have to vote for anyone in particular:)  Just go and vote.&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/a2J8KJDsqqY&amp;hl=en&amp;fs=1&amp;rel=0&amp;color1=0x3a3a3a&amp;color2=0x999999"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/a2J8KJDsqqY&amp;hl=en&amp;fs=1&amp;rel=0&amp;color1=0x3a3a3a&amp;color2=0x999999" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;While you are enjoying your free coffee at Starbucks, perhaps explore the latest Merb 1.0 release candidate.  To install simply do the following:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ sudo gem update --system&lt;br /&gt;$ gem --version # make sure it is at least 1.2.0&lt;br /&gt;$ sudo gem install merb&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now to create a new Merb application do the following:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;$ merb-gen app your-app-name-here&lt;br /&gt;$ cd your-app-name-here&lt;br /&gt;# now start editing the files you need to edit for you app.&lt;br /&gt;# I promise more tutorials will be coming once I have &lt;br /&gt;# free time&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-4336889545077205436?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/4336889545077205436/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=4336889545077205436" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/4336889545077205436" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/4336889545077205436" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/AqF0bw2UZzs/free-coffee-for-voting.html" title="Free Coffee for Voting" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/11/free-coffee-for-voting.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-6483095180237787444</id><published>2008-09-27T21:52:00.020-05:00</published><updated>2008-09-28T11:03:24.220-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="agile" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby on rails" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="books" /><category scheme="http://www.blogger.com/atom/ns#" term="rubyonrails" /><category scheme="http://www.blogger.com/atom/ns#" term="capistrano" /><category scheme="http://www.blogger.com/atom/ns#" term="consulting" /><category scheme="http://www.blogger.com/atom/ns#" term="book" /><title type="text">Book Shelf Clearing</title><content type="html">In an effort to reorganize my office, I am clearing off space on my bookshelves and selling books (on Amazon marketplace) that I have already read.  Since they are all software development related I thought I would list the most relevant below in case any blog readers are looking for books on the subject for cheap:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;[SOLD]&lt;/strong&gt; &lt;strike&gt;Deploying Rails Applications: A Step-by-Step Guide (Facets of Ruby)&lt;/strike&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; (&lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2FDeploying-Rails-Applications-Step-Step%2Fdp%2F0978739205&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" target="_blank"&gt;buy it new&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; or &lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Foffer-listing%2F0978739205%2F&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" target="_blank"&gt;used&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;)&lt;br/&gt;Very good for the beginner or intermediate Capistrano recipe writer.  It also contains some good pointers at the end of the book on benchmarking.  Released relatively recently (within 3 months I think?)&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Foffer-listing%2F0596529554%3Fseller%3DA2GY6CQ7Y4MII2&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" target="_blank"&gt;SOA in Practice: The Art of Distributed System Design (Theory in Practice)&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; (Published Aug 2007)&lt;br/&gt;This book is more for the unRESTful SOA types than the RESTful folk like me.  The author obviously has some old-time experience, so if you are into old school SOA standards (WSDL, SOAP, UDDI) then this would provide a lot of good architect-level areas to consider, which are often ignored including: service lifecycle, versioning, security, service management and more.  One gripe I had with the book is in the versioning section.  Let's just say his preference for naming is definitely NOT my style:)  Otherwise this contains good reading material for the architect just getting into SOA in an enterprise setting.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Foffer-listing%2F0596527314%3Fseller%3DA2GY6CQ7Y4MII2&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" target="_blank"&gt;Rails Cookbook (Cookbooks (O'Reilly))&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;&lt;br/&gt;Great for starting Rails projects with limited Ruby on Rails experience.  It covers Rails 1.2, but most recipes will only require minor changes.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Foffer-listing%2F0596527675%3Fseller%3DA2GY6CQ7Y4MII2&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" target="_blank"&gt;The Art of Agile Development&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;&lt;br/&gt;Covers all aspects of agile development from planning to delivery.  If you aren't already an agile development ninja, this is in my top three agile books.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Foffer-listing%2F1593271204%3Fseller%3DA2GY6CQ7Y4MII2&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" target="_blank"&gt;Webbots, Spiders, and Screen Scrapers: A Guide to Developing Internet Agents with PHP/CURL&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;&lt;br/&gt;Last year I had to work (for a short while) with PHP in the crawling/bot arena.  This book contained got me developing bots and crawlers in no time in PHP.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Foffer-listing%2F0596527446%3Fseller%3DA2GY6CQ7Y4MII2&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" target="_blank"&gt;Ajax on Rails&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;&lt;br/&gt;This would be a decent book for Rails developers that aren't believers in Unobtrusive Javascript (UJS).  I have to purge this book from my bookcase now that I am a big UJS convert:)  I hope you understand.  I got this when it first came out, before I had seen the light.  Seriously though, if you don't care about UJS principles, this book covers good ground on using AJAX Rails helpers.  You should realize that the book was written pre-2.0 (Rails release that is).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Also those wanting to branch out on their own as a consultant, the following books might be for you as I found both very helpful when first starting my software consulting practice in 2001:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Foffer-listing%2F0471384550%3Fseller%3DA2GY6CQ7Y4MII2&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" target="_blank"&gt;Getting Started in Consulting&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;&lt;br/&gt;If I could only recommend one of these two consulting books it would be this one hands down, since this is more about general consulting principles and practices and the second book might be slightly dated in the initial chapters, because both were written before the software outsourcing/offshoring mania.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Foffer-listing%2F0471348139%3Fseller%3DA2GY6CQ7Y4MII2&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" target="_blank"&gt;Getting Started in Computer Consulting&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;PS I have been using &lt;a href="http://www.amazon.com/gp/subs/primeclub/signup/extmain.html?&lt;br /&gt;ref=prime_assoc_bt&amp;tag=illinilistn09-20" rel="nofollow" target="_blank"&gt;Amazon Prime&lt;/a&gt; for two months now and love it.  You can &lt;a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&amp;location=http%3A%2F%2Fwww.amazon.com%2Fgp%2Fsubs%2Fprimeclub%2Fsignup%2Fextmain.html%3Fref%3Dprime%5Fassoc%5Fbt&amp;tag=illinilistn09-20&amp;linkCode=ur2&amp;camp=1789&amp;creative=9325" rel="nofollow" target="_blank"&gt;try Amazon Prime FREE for one month&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=illinilistn09-20&amp;amp;l=ur2&amp;amp;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; if you like too.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-6483095180237787444?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/6483095180237787444/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=6483095180237787444" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/6483095180237787444" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/6483095180237787444" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/USZSKVos1Pw/book-shelf-clearing.html" title="Book Shelf Clearing" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/09/book-shelf-clearing.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-3163567399148266115</id><published>2008-09-22T10:20:00.041-05:00</published><updated>2008-09-22T12:58:37.970-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="entrepreneur" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby on rails" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><title type="text">Tips to Enterpreneurs Hiring Ruby on Rails Consulting Firms</title><content type="html">I know I am taking a break from my DataMapper/Merb series of posts today, but I have seen enough fakers out there in the Ruby on Rails world that I just have to get a few things off my chest:&lt;br /&gt;&lt;br /&gt;Below is a list of things to avoid when hiring a Ruby on Rails consulting firm:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Overexcited marketing speak.&lt;/strong&gt;  Drop any firm that has something like the following on their website: &lt;em&gt;"We believe Ruby on Rails is the most elegant, powerful programming language on the planet"&lt;/em&gt;.  These people might know a thing or two about configuring WordPress or Drupal or perhaps only Photoshop, but definitely no serious Object Oriented development of large scale Ruby server applications.  Basically anyone that calls "Ruby on Rails" as a whole a programming language has an inadequate skill set to build a non-trivial web application.  In addition anyone that knows more than three non-similar programming languages will know Ruby is not &lt;strong&gt;&lt;a href="http://www.opensourcery.com/services/custom-software"&gt;"the most powerful programming language on the planet"&lt;/a&gt;&lt;/strong&gt;.  Sorry I had to find a quote on the web to prove I wasn't exaggerating.  There are many more fakers on the web too, so look out!  Remember you aren't looking for people using the most powerful programming language, you want results.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Agile this, agile that, agile everywhere.&lt;/strong&gt;  Beware of firms using the word &lt;strong&gt;agile&lt;/strong&gt; like there is no tomorrow.  Some use is fine, but ask them what they mean by agile.  And what benefits you, the client, will receive from an agile team.  Don't get me wrong if a web application is built in an iterative fashion with lots of client involvement and sign off, with lots of useful automated tests/specs that are run often then this is almost certainly a great thing for the project.  However, beware of the firms or freelancers that are using &lt;em&gt;agile&lt;/em&gt; simply as a buzzword.  (Note: some firms like mine use agile a lot in web page titles for SEO purposes, so not all firms that use agile a lot in titles are faking.  So make sure to ask firms what they mean by the word agile when they use it).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Why Rails?&lt;/strong&gt;  If any firm tells you that a web application written using Django, TurboGears, Merb or other web frameworks will never be as good as a Rails web application, then drop them off your consideration list immediately.  The same is true if the converse is said.  If they answer with something more measured and sensible like "our engineers have found developing applications in Rails to be more productive than X, Y and Z, which we previously used, and it provides us with the right amount of control/flexibility without us needing to worry about all configuration than previous frameworks" then at least they aren't misleading you just to get a sale.  Of course, you might be looking for other points in the answer (other attributes of a web framework that would make &lt;em&gt;business&lt;/em&gt; sense like active community, skillset, etc.).  Also in general you should look for measured answers to all your questions, not answers that lack insight and promise they can do EVERYTHING under the sun for you in 2 weeks time.  You will be disappointed if you hire that firm or freelancer.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Expert in everything, expert in nothing.&lt;/strong&gt;  Consulting firms and/or freelancers need to choose a specific set of technical competencies so they can be experts in those areas.  Beware of consulting firms or freelancers that claim to be experts in every framework, programming language and operating system.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Ubiquitous buzzwords.&lt;/strong&gt;  Beware of too many buzzwords.  Even if you know what a buzzword means, ask the person using too much jargon to clarify so you can evaluate whether they really know what they are saying.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Everything AJAX.&lt;/strong&gt;  I previously worked through a consulting firm on the west coast (I'll not name names).  The consulting manager who led project management functions on all the firms' projects was convinced that if we just put an AJAX form in here and there it would solve all our problems.  My experience with this firm wasn't overly positive.  I like the people on a personal level, but their work quality and focus tended to create hard to use web applications.  Beware of people who think AJAX is the answer to everything.  It has its place, but don't go overboard.  PS Make sure the people you hire write unobtrusive Javascript rather than embedded Rails Prototype helpers.  &lt;acronym title="Unobtrusive JavaScript"&gt;UJS&lt;/acronym&gt; has many benefits including graceful degradation (benefiting those that do not have Javascript enabled), avoiding browser incompatibilities and improved code organization (separation of concerns).  Users of your web application will appreciate the forethought and your developers can be more productive!:)  Win-win.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Novice.has_many :problems&lt;/strong&gt;  Look for previous Object Oriented modeling experience for the engineers on the project team.  Even though ActiveRecord (the default Ruby on Rails Object Relational Mapping framework) provides a higher level of abstraction for &lt;acronym title="Object Relational Mapping"&gt;ORM&lt;/acronym&gt; associations than other frameworks, don't be fooled into thinking anyone can model your business domain correctly without experience and/or know-how.  Many developers who are used to using Hibernate or TOPLink (as only two examples) before in Java or Smalltalk respectively will have likely done a lot of &lt;acronym title="Object Oriented"&gt;OO&lt;/acronym&gt; modeling.  Ask them about the most complex business domain they have modeled previously to be able to guage their skill level and experience in this area.  This point is most important in applications that have more complex business domains.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Why should I care about your data?  Look at my cool Photoshop spinning logo.&lt;/strong&gt;  Rails consulting firms and/or freelancers should have a good understanding of the importance of data modeling.  Even if they do not have specific data modeling expertise they should at least know that indexing appropriate columns and defining column size limits where appropriate can save not just storage space, but also shave time off queries (depending on the query and usage scenario).  That way when your application gets to the point where the database needs to be fine tuned, the data architect you hire will have an easier job than if your schema was designed by a PHP weekender that thinks the Drupal or WordPress database schema is finely tuned (sorry, it's horrendous and yes you should know that anyway).  This is a very important consideration if your application is supposed to hold a considerable amount of data and/or if you have strong reporting requirements.  As a side note, make sure to ask them if different database schemas are sometimes needed for querying large data sets (classical reporting requirements) versus &lt;acronym title="Create-Read-Update-Delete"&gt;CRUD&lt;/acronym&gt; usages.  The answer should be yes and you should ask them to explain this a little to see how much they really &lt;strong&gt;understand&lt;/strong&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;I can design, develop, deploy and manage perfectly.&lt;/strong&gt;  Usually firms and freelancers are much better in one or two areas than all equally.  Some are better at graphic design and got into development to earn $20/hr extra.  That's fine, but you should know what you are getting yourself into.  Ask what their strengths and weaknesses are.  For example, I am excellent at developing and very good at deploying and systems engineering.  I can use Photoshop and Illustrator (just like graphic designers can copy Rails code from forums and paste it into their editor), but ask me to create a visually stunning logo that encapsulates your company's image and I am lost (just like the graphic designers that can't write original code themselves).  Know what is most important for your application needs and hire the appropriate people.  Usually outsourcing graphic design to a design firm and hiring a flexible developer that can work with external teams well, gets you the best value for money.  Throw away the firms and people that don't have any weaknesses.  They are lying.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;One point I would like to make to round this piece off is that if you find a young, eager engineer with higher than average aptitude, he/she can really do a lot for your project.  However, you should expect them to make a few mistakes.  Nobody is perfect and without prior experience with large scale server applications it is virtually impossible for someone not to make mistakes.  If you can afford a few mistakes here and there, then this might be the way to go.  Give them an equity stake if capital is an issue for you, they are more likely to take a risk with you than a seasoned consultant with a mortgage to pay or spouse and children to feed.  However, never hire someone who claims to be a Ruby/Rails expert at a high rate if they simply copy and paste sample code from Ruby/Rails forums online (you would be surprised how many there are out there).  It's a terrible waste of your capital and frankly it takes work away from better firms and/or freelancers out there and you will end up with badly written software that runs poorly.&lt;br /&gt;&lt;br /&gt;As a final note, hire a firm, freelancer or in-house engineer that has similar energy level and compatible personality to yours.  Or at a minimum hire a firm or freelancer that you can trust and has been recommended, but not just through popularity contests like those at WorkingWithRails.com (I know three freelancers who are excellent Ruby engineers with only have 1 recommendation on the site and I have worked with one person that has more than ten recommendations and consider them subpar to most Ruby/Rails developers I know).&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-3163567399148266115?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/3163567399148266115/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=3163567399148266115" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/3163567399148266115" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/3163567399148266115" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/vk9OSCFbZ7g/tips-to-enterpreneurs-hiring-ruby-on.html" title="Tips to Enterpreneurs Hiring Ruby on Rails Consulting Firms" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/09/tips-to-enterpreneurs-hiring-ruby-on.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-1104836026982398911</id><published>2008-09-04T10:13:00.015-05:00</published><updated>2008-09-11T19:22:45.427-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="orm" /><category scheme="http://www.blogger.com/atom/ns#" term="datamapper" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><title type="text">DataMapper: Flexibility of mapping model attributes to table columns</title><content type="html">I know an esteemed ex-colleague of mine (even if he is an Apple zombie now - yes, becoming a fan of Apple on Facebook deserves some heckling;)) has reservations about the apparent unDRY-ness of DataMapper with migrations.  I used to share his reservations before I wrote two applications using DataMapper.  Neither Merb application was particularly spectacular, but both had to work with legacy database schemas.  Oh the joys of crazy DBA naming conventions!&lt;br /&gt;&lt;br /&gt;Let's look at a brief example of DBA naming madness (some names were changed, but the conventions used are the same):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ordersTable:&lt;br /&gt;  - uid_int: int (PK)&lt;br /&gt;  - acc_id_int: int&lt;br /&gt;  - amt_int: int&lt;br /&gt;  - ref_code_string: varchar(64) natural key&lt;br /&gt;  - desc_string: varchar(128)&lt;br /&gt;  - entered_dt: datetime&lt;br /&gt;  - changed_dt: datetime&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In another table managed by a different group we had:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Account:&lt;br /&gt;  - ID: int (PK)&lt;br /&gt;  - Balance: int&lt;br /&gt;  - UserID: int (FK)&lt;br /&gt;  - EnteredDateTime: datetime&lt;br /&gt;  - ChangedDateTime: datetime&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I kid you not.  Two different conventions, both relatively unreadable as Ruby attributes as they both violate popular coding conventions in some way.&lt;br /&gt;&lt;br /&gt;In ActiveRecord you would be left doing non-trivial coding to hide the ugly column names in the model and map Ruby-friendly names to the appropriate column.&lt;br /&gt;&lt;br /&gt;In DataMapper this is not so.  Lending from the design pattern's primary purpose - to explicitly map model attributes to database columns to decouple the two - we can write something like the following using DM:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class Order&lt;br /&gt;  include DataMapper::Resource&lt;br /&gt;  set_table_name("ordersTable") #ridiculous name really, but what can you do if other older applications rely on this already?&lt;br /&gt;&lt;br /&gt;  has(1, :account, :child_key =&gt; 'acc_id_int', :repository =&gt; repository(:accounts))&lt;br /&gt;  property(:id, Integer, :serial =&gt; true, :field =&gt; 'uid')&lt;br /&gt;  property(:amount, Integer, :field =&gt; 'amt_int')&lt;br /&gt;  property(:reference, String, :field =&gt; 'ref_code_string', :key =&gt; true)&lt;br /&gt;  property(:description, String, :field =&gt; 'desc_string')&lt;br /&gt;  property(:created_at, DateTime, :field =&gt; 'entered_dt')&lt;br /&gt;  property(:changed_dt, DateTime, :field =&gt; 'changed_dt')&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class Account&lt;br /&gt;  include DataMapper::Resource&lt;br /&gt;  set_table_name('Account')&lt;br /&gt;&lt;br /&gt;  property(:id, Integer, :serial =&gt; true, :field =&gt; 'ID')&lt;br /&gt;  property(:balance, Integer, :field =&gt; 'Balance')&lt;br /&gt;  property(:created_at, DateTime, :field =&gt; 'EnteredDateTime')&lt;br /&gt;  property(:updated_at, DateTime, :field =&gt; 'ChangedDateTime')&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This way we can write readable Ruby code with the model.&lt;br /&gt;&lt;br /&gt;Next time we can look at lazy loading: how to switch it on and off and when to use it for greater effect.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-1104836026982398911?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/1104836026982398911/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=1104836026982398911" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/1104836026982398911" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/1104836026982398911" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/pXuXmeTvDIM/datamapper-flexibility-of-mapping-model.html" title="DataMapper: Flexibility of mapping model attributes to table columns" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/09/datamapper-flexibility-of-mapping-model.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-2198880354566669059</id><published>2008-09-04T09:27:00.007-05:00</published><updated>2008-09-04T10:03:06.203-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="datamapper" /><category scheme="http://www.blogger.com/atom/ns#" term="merb" /><title type="text">DataMapper does have migrations</title><content type="html">I wanted to bust a myth out there that DataMapper does not have regular migrations, just the auto migrations.  At least in post 0.9 versions DataMapper has both.&lt;br /&gt;&lt;br /&gt;In other blogs about the topic I found quotes like: "DataMapper migrations pull your database structure directly from the Ruby code for your models, so there’s no need to write separate migration files...".  This, in my opinion, gives the wrong impression to those that are worried about non-trivial schema migrations.  The author of that quote appears to have never moved one column into multiple or vice versa (a non-trivial schema change), among other schema changes where a DataMapper auto migration would not work in a production environment.  &lt;br /&gt;&lt;br /&gt;In merb you can just create a new DM migration with the following:&lt;br /&gt;&lt;code&gt;$ merb-gen migration name_of_your_migration&lt;/code&gt;&lt;br /&gt;(Assuming you have set the &lt;code&gt;use_orm&lt;/code&gt; setting to &lt;code&gt;:datamapper&lt;/code&gt; in config/init.rb.)&lt;br /&gt;&lt;br /&gt;A simple DataMapper migration might look something like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;migration 1, :create_orders  do&lt;br /&gt;  up do&lt;br /&gt;    create_table(:orders) do&lt;br /&gt;      column(:id, Integer, :serial =&gt; true)&lt;br /&gt;      column(:amount, Integer)&lt;br /&gt;      column(:completed, Boolean)&lt;br /&gt;      column(:description, String, :size =&gt; 255)&lt;br /&gt;      column(:created_at, DateTime)&lt;br /&gt;      column(:updated_at, DateTime)&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  down do&lt;br /&gt;    drop_table(:orders)&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you have problems with &lt;code&gt;Boolean&lt;/code&gt; not being recognized, throw in the line:&lt;br /&gt;&lt;code&gt;include DataMapper::Types&lt;/code&gt; &lt;br /&gt;to the top of the migration (yes, this needs some finessing obviously).&lt;br /&gt;&lt;br /&gt;Hope that helps a few people that may have been mislead by some blog posts inadvertently.  Migrations are needed for many cases I come across where auto migrations just will not cut it without losing data in production (not a good thing if data matters in your application:)).&lt;br /&gt;&lt;br /&gt;BTW A minor annoyance of mine in Merb is that for DM migrations you need to use this ugly Rake task: &lt;code&gt;dm:db:migrate&lt;/code&gt; to migrate to latest version.  To rollback migrations you need to use this ugly thing: &lt;code&gt;dm:db:migrate:down[version]&lt;/code&gt;.  Where those using AR in Merb just keep using &lt;code&gt;db:migrate&lt;/code&gt; and &lt;code&gt;db:rollback&lt;/code&gt;.  This is an area that needs cleaning up to promote ORM agnosticism the way Merb is supposed to do.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-2198880354566669059?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/2198880354566669059/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=2198880354566669059" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/2198880354566669059" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/2198880354566669059" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/jKyuW4YUewI/datamapper-does-have-migrations.html" title="DataMapper does have migrations" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/09/datamapper-does-have-migrations.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-1749384692716695241</id><published>2008-08-30T08:34:00.012-05:00</published><updated>2009-02-17T15:39:54.334-06:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="RSS" /><category scheme="http://www.blogger.com/atom/ns#" term="xml" /><category scheme="http://www.blogger.com/atom/ns#" term="Feeds" /><title type="text">Next Generation Syndication and Publishing</title><content type="html">For the last year or so, I have been focusing on implementing RSS, Atom publishing and related standards for a particular client in the podcasting industry.  Both RSS and (to a lesser extent due to its standard being finalized much later) Atom are being heavily used not just for blogs, podcasts, videos and multimedia content, but also used heavily for web 2.0 (or social media) activity "watching".&lt;br /&gt;&lt;br /&gt;Most people should be familiar with FriendFeed by now (if not, where have you been?  really!).  This month (August 2008) FriendFeed came out with their Simple Update Protocol (SUP) which sits on top of RSS/Atom publishing to make it easier for content consumers (very self-serving for FriendFeed, but at least they are coming up with some kind of "solution" instead of just bitching about the status quo) to identify feeds that have changed before they make a timed request for the feed every X minutes regardless of whether the feed has changes or not.&lt;br /&gt;&lt;br /&gt;In a nutshell, SUP requires a meta JSON &lt;strong&gt;feed&lt;/strong&gt; that notifies consumers of newly updated feeds to publish data.  The first time an RSS/Atom feed is subscribed to, the consuming agent (e.g. FriendFeed) will strip out the SUP-ID and the SUP feed URL from the &lt;tt&gt;xpath:channel/link&lt;/tt&gt; element and associate this information with the relevant user/account or whatever.  Then using the identifier for a feed returned by the meta JSON feed, the consumer knows the URL associated with that ID for feeds they need to be updated by.&lt;br /&gt;&lt;br /&gt;While this might solve some problems, it really does feel very much like a monkey patch.  On the flip side I do understand to some extent why they took this path of monkey patching as opposed to coming up with something more revolutionary.  Revolutionaries tend to get killed and only the second wave settlers reap the benefits of their blood, sweat and tears.&lt;br /&gt;&lt;br /&gt;However, I did want to mention SixApart's efforts to broadcast frequently updating consumable data in what should be a much more obvious way for former enterprise MOM developers like myself.&lt;br /&gt;&lt;br /&gt;The Six Apart Update Stream broadcasts over HTTP new public updates/posts as they happen.  It's an interesting idea and much closer to the XMPP ideal that companies like Twitter have attempted.&lt;br /&gt;&lt;br /&gt;Any other former enterprise architects merely see this new trend in web [defacto] standards in publishing and consuming data as just another message oriented middleware (MOM)?  And I am hopeful that finally the web has found a MOM in XMPP that can stand the test of public scrutiny.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-1749384692716695241?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/1749384692716695241/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=1749384692716695241" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/1749384692716695241" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/1749384692716695241" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/yGxo5uDAF-k/next-generating-syndication-and.html" title="Next Generation Syndication and Publishing" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/08/next-generating-syndication-and.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-8307808780952707707</id><published>2008-08-21T17:20:00.005-05:00</published><updated>2008-08-21T19:38:28.755-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="paypal" /><category scheme="http://www.blogger.com/atom/ns#" term="scam" /><category scheme="http://www.blogger.com/atom/ns#" term="fraud" /><title type="text">NEVER use or trust Paypal</title><content type="html">For those that have been screwed by Paypal and need to find another venue to conduct business here are some alternative services:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://checkout.google.com"&gt;Google Checkout&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.propay.com"&gt;ProPay&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.bidpay.com"&gt;Authorize.NET&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://corporate.digitalriver.com/store/driv/en_US/ContentTheme/pbPage.Homepage/sectionName.home"&gt;Digital River&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.alertpay.com/?5%2biyjHxo%2ftMvjzwkUb4KZg%3d%3d"&gt;AlertPay&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.e-junkie.com/"&gt;E-Junkie&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;For *some* of the many issues surrounding Paypal/Ebay policies and rules you can check out the following articles:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://money.cnn.com/2008/02/08/smbusiness/paypal_funds_freeze.fsb/index.htm"&gt;EBay's PayPal funds freeze plan draws fire &lt;/a&gt; (CNN Money)&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.consumeraffairs.com/online/paypal_debit.html"&gt;Paypal Debit Card Disputes&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;&lt;a href="http://www.ripoffreport.com/reports/0/324/RipOff0324012.htm"&gt;Ripoff Report: Paypal&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I have recently been royally screwed by Paypal.  However, I have been advised not to comment on specifics until I play all my cards:)&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-8307808780952707707?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/8307808780952707707/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=8307808780952707707" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/8307808780952707707" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/8307808780952707707" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/mOpujwLwWis/never-use-or-trust-paypal.html" title="NEVER use or trust Paypal" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/08/never-use-or-trust-paypal.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-3875087204352500306</id><published>2008-07-22T18:51:00.005-05:00</published><updated>2008-07-22T18:58:14.395-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="open source" /><category scheme="http://www.blogger.com/atom/ns#" term="oss" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter4r" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter" /><category scheme="http://www.blogger.com/atom/ns#" term="opensource" /><title type="text">LA Times Travel uses Twitter4R</title><content type="html">&lt;a href="http://travel.latimes.com/"&gt;LA Times Travel&lt;/a&gt; is now using &lt;a href="http://twitter4r.rubyforge.org" title="Twitter Ruby library"&gt;Twitter4R&lt;span style="display:none"&gt;&amp;nbsp;(Ruby library for the Twitter API)&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can see they sent messages via the Twitter4R for a few hours today (2008-07-22) on their &lt;a href="http://twitter.com/latimestravel"&gt;Twitter timeline&lt;/a&gt; before changing the Twitter4R configuration to not sure which library/application they are using (or just waiting to get Alex to approve their application source code).&lt;br /&gt;&lt;br /&gt;Please let me know if you see Twitter4R sightings being used by other well known or cutting edge applications.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-3875087204352500306?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/3875087204352500306/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=3875087204352500306" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/3875087204352500306" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/3875087204352500306" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/6l6_HFDHaEc/la-times-travel-uses-twitter4r.html" title="LA Times Travel uses Twitter4R" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/07/la-times-travel-uses-twitter4r.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-8556085172217297724</id><published>2008-07-18T08:44:00.005-05:00</published><updated>2008-07-18T16:31:32.457-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="pradipta" /><category scheme="http://www.blogger.com/atom/ns#" term="serendipity" /><title type="text">Serendipity: An original Pradipta's Rolodex member</title><content type="html">Last night I got the &lt;a href="http://blog.reverberate.org/2008/07/17/416-random-people-with-ror-on-their-resume-reply-all-reverse-flash-mob/"&gt;Pradipta's Rolodex message&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Rock on Pradipta!:)&lt;br /&gt;&lt;a href="http://thepradipta416.com" title="Proud Member of the Pradipta 416"&gt;&lt;img src="http://thepradipta416.com/img/badge2.gif" alt="The Few, The Proud, The Pradipta 416"/&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-8556085172217297724?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/8556085172217297724/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=8556085172217297724" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/8556085172217297724" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/8556085172217297724" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/D4F-Fy6A13M/serendipity-original-pradiptas-rolodex.html" title="Serendipity: An original Pradipta's Rolodex member" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/07/serendipity-original-pradiptas-rolodex.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-1920917351345516137</id><published>2008-06-30T22:04:00.003-05:00</published><updated>2008-07-01T10:13:53.471-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="open source" /><category scheme="http://www.blogger.com/atom/ns#" term="oss" /><category scheme="http://www.blogger.com/atom/ns#" term="rubyforge" /><category scheme="http://www.blogger.com/atom/ns#" term="git" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter4r" /><category scheme="http://www.blogger.com/atom/ns#" term="github" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter" /><category scheme="http://www.blogger.com/atom/ns#" term="opensource" /><title type="text">Twitter4R Development Releases</title><content type="html">Over the last week or so I have been putting Twitter4R sources in GitHub and getting the on-the-fly GemSpec to work "safely" enough for GitHub servers.  Tonight (June 30) I decided I would announce Twitter4R development micro-releases available only via the GitHub gem server.  To setup your environment to install the latest development release of &lt;a href="http://twitter4r.rubyforge.org"&gt;Twitter4R&lt;span style="display:none"&gt;: the most complete Ruby client bindings for the Twitter.com REST API&lt;/span&gt;&lt;/a&gt;, please read &lt;a href="http://github.com/mbbx6spp/twitter4r/wikis/howto-install-github-development-releases"&gt;HowTo: Install GitHub Development Releases&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Official documentation will still exist through the official &lt;a href="http://twitter4r.rubyforge.org/"&gt;Rubyforge project site of Twitter4R&lt;/a&gt;, but any documentation related to current development tasks, features, bugfixes will now be documented on the &lt;a href="http://github.com/mbbx6spp/twitter4r/wikis"&gt;Official Twitter4R GitHub Wiki&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you want to keep an eye on the Git repository, feel free to &lt;a href="http://github.com/mbbx6spp/twitter4r/toggle_watch"&gt;watch the mbbx6spp/twitter4r&lt;/a&gt; GitHub repository.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-1920917351345516137?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/1920917351345516137/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=1920917351345516137" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/1920917351345516137" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/1920917351345516137" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/Uv_hr4iZEts/twitter4r-development-releases.html" title="Twitter4R Development Releases" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/06/twitter4r-development-releases.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-6162266326860941502</id><published>2008-05-20T14:12:00.015-05:00</published><updated>2008-05-20T15:09:07.834-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="apple" /><title type="text">Rails rocks, X sucks: How Provincial</title><content type="html">I seem to be coming across more and more [Steve] Jobs-clones or simply no-thinking Apple fan boys lately.  I don't mind the Apple fans that thought themselves about why they love their stylish new Macbook Pro, I have just had enough of the no-thinking variety of Apple zealots.&lt;br /&gt;&lt;br /&gt;This part of the Rails community appears to be a large population unfortunately.  Because these fan boys are actually incapable of thinking on their own, they adopt other people's arguments and say things like: "Rails rules, X sucks because so-and-so said this...".  Hmmmm.   Need I say more?&lt;br /&gt;&lt;br /&gt;On the other side I recently came across a Django fan boy who tried to convince his non-technical manager that Rails "cannot scale period".  Hmmmm.  How original.  A blanket statement like this is not only misleading, it is actually in many ways technically incorrect.  This is why in middle school we learned how to qualify our arguments.  Why is it that supposed college graduates cannot do this in their 20s and 30s?  It is one thing to strip out technical jargon for non-technical managers to understand a situation, but it is quite another to over simplify and mislead them because you have your own tech-religion agenda.  Be passionate, but admit to yourself and others when passion is getting the better of you.&lt;br /&gt;&lt;br /&gt;Why is acknowledging your chosen solution's weakness bad?  Doesn't it actually make the solution implementation stronger if you have thought about scenario-based weaknesses?  &lt;br /&gt;&lt;br /&gt;How about we each try to &lt;b&gt;*qualify*&lt;/b&gt; our positions on technology solutions out there, rather than figuratively urinate all over others without any basic respect for them.  I encourage criticism, but criticize constructively.  Say why.  On the flip side, we should also accept constructive criticism too.  &lt;br /&gt;&lt;br /&gt;The first step to constructive criticism, need not necessarily be candy coating your critique, but having the right intentions behind your critique.  For example, if your motivation for giving criticism is to start a flame war (sorry that is probably a very out of date term now), then you will probably get what you want.  However, if you really want to help a project get better because you care, then that is the first step.  &lt;br /&gt;&lt;br /&gt;In addition, the way you word and tone statements (as Twitter's Alex Payne should have learned all too well by now) has a big impact.  For example, Alex Payne's statements about Rails and Ruby cost me a contract at a former Rails shop that had a conniving PHP zealot waiting in the wings to jump on anything and take issue with Rails to upper management.  Lucky for him, it worked and he had 3 to 4 months of leading a team to miserable failure using Drupal as a "platform".  Not necessarily a reflection of PHP (or Drupal for CMS applications since it was far from a CMS application), but a reflection of this calculating pseudo-coder's inability to lead a project.  A "technical" manager who thought the kernel version on his Fiesty Ubuntu laptop was 7.0.4.  Enough said!:)&lt;br /&gt;&lt;br /&gt;Overall, I hope we can start to have intelligent conversations about software stacks rather than "yours sucks ass".  Because the latter in the end favors nobody.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;PS Merb rulez and Rails suckz!:)  If you want to know why read my teaser entry titled &lt;a href="http://snakesgemscoffee.blogspot.com/2008/05/why-merb-is-delicious.html"&gt;Why Merb is delicious&lt;/a&gt;, though I plan on writing more soon.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;PPS Merb wouldn't be where it is today without Rails.&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-6162266326860941502?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/6162266326860941502/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=6162266326860941502" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/6162266326860941502" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/6162266326860941502" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/1DSdGKljI9Q/rails-rocks-x-sucks-how-provincial.html" title="Rails rocks, X sucks: How Provincial" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/05/rails-rocks-x-sucks-how-provincial.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-2355125211359606383</id><published>2008-05-06T08:49:00.010-05:00</published><updated>2008-05-06T09:15:31.222-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="merb" /><title type="text">Why Merb is delicious</title><content type="html">Below are the reasons why &lt;a href="http://merbivore.com"&gt;Merb&lt;/a&gt; is more delicious than other MVC web frameworks I have worked with (including Rails):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;On a diet...&lt;/b&gt;It is lighter weight than most, but still has enough oomph to implement common features with minimal code&lt;/li&gt;&lt;li&gt;&lt;b&gt;Religion-free...&lt;/b&gt;It is ORM, JavaScript/AJAX and testing/speccing library agnostic.&lt;/li&gt;&lt;li&gt;&lt;b&gt;The sum of it's parts...&lt;/b&gt;OK that was a lame segway, but &lt;b&gt;parts&lt;/b&gt; is a mightily useful feature where a plugin is just total overkill.  Just because Java calls something a "component" does not make it the general definition of a component in concept.  And now look at the Rails plugin debacle today.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Precious gems...&lt;/b&gt;Plugins are created, distributed and installed in the form of beautiful RubyGems as opposed to the Rails plugin catastrophe with Gigabytes of duplicate disk space and lame version/revision control&lt;/li&gt;&lt;li&gt;&lt;b&gt;It's exceptional...&lt;/b&gt;Merb actually thought about how to do exception handling in controllers before Rails came up with something and also came up with IMHO a better solution.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Speedy Gonzalez...&lt;/b&gt;Compared to especially Rails, Merb performs &lt;a href="http://www.webficient.com/2007/08/testing-various-configurations-of-rails.html"&gt;very nicely indeed&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Loose threads...&lt;/b&gt;Merb is thread-safe unlike Rails, so that means one process can handle multiple concurrent file uploads, where Rails cannot right now.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;All together I think most people will find Merb to be a much better thought out (conceptually) MVC framework than Rails.  Over the next few weeks I'll be talking a lot about Merb and it's delicious APIs, Plugins, etc. as it nears it's 1.0 release.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-2355125211359606383?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/2355125211359606383/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=2355125211359606383" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/2355125211359606383" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/2355125211359606383" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/od1CXs5jHjs/why-merb-is-delicious.html" title="Why Merb is delicious" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/05/why-merb-is-delicious.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-2880256725987487057</id><published>2008-04-04T10:23:00.001-05:00</published><updated>2008-04-04T11:54:50.304-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="chicago" /><category scheme="http://www.blogger.com/atom/ns#" term="jug" /><category scheme="http://www.blogger.com/atom/ns#" term="cjug" /><title type="text">Comedy of Errors</title><content type="html">Does anyone else find it comical that the &lt;a href="http://cjug.org/uger/directory/list"&gt;Chicago Java Users Group&lt;/a&gt; website is written in Rails?  And apparently not very well if it is not only sending a HTTP 500 error, but still using the default Rails generated 500.html page.  Poor all around.&lt;br /&gt;&lt;br /&gt;An IM buddy mentioned it might be JRuby, but I do think it is still very ironic considering the hostility from the Java world regarding Rails in general (whether Ruby on Rails or JRuby on Rails).&lt;br /&gt;&lt;br /&gt;I just had to share!:)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt; Someone fixed it shortly after I reported it to CJUG.&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt; Actually it was only temporarily fixed, it is back to the default 500 Rails error page.&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt; In addition they have exposed their SVN information.  See the &lt;a href="http://cjug.org/uger/.svn/entries"&gt;public entries&lt;/a&gt; and from that information you can find their &lt;a href="http://svn.oaktop.com/Uger/trunk/"&gt;non-password protected source code and check it out&lt;/a&gt; if you like.&lt;br /&gt;&lt;br /&gt;If anyone from CJUG is reading, you can fix this by reading my blog entry from two months back called &lt;a href="http://snakesgemscoffee.blogspot.com/2008/02/preventing-information-leaks-part-3.html"&gt;Preventing Information Leaks, Part 3&lt;/a&gt;.  Although it might be useful to read &lt;a href="http://snakesgemscoffee.blogspot.com/2008/02/preventing-information-leaks-part-1.html"&gt;part 1&lt;/a&gt; and &lt;a href="http://snakesgemscoffee.blogspot.com/2008/02/preventing-information-leaks-part-2.html"&gt;part 2&lt;/a&gt; as well.  Cheers!&lt;br /&gt;&lt;br /&gt;PS I also sent an email to &lt;code&gt;info at cjug.org&lt;/code&gt; and received an email delivery error.&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Update:&lt;/b&gt; I may have read too much into the SVN repository information exposure in this specific case since this is an open source Rails application project (I only just realized), thus the non-password protected repository, but I still stand by the rest!:)  It is also not good practice to expose such information from the outset of deploying an web application.&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Update (1.5 hours after trying to notify JUG and posting the blog post):&lt;/b&gt; The site has been fixed now for over 5 minutes, so good job fixing it CJUG!:)&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Update (8 minutes later):&lt;/b&gt; Ooooops!  It is back to the default Rails 500 error page.  Perhaps it is 2 out of three bad FastCGI processes that need to be killed on the server?  HTH someone at CJUG, but since I can't look at the system I can't say for sure.&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-2880256725987487057?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/2880256725987487057/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=2880256725987487057" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/2880256725987487057" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/2880256725987487057" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/PykWnXmKoiM/comedy-of-errors.html" title="Comedy of Errors" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/04/comedy-of-errors.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-25066620.post-125069007997943352</id><published>2008-04-01T10:34:00.007-05:00</published><updated>2008-04-01T10:58:22.947-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="php" /><category scheme="http://www.blogger.com/atom/ns#" term="coding" /><title type="text">Coding with Explicit Intentions</title><content type="html">Recently I have had the [mis]fortune to be working with PHP for integration purposes for a client.  A partner of my client's (in the advertising space) sent us some PHP code to add to our servers for resolving the content type of a file based on its extension.  The line of code in the PHP script they sent over that was supposed to determine the file extension was:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  $ext = substr($file,-4);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;As you can see they are making a pretty big assumption - that the extension is exactly three letters long.  The media files that this script *may* support in the future are: Real Media (.rm), MPEG (.mpeg), Quicktime (.qt), etc.  These extensions are not exactly three letters long.  Why would someone want to write code that is quite likely to fail and also not communicate more explicitly their intentions?  &lt;br /&gt;&lt;br /&gt;This partner already doesn't support PHP &lt; 4.0.3, so why not substitute the line above with:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  $ext = ".".pathinfo($file, PATHINFO_EXTENSION);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;It is standard, will never fail (unless there is a defect in the PHP version you are using for the standard function pathinfo, but what can you do about that?) and communicates the explicit intent of the original author, thus improving code maintainability.&lt;br /&gt;&lt;br /&gt;Anyway, just a pet peeve.  This is not by any means the only example I see on a day in day out basis, this just happened to be a great example for me to demonstrate my point.  While this example demonstrates a minor one-line demonstration, if developers introduce even only 2-3 of these un-explicit intentioned lines of code a day that do not always do what you might want it to do, then the codebase quickly becomes a mine field.&lt;div class="blogger-post-footer"&gt;2006-2008 Copyright (c) Susan Potter [http://susanpotter.net].  All rights reserved.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25066620-125069007997943352?l=geek.susanpotter.net'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://geek.susanpotter.net/feeds/125069007997943352/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=25066620&amp;postID=125069007997943352" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/125069007997943352" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/25066620/posts/default/125069007997943352" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/SnakesGemsCoffee/~3/1muIvL7DryY/coding-with-explicit-intentions.html" title="Coding with Explicit Intentions" /><author><name>S. Potter</name><uri>http://www.blogger.com/profile/17341145424164713662</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10967243213996769910" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://geek.susanpotter.net/2008/04/coding-with-explicit-intentions.html</feedburner:origLink></entry></feed>
