<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/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:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6845919040715696857</id><updated>2011-12-29T15:02:43.539-08:00</updated><category term='ruby'/><category term='job protection'/><category term='testing'/><category term='plugins'/><category term='web services'/><category term='quack ideas'/><category term='os'/><category term='html'/><category term='rails'/><title type='text'>Rubyssimo</title><subtitle type='html'>Ruby, Rails, Postful, and Some Truly Hideous Ideas</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-3018495895343993893</id><published>2007-07-23T16:46:00.000-07:00</published><updated>2007-07-23T16:52:33.297-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Another Ruby Scoping Shocker</title><content type='html'>Try this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;i = 10&lt;br /&gt;5.times do |i|&lt;br /&gt;end&lt;br /&gt;i&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;What would you expect the value of &lt;b&gt;i&lt;/b&gt; to be? Coming from a language like Java with its nested variable scoping, I would expect &lt;span style="font-weight:bold;"&gt;10&lt;/span&gt;. But it is not so in Ruby.&lt;br /&gt;&lt;br /&gt;The result is &lt;span style="font-weight:bold;"&gt;4&lt;/span&gt;, the last value of the variable passed to the block.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-3018495895343993893?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/3018495895343993893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=3018495895343993893' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/3018495895343993893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/3018495895343993893'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/07/another-ruby-scoping-shocker.html' title='Another Ruby Scoping Shocker'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-1683063948959847820</id><published>2007-06-29T09:43:00.001-07:00</published><updated>2007-06-29T09:44:53.551-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='web services'/><title type='text'>A Thought on Rails and Web Services</title><content type='html'>A very simple thought occurred to me the other day about Rails, REST, and Web services. The WS-* platforms had sidestepped web application frameworks when it came to the business of developing web services. At the most, you might tunnel service requests through a single controller before passing them on to whatever was processing the WS-* protocols. All that work you might have done in crafting your web application didn't mean much when it came to the Web service. In fact, you would have to start all over. It is not just a matter of work, of course, but of skill sets. WS-* spurned the lowly web developer. You gotta read 15 books and take 20 classes before you're up there with the big boys doing enterprise service stacks. &lt;br /&gt;&lt;br /&gt;It seems to me that REST and Rails are an effort to grab mindshare about whether the web application framework should have something to do with a web service. I find it interesting that it took us this long to hit upon this simple proposition. For example, there is nothing to a prevented earlier WAFs from having tried a similar grab at mindshare. REST on Struts could have been the hype five years ago. In fairness, the Java frameworks tend to try to specialize and see having only a single purpose as a virtue. I don't know much in Java open-source that aims to be as pervasive as Rails.&lt;br /&gt;&lt;br /&gt;Of course, Java had other reasons for fighting REST. Web services are a direct competitor to EJB as a means of enterprise interoperability. And dropdead simple web services rout EJB for all but a few use cases. What is more, using frameworks, not conventions, is the Java away.&lt;br /&gt;&lt;br /&gt;Java always took a particular attitude toward simplicity. In the Java world, simplicity was code generation. Java products often advertise themselves by how much code they can generate. In my world, simplicity is emphatically not code generation. Code generation is a sure sign that something has gone seriously wrong with my tool set. Generated code (until the days that code is generated by a bona fide AI) is always somehow a conceptual redundancy in an application. And redundancy is going to become a maintenance burden.&lt;br /&gt;&lt;br /&gt;It is quite simply very exciting that we are now moving away from the idea of adopting standards for the sake of the tools we can fetch to help observe them, and that we are moving towards the idea that standards are wonderful because of how they allow us to participate in a service and software ecosystem that has been built around them. One was the vision of big software vendors eager to make large-scale sales. The other was the vision behind the W3C protocols.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-1683063948959847820?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/1683063948959847820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=1683063948959847820' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/1683063948959847820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/1683063948959847820'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/06/thought-on-rails-and-web-services.html' title='A Thought on Rails and Web Services'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-1471696108849770869</id><published>2007-05-30T15:09:00.001-07:00</published><updated>2007-05-30T15:14:28.044-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>ActiveRecord Validations Gotcha</title><content type='html'>Adding a validation to an ActiveRecord model over live data can cause &lt;span style="font-weight:bold;"&gt;sudden inexplicable brain-shattering headache&lt;/span&gt;. Why? &lt;br /&gt;&lt;br /&gt;If the new validation causes existing rows to be invalid, any attempt to update attributes on the object without correcting the offending attribute will fail. This will happen, even if an html form that fronts the model doesn't provide an opportunity for your user to modify the attribute. And, boy, that can disorient your users. Any part of your application touching that row will become unwritable.&lt;br /&gt;&lt;br /&gt;ActiveRecord's tight policy makes you think hard about what you're doing, which might be a good thing. It's hard to see alternatives that maintain ActiveRecord's simplicity. If your application never modifies rows outside of user-generated CRUD and if each model object corresponds to a single form, then you should be okay. But plenty of good application designs cannot meet both those criteria.&lt;br /&gt;&lt;br /&gt;The best alternative behavior I could think of would be a "partial" validation. That is, a validation check only occurred on attributes that had been modified on the object, the "dirty" attributes, so to speak, letting other invalid attributes flyby. Eventually, an invalid row is going to kill you. After all, there is a reason it is &lt;span style="font-style:italic;"&gt;invalid&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;And while I prefer a noisy failure to a quiet failure, I'd rather not my application lockup and my users bear the burden of my oversight. I can even imagine a validations mechanism that strictly enforced partial validation, but performed full validation, alerting the developers in some loud cantankerous way if full validation failed but partial did not.&lt;br /&gt;&lt;br /&gt;Depending on the size of your database, it might be a good idea to database validity during a migration. You could iterate through all rows, calling Active Record#valid? on each, and raise an exception failing on a validation failure. It could report or enact some other policy. Consider adding a migration for each such validation. A validation that invalidates existing rows is really no different than a database migration. After all, in olden times, much of the constraints expressed in validations were expressed in the database schema itself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-1471696108849770869?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/1471696108849770869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=1471696108849770869' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/1471696108849770869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/1471696108849770869'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/05/activerecord-validations-gotcha.html' title='ActiveRecord Validations Gotcha'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-4220654135894101291</id><published>2007-05-28T22:07:00.000-07:00</published><updated>2007-05-29T11:30:53.199-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web services'/><title type='text'>REST and Transactional Web Services</title><content type='html'>There's a long way to go before distributed programming becomes as safe and as simple as non-distributed programming. But if the Web is going to meet its potential of interoperable services locking together to create seamless, smart software, we need to get there. And here's something we need: &lt;span style="font-weight:bold;"&gt;distributed transactions&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;One shortcoming we've found to Amazon Web Services has been this: we can send something to &lt;a href="http://www.amazon.com/gp/browse.html?node=16427261"&gt;S3&lt;/a&gt;, to &lt;a href="http://www.amazon.com/Simple-Queue-Service-home-page/b?ie=UTF8&amp;node=13584001"&gt;SQS&lt;/a&gt;, and then to our database, but while we can rollback our database, we cannot rollback Amazon. There is a danger that an application operating over these distributed services can be left in an inconsistent state, and that's just no fun for users. EJB was designed to solve such problems with distributed transactions, but the cost of that was, well, EJB.&lt;br /&gt;&lt;br /&gt;How does REST clarify this picture? REST gives us a uniform, simple way to describe web services. This makes it easy to describe one Web service call to another Web service. In fact, it makes it easy to describe any RESTful Web service call to a Web service. Yes, the meta-web service! We need only supply a verb, a URL, and maybe a few headers. Signature-based authentication makes it easy to authorize a service to make a call on another without releasing your credentials. With this, I can imagine Web service &lt;span style="font-style:italic;"&gt;filtering&lt;/span&gt; or Web service &lt;span style="font-style:italic;"&gt;tunneling&lt;/span&gt;: calling one service through another.&lt;br /&gt;&lt;br /&gt;Here is the Web service I would love to see Amazon develop next: &lt;span style="font-weight:bold;"&gt;a transaction service&lt;/span&gt;. There are many, many ways to do this, but here's just one proposal. A client can create a transaction resource with Amazon, describing all the service calls comprising the transaction. Then, Amazon can act as a coordinator for a &lt;a href="http://en.wikipedia.org/wiki/Two-phase_commit"&gt;2PC&lt;/a&gt; (or &lt;a href="http://en.wikipedia.org/wiki/Three-phase_commit_protocol"&gt;3PC&lt;/a&gt;) transaction protocol. Any service that can work within such a transaction, of course, has to implement the protocol.&lt;br /&gt;&lt;br /&gt;This has some disadvantages. For one, the client wouldn't be able to change state based on the responses of intermediary service calls. For another, it's hard to see how the client could commit the transaction synchronously (And without synchronous response, much of the ease of use of the Web is lost). &lt;br /&gt;&lt;br /&gt;For the first problem, I can imagine another way of working this without tunneling. This involves splitting up coordinator duties in 2PC. The transaction client can herself make calls to cohorts during commit-request phase, then letting the transaction service takeover as coordinator during the commit phase.&lt;br /&gt;&lt;br /&gt;As for the second problem, creating a long-running task is pretty easy for human clients. Just give them a callback for their browsers to keep polling. &lt;a href="http://backgroundrb.rubyforge.org/"&gt;BackgrounDRB&lt;/a&gt; works like this. For the machine-readable Web, a callback URL to submit check transaction status changes is easy enough. Another alternative is for the service to expose a REST transaction resource which its consumers can poll.&lt;br /&gt;&lt;br /&gt;What more is needed?&lt;br /&gt;&lt;br /&gt;(1) Some way to describe transactional status within REST resources.&lt;br /&gt;&lt;br /&gt;(2) Some way for applications to implement transactional undo/redo across network latencies without locking too many resources. This part is difficult. Database transactions really aren't up for being kept open for long periods of time. We may need new tools to make this happen or at least a better understanding of the design and performance issues involved.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-4220654135894101291?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/4220654135894101291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=4220654135894101291' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/4220654135894101291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/4220654135894101291'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/05/rest-and-transactional-web-services.html' title='REST and Transactional Web Services'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-3963317796875383949</id><published>2007-05-26T17:21:00.000-07:00</published><updated>2007-05-26T18:44:08.991-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='web services'/><title type='text'>The Web: Waiting for the Other Shoe to Drop</title><content type='html'>The philosophy behind REST design has always struck me as having this back-to-the-basics feel: Let's use HTTP verbs as they were originally intended. It's not the first time the community has looked across the convoluted territory of HTTP and felt a reformist impulse. After all, back in the late 90s, there was a lot of talk about how XHTML + CSS would help bring machine readability back to web pages by separating content from layout. The Semantic Web was supposed to further this by providing an ontology to this clean, machine-readable content. Even WS-* web services were supposed to bring about this magical world of seamlessly interoperable machines all plugging into each other.&lt;br /&gt;&lt;br /&gt;REST brings new hope. We have a clean, uniform interface for clients to interact with one another. Tools like ActiveResource help reinforce the idea that the interface to a distributed resources can be just the same as the interface to local resources. But which clients should interact with which services and why clients ought to interact with them remain questions answered only by human intervention. What if we can find a layer of abstraction to help chip away at &lt;span style="font-style: italic;"&gt;this&lt;/span&gt; problem? Actually "solving" the problem might be the realm of AI fantasyland. But I think we can begin to chip away at. And that's progress.&lt;br /&gt;&lt;br /&gt;We've already had something basic like this in the past. For example, back in the day using the Web required finding a list of servers that implemented a particular Internet protocol: gopher, IRC, etc. Interoperability occured at the level of protocol. Can we make interoperability happen at the level of semantic description of service with REST?&lt;br /&gt;&lt;br /&gt;This is the thought that occurred to me reading Richardson and Ruby's excellent &lt;a href="http://www.amazon.com/RESTful-Web-Services-Leonard-Richardson/dp/0596529260/ref=pd_bbs_sr_1/103-3709930-3340630?ie=UTF8&amp;s=books&amp;qid=1180225486&amp;sr=8-1"&gt;RESTful Web Services&lt;/a&gt;. As they point out:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Computers do not know what "modifyPlace" means or what data might be a good value for "latitude".&lt;/blockquote&gt;&lt;br /&gt;Well, why not? A computer can certainly know what a good value for an email address is. We take it for granted that a compiler knows the difference between an integer and a string. Why not latitude? We just need one more layer of abstraction above what we have today, before clients can consume services without having been programmed in advance.&lt;br /&gt;&lt;br /&gt;It prompts the question: how distributed do we want programming to be? I can imagine the ontology itself being a Web service. If a client did not know what latitude was, it could just look it up. What would the service provide? I can imagine lots. An ontology, validations, algorithms, related services.&lt;br /&gt;&lt;br /&gt;REST is real progress, because it simplifies things. Hopefully we'll be spending less time wiring together our Web service stacks and more time thinking about the big picture.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-3963317796875383949?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/3963317796875383949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=3963317796875383949' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/3963317796875383949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/3963317796875383949'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/05/web-waiting-for-other-shoe-to-drop.html' title='The Web: Waiting for the Other Shoe to Drop'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-2555870369751316247</id><published>2007-05-22T11:56:00.000-07:00</published><updated>2007-05-22T11:59:16.212-07:00</updated><title type='text'>The Document Abstraction</title><content type='html'>There are two ways to go with an Office 2.0 application. You can either use the familiar document abstraction, where the user makes changes to the document within the browser and finally commits them with a save. This is the familiar Office workflow, with the document being kept in JavaScript memory. The alternative is to break the document abstractions somehow. Basecamp is a great example of this. You do not work with a single monolithic document. Instead, you make and commit small changes, one change at a time.&lt;br /&gt;&lt;br /&gt;From the point of view of building a web application, the second way is the much friendlier way to go. Easier on the browser. Easier on the database. But it's not really feasible for applications competing against the word processor or the spreadsheet. I suspect that those using the document abstraction are eventually gonna run into problems with very large documents. After all, there are going to be costs to tunneling through HTTP and browsers. Those tunneling costs are likely to surface as performance issues. We all know how some browsers begin to choke on very large pages. Toss big pages together with lots of data kept in JavaScript and you have a recipe for trouble.&lt;br /&gt;&lt;br /&gt;There is a technical opportunity here, I feel. The great thing about the browser is that it is a universal platform. The terrible thing about the browser is that it really wasn't designed to be an application platform. If a developer wants to build a document-centric Web application, she is still missing that sweet spot of tools and best practices to make things work out. Is Flex the answer? Is Java WebStart?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-2555870369751316247?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/2555870369751316247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=2555870369751316247' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/2555870369751316247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/2555870369751316247'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/05/document-abstraction.html' title='The Document Abstraction'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-4363236596321474543</id><published>2007-05-01T22:54:00.000-07:00</published><updated>2007-05-01T23:51:45.732-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Unit Testing and Purity</title><content type='html'>Tim Lucas has a fine &lt;a href="http://www.toolmantim.com/article/2007/3/27/if_youve_been_ignoring_mocking"&gt;article&lt;/a&gt; on mocking and Rails testing which touches on some themes that I also hit on in an &lt;a href="http://rubyssimo.blogspot.com/2007/04/ddd.html"&gt;earlier post&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;There is a &lt;a href="http://rubyforge.org/pipermail/mocha-developer/2007-March/000227.html"&gt;tendency&lt;/a&gt; towards &lt;a href="http://blog.jayfields.com/2006/06/ruby-on-rails-unit-tests.html"&gt;keeping&lt;/a&gt; &lt;a href="http://www.verticalexpressionsoftware.com/blog/2006/06/17/converting-to-using-testrails/"&gt;functional&lt;/a&gt; &lt;a href="http://blog.jayfields.com/2006/09/rubyrails-unit-testing-in-less-than-1.html"&gt;tests&lt;/a&gt; &lt;a href="http://blog.testingrails.com/2006/9/26/how-to-make-active-record-rails-tests-run-faster"&gt;pure&lt;/a&gt; in Rails.&lt;br /&gt;&lt;br /&gt;Now, I find myself in a different position. I need to exercise my code as much as possible with the little time I have, so I like to get lots of testing bang for my buck. That means that the pragmatist in me wins over the purist who'd like to see each strata tidily tested in its own appropriate testing layer which does not so much as touch the code stink of another layer, let alone the putrescent code fart-bomb that is the database.&lt;br /&gt;&lt;br /&gt;Frankly, I regard it as one of the strengths of Rails that I'm again close to my database. Unlike my magnificent Tapestry+Struts+Spring+Hibernate architectures of old, I'm again within earshot of something that &lt;span style="font-style: italic;"&gt;actually has implications for my users&lt;/span&gt;, no longer in that level of coding hell where I was which is testing Data Transport Objects and testing the XML configuration of my DTOs and testing my database schema declaration so that it would not be altered while I was busy testing all those other things that I had to be testing to, ya know, save a record in a database -- all of course in perfect TDD abstraction from my database, database connection, web controller, and views, and pretty much in abstraction from the 6,000 things that can and will go wrong. But at least I know my DTO code is impeccable! A bullet-proof POJO! My business logic is flawless, portable. Oh, wait. I didn't write any business logic, which is properly abstracted away into a business logic container framework. Whatever. Come break me!&lt;br /&gt;&lt;br /&gt;Testing purists say the solution to this is just more tests, and they are certainly right. The problem is that a small startup simply doesn't have the resources. All this code does come at a cost. Can we do things less purely but more efficiently?&lt;br /&gt;&lt;br /&gt;What is crucial to a smallish application is &lt;span style="font-style: italic;"&gt;code coverage&lt;/span&gt;, not purity of testing style. This is particularly true for uncompiled languages, where there is no such thing as compilation to give you even a smoke test on your code.&lt;br /&gt;&lt;br /&gt;Five layers of well-segregated tests are just great, but one layer of impure tests is far, far better than any number of layers of pure tests where some layer somewhere has gone uncovered.&lt;br /&gt;&lt;br /&gt;But this alternative approach of a single round-trip from user to database and back has costs of its own. You pay a price in test fragility. Fragility is a symptom of concerns that are improperly coupled.&lt;br /&gt;&lt;br /&gt;Lucas has hit on this problem: Rails controller tests basically change each time you change your validations. Repairing them involves duplicating validation concerns within controller tests. Fixtures seemed originally intended to resolve this problem, but they don't lighten the load any, they just hide it off in another file, which can become a curse of its own.&lt;br /&gt;&lt;br /&gt;He proposes using &lt;a href="http://mocha.rubyforge.org/"&gt;mocha&lt;/a&gt; to stub out ActiveRecord objects during controller testing. Problem is that views will make calls on all kinds of properties, and stubbing each property just recreates the same coupling problem that stubs were supposed to get around.&lt;br /&gt;&lt;br /&gt;One solution is to turn rendering off, but it's just very very useful to have something exercising the rendering code as a basic sanity check.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;So my suggestion?&lt;/span&gt; What if each model object kept a class method for creating a single valid instance of itself? Something like &lt;code&gt;Object.fixture&lt;/code&gt;? At least the responsibility then remains with the model object  itself,  close to the declaration of its validations. And the controller tests stay uncluttered. You can change properties on that single instance in your test itself, if that particular value is what you are testing. This way, the controller tests do not break. And if you add validations, changes only need to be made in one other method.&lt;br /&gt;&lt;br /&gt;A low-fi suggestion, to be sure.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-4363236596321474543?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/4363236596321474543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=4363236596321474543' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/4363236596321474543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/4363236596321474543'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/05/unit-testing-and-purity.html' title='Unit Testing and Purity'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-5972781799297943209</id><published>2007-04-29T20:33:00.000-07:00</published><updated>2007-04-29T21:14:29.435-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='job protection'/><title type='text'>Insano-Pattern: Tuple Madness</title><content type='html'>Here at this blog I hope to be documenting all kinds coding tricks sure to keep you indispensable to your employers. This one's for the dynamic languages only: &lt;a href="http://blog.objectmentor.com/articles/2007/02/13/tuple-madness"&gt;tuple madness&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The pattern is this:&lt;br /&gt;&lt;h3&gt;Never return anything from a method call that is not wrapped in an array.&lt;/h3&gt;Do:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Prefer returning many objects at once to creating a struct-like container for them.&lt;/li&gt;&lt;li&gt;Return objects of &lt;span style="font-style: italic;"&gt;extremely&lt;/span&gt; heterogenous types,  sharing no ancestor class whatsoever.&lt;/li&gt;&lt;li&gt;Use well-known mathematical sequences as type-indicating indices to your array, placing -- for example -- Orders on all Fibonacci numbers and Users on all perfect squares, with perfect squares taking precedence. Point out that this allows rapid &amp;lt; O(n) array traversal.&lt;/li&gt;&lt;li&gt;Once, &lt;span style="font-style: italic;"&gt;just once&lt;/span&gt;, return [[[]]] and parse it out as the true set-theoretic definition of the number 2.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Don't:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Document your return types in comments.&lt;/li&gt;&lt;li&gt;Return types in a consistent order. Use the handy-dandy shuffle function.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Return a consistent number of objects. Different code paths should sometimes leave four objects, sometimes five.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;If someone criticizes your code, tell them that: &lt;ul&gt;&lt;li&gt;Your coding is LISPish, and that there is just nothing as beneficial to developer productivity as LISP and its powerfully productive list abstractions.&lt;/li&gt;&lt;li&gt;You are taking advantage of duck typing and that you work twice as quickly as you did in the days of static programming.&lt;/li&gt;&lt;li&gt;You are practicing defensive programming and making sure that no dreaded null pointer exception will ever be thrown again. You are doing this by enforcing a scrupulously consistent contracts on each method's return type, and that you really deserve a raise for all the debugging costs you are saving the company. (Note that this should not prevent you from returning nil wrapped in an array).&lt;/li&gt;&lt;li&gt;Typing is just not Agile®. Finishing user story cards is all that counts.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-5972781799297943209?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/5972781799297943209/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=5972781799297943209' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/5972781799297943209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/5972781799297943209'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/04/insano-pattern-tuple-madness.html' title='Insano-Pattern: Tuple Madness'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-962238028878539943</id><published>2007-04-27T12:01:00.000-07:00</published><updated>2007-04-28T15:33:30.994-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='os'/><category scheme='http://www.blogger.com/atom/ns#' term='quack ideas'/><title type='text'>Coghead Revisited -- A New Kind of OS?</title><content type='html'>&lt;strong&gt;Teaching the Whole Office to Program&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Since my elementary school days of turtle programming and BASIC, there's been talk about the importance of teaching more people -- &lt;a href="http://www.kidsprogramminglanguage.com/kids.php"&gt;kids&lt;/a&gt; &lt;a href="http://www.rubyinside.com/hackety-hack-an-amazing-ruby-environment-for-beginners-466.html"&gt;even&lt;/a&gt; -- how to program, making programming into a basic skill, so that anyone could use it to improve her productivity anytime she wanted to without hiring an IT consultant. And the focus -- in this great quest -- has often been on making programming languages a lot easier to &lt;a href="http://www.primidi.com/2005/03/24.html"&gt;understand&lt;/a&gt;, easier to read. And, as for all Big Ideas, there's even a sizable naysayer- and &lt;a href="http://doodleplex.com/glassmaze/http:/doodleplex.com/glassmaze/index.php/programming-in-english-is-a-bad-idea"&gt;backlash- community&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.coghead.com/"&gt;Coghead&lt;/a&gt; is building tools to do this kind of thing for Web applications -- to liberate the world from programmers (I, as a programmer, am chomping at the bit to automate myself into irrelevance: I mean that completely sincerely) or to make us all into programmers, depending on your point of view. I saw a firm at Web 2.0 last week (apologies, their name escapes me) that was promoting English as a scripting language.&lt;br /&gt;&lt;br /&gt;To be honest, I'm really not sure programming languages can get much simpler. I am very, very happy with the Ruby syntax. I think Ruby -- as a syntax -- is a thing of succinct, eloquent genius. So I don't think the next big gain in either developer productivity or the democratization of programming comes from improving on that syntax. I think it's gone about as far as it can go. The returns are diminishing.&lt;br /&gt;&lt;br /&gt;So what if we changed tack? What if we tried something other than simplying programming languages? What if we took Coghead's approach toward all of our programming? I know what you're thinking to yourself: groan, not the dumb RAD (Rapid Applications Development) tools that were so big in the 80s and early 90s, those clunky sets of wizards never amounted to much actual productivity-gain. No, RAD wasn't so rad, because it was simply another interface to the familiar, forever-inaccessible machine code. What I'm wondering about rather is this: What if an entire OS were built in this Coghead-style from the ground up?&lt;br /&gt;&lt;br /&gt;What if I could create my own custom view in Outlook? In Photoshop? What if I didn't need to go spelunking in a 6,000 page Developer's Guide? What if I didn't need to pay a year's worth of college tuition for an SDK to do that?&lt;br /&gt;&lt;br /&gt;That is, what if applications no longer had despotic control over their own frames? What if I could create a view in any application on my desktop? The OS allowed it, made provisions for it, so no application could fail to support it. And what if I could do this visually? And what if I could tell the OS that what I wanted was a list, and then I could tell the OS what I wanted it to be a list of? What if the entire OS took the creation of this kind of abstraction as one of its primary responsibilities?&lt;br /&gt;&lt;br /&gt;So why hasn't this happened already?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Problem: Declarative Programming and the Backwardness of Software Development&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;Try teaching someone to program for the very first time. What's the first conceptual stumbling block? What I've found is that it takes people a while to come to terms with the idea that they can't just tell the computer what to do, what they want, what their intention is, they actually have to tell the computer how to do it.&lt;br /&gt;&lt;br /&gt;I firmly believe that a smart application could talk a person through about 80% of what programmers commonly do, since so much of what programmers do day-to-day is repetitive and near-automatable with a piece of software pitched at the right level of abstraction. Think about it this way: most all of us still program procedurally. But what we are doing is in essence something declarative. We tell our computers how to do things step-by-step, not what we want done.&lt;br /&gt;&lt;br /&gt;After all, the history of programming is the history of increasing abstraction. Standard libraries increase abstraction. Third-party libraries increase abstraction. Good application design involves creating your own reusable abstractions. And these abstractions are declarative in nature: we tell our processor that we want it to multiply two floats. We do not tell it how to encode the floats. We simply need to rise to the level declarative abstraction that non-practitioners are comfortable with.&lt;br /&gt;&lt;br /&gt;But most programmers still, for the most part, program at the wrong level of generalization. Creating new algorithms is a very small subset of the day-to-day tasks of most of us. You find yourself most often using other people's algorithms, applying design patterns, and following common business processes -- procedurally doing what ought to be done declaratively.&lt;br /&gt;&lt;br /&gt;Rails -- considered as a DSL for web applications -- actually goes a long way towards making Web application programming declarative. Even Java's newfangled annotations are moving in that direction. Those old RAD tools back in the day were basically just visual interfaces to declarative programming done cheaply by code generation.&lt;br /&gt;&lt;br /&gt;There are of course the renowned plug-in architectures of Firefox and Eclipse. But those bad boys require some serious code-fu, and while they might liberate their respective platforms, they don't do anything to lower the bar on what it takes to be able to create your own software. If anything, they raise that bar. There's a long long road between Java 101 and OSGi development.&lt;br /&gt;&lt;br /&gt;What has limited the power of these kinds of tools in the past is this: it's just been too hard to get all your applications to play ball together. There's just not much out there that I could tie my little visually declared list to. Web 2.0 is making interoperability compulsory, but only an operating system could make it a true precondition of software development. Lots of OSes have component models, but applications tend to support components as an afterthought. What if they simply had to develop for them or else they would have no persistent storage?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Application Rights versus User Rights&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;So I think there are other kinds of orthogonal concerns whose development would really make a proposal like this fly. Consider, for example, the broad issue of application rights versus user rights. Traditionally, applications have had rights to their territorial integrity (their frame). They have rights to their source code, if they want it (pretty hard to disassemble most stuff). And they have rights to keep your data however they want. What if we revoked those rights? What if we revoked the right to the user's data? That is, what if an OS were designed to prevent applications from serializing data unless it were serialized to an open specification (a specification it would have to provide to the OS)? What if we revoked the right to the source code? What if a popular OS took hold in which everything were scripted and nothing could be compiled down? Sure, companies might shy away from it, but if the platform were popular enough, they would simply have no choice but to develop for it. There's much less to fear from openness if everyone &lt;strong&gt;must&lt;/strong&gt; be open, because if you're looking for intellectual property infringement, &lt;em&gt;no one can hide infringement from you&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;I'm not saying that all these ideas are feasible, but I hope they are worth thinking about. It's hard to imagine a speedy OS that didn't allow programmers to compile things down to machine code for some optimizations. On the other hand, as processing power continues to grow, we might see these kinds of optimizations less and less often over the next couple of years.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-962238028878539943?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/962238028878539943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=962238028878539943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/962238028878539943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/962238028878539943'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/04/coghead-revisited-new-kind-of-os.html' title='Coghead Revisited -- A New Kind of OS?'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-1990804036895856553</id><published>2007-04-25T12:43:00.000-07:00</published><updated>2007-04-25T13:10:07.666-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='html'/><title type='text'>HTML 5 and Drag and Drop</title><content type='html'>Here's a &lt;a href="http://www.devx.com/webdev/Article/34389"&gt;good overview&lt;/a&gt; of the newly unveiled &lt;a href="http://www.whatwg.org/specs/web-apps/current-work/"&gt;HTML 5&lt;/a&gt; specification that's just out.&lt;br /&gt;&lt;br /&gt;And I think they're missing something crucial.&lt;br /&gt;&lt;br /&gt;Ray Ozzie has done some great work making what amounts to a &lt;a href="http://rayozzie.spaces.live.com/blog/cns%21FB3017FBB9B2E142%21285.entry"&gt;clipboard hack&lt;/a&gt; for the Web. He is quite right: the Web needs a clipboard, particularly as the Web becomes an application platform. Ozzie's work is slick, elegant, and very useful.&lt;br /&gt;&lt;br /&gt;But it's also too darned &lt;a href="http://rayozzie.spaces.live.com/editorial/rayozzie/demo/liveclip/liveclipsample/techPreview.html"&gt;complicated&lt;/a&gt;, and that is no knock on Ray Ozzie. It took a lot of ingenuity to get to this point with the limited resources of HTML 4.&lt;br /&gt;&lt;br /&gt;Really, drag and drop should be a first-class citizen of HTML. Why not? &lt;span style="font-style: italic;"&gt;Forms&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;buttons&lt;/span&gt; are, and dragging and dropping is as important a GUI concept as forms and buttons. Support baked straight into HTML would make it simple on developers: your browser implements it once, and the rest of us down the Web food-chain never have to worry about it any more than we worry about our &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; tags.&lt;br /&gt;&lt;br /&gt;How simple can it be? Very simple, I think. All we really need is a &lt;code&gt;&amp;lt;drag&amp;gt;&lt;/code&gt; tag and a &lt;code&gt;&amp;lt;drop&amp;gt;&lt;/code&gt; tag. Each &lt;code&gt;&amp;lt;drag&amp;gt;&lt;/code&gt; tag attribute can specify which mime formats it will export to (i.e. application/pdf, text/plain) and a callback function for fetching the data each format. A &lt;code&gt;&amp;lt;drop&amp;gt;&lt;/code&gt; tag event handler can choose an available format when a drop is made and update its appearance.&lt;br /&gt;&lt;br /&gt;And the Web will have, not only a clipboard, but also a desktop.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-1990804036895856553?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/1990804036895856553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=1990804036895856553' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/1990804036895856553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/1990804036895856553'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/04/html-5-and-drag-and-drop.html' title='HTML 5 and Drag and Drop'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-7351621346619721559</id><published>2007-04-20T10:20:00.000-07:00</published><updated>2007-04-20T11:18:09.872-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>In Ruby, Not All Objects Are Created Equally</title><content type='html'>Try this:&lt;br /&gt;&lt;pre&gt;irb(main):001:0&gt; class &lt;&lt; :a&lt;br /&gt;irb(main):002:1&gt; def foo; "bar"; end&lt;br /&gt;irb(main):003:1&gt; end&lt;br /&gt;TypeError: no virtual class for Symbol&lt;br /&gt;      from (irb):1&lt;br /&gt;&lt;/pre&gt;But.. but.. but.. I thought adding instance-specific methods was a hallmark of Ruby metaprogramming?&lt;br /&gt;&lt;br /&gt;I ran into this problem while trying to create "smart" symbols, symbols that I could hang methods off of to, say, change their textual representation when displayed to the user.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What other objects lack virtual classes?&lt;/span&gt; Well, &lt;code&gt;String&lt;/code&gt; and &lt;code&gt;Fixnum&lt;/code&gt; for two. I'm guessing that this is true of any objects that are accessible as literals.&lt;br /&gt;&lt;br /&gt;At first, you might think this is disappointing, an imperfection in the otherwise glittering consistency of Ruby. But consider the alternative.&lt;br /&gt;&lt;br /&gt;For one, Ruby would have to keep an object in memory representing the number 7 -- a virtual class just for every token of 7.  It would have to create such an object when you tried to access its virtual class. If you had &lt;code&gt;def voyages_of_sinbad; 4 + 3; end&lt;/code&gt;, that would have to return not just the result of computation, but then &lt;span style="font-style: italic;"&gt;look up&lt;/span&gt; the possible virtual class. Whether or not a virtual class for 7 had been created, it would have to at least check. So this look up would be a requirement of &lt;span style="font-style: italic;"&gt;any&lt;/span&gt; numerical computation.&lt;br /&gt;&lt;br /&gt;For another, what distinguishes literals is that they can be accessed directly without clients being passed a reference. In essence, literals are the  objects we all share. Literals, as true first-class objects, pulverize encapsulation! (And I ask you to imagine for the moment a &lt;a href="http://mindprod.com/jgloss/unmaindesign.html"&gt;insano-pattern&lt;/a&gt; of using Fixnums like &lt;code&gt;7.secret_info&lt;/code&gt; to pass messages between objects!)&lt;br /&gt;&lt;br /&gt;So be thankful that not all objects are created equally in the Ruby world.&lt;br /&gt;&lt;br /&gt;It would be an interesting thought experiment to try to imagine a sensible language without literals.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-7351621346619721559?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/7351621346619721559/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=7351621346619721559' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/7351621346619721559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/7351621346619721559'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/04/in-ruby-not-all-objects-are-created.html' title='In Ruby, Not All Objects Are Created Equally'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-3876603161393502121</id><published>2007-04-15T12:55:00.000-07:00</published><updated>2007-04-15T15:05:29.889-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>Reporting on Rails</title><content type='html'>Another (far more famous) &lt;a href="http://codeforpeople.com/teaching.html"&gt;Ara&lt;/a&gt; has written a fantastic, much-needed plug-in for Rails called &lt;a href="http://liquidrail.com/2007/4/8/mole-plugin-inspect-the-rails/"&gt;MOle&lt;/a&gt;. MOle lets you gather reporting information on your Rails application in real-time. Reporting is really a cross-cutting concern, common to many applications. It's great to see tools becoming available for Rails in this direction. Coincidentally, we've been rolling our own framework at &lt;a href="http://www.postful.com"&gt;Postful&lt;/a&gt; for doing this sort of thing. What did we call it? &lt;i&gt;Snitch&lt;/i&gt;. I'm not kidding. And Snitch is the name of the console application for MOle. We were planning to release our Snitch as a plug-in, but now seeing the fantastic work done on MOle, it makes more sense for us to contribute rather than compete.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;What are the advantages of MOle over externalizing your reporting with something like, say, Google Analytics?&lt;/b&gt; This is only going to be a fragment of the true list of advantages, since I've just begun dipping into the code, but at first glance what is obvious is this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Gauging application performance by wrapping controllers&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Capturing application-specific business data&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Monitoring this data in real-time, rather than the typical reporting lag of external analytics tools&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Monitoring particular code paths, like exceptions thrown, rather than just raw request headers &lt;/li&gt;&lt;/ul&gt;By itself, these things make MOle a necessary complement to externalized analytics packages I'm excited to see where development is going to take this project.&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-3876603161393502121?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/3876603161393502121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=3876603161393502121' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/3876603161393502121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/3876603161393502121'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/04/reporting-on-rails.html' title='Reporting on Rails'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-7448759000740423432</id><published>2007-04-14T12:28:00.000-07:00</published><updated>2007-04-20T11:16:01.346-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><title type='text'>How to Make Your ActionController Go Up In A Bang</title><content type='html'>&lt;p&gt;Go on, try it. I dare you. I double-dare you:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;class UserController &lt; ActionController::Base  &lt;br /&gt;  def send&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def request&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def render&lt;br /&gt;  end&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;These are all natural enough names for controller methods, but your controller will mysteriously vanish, cease to operate in strange, strange ways if you use any of them.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;Why?&lt;/b&gt; Because you are overriding methods crucial to the internals of the controller. In the first method, Ruby's Object#send. In the next two, ActionController methods.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;b&gt;How to save yourself time:&lt;/b&gt; I really hate silent failure or mysterious failure. But you can make the silent failures clear and noisy (oxymoronic, I know!). Try something like this:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;module ActionController&lt;br /&gt;  class Base&lt;br /&gt;    def Base.method_added(sub)&lt;br /&gt;      raise "Cannot override action 'send'"     if sub == :send &lt;br /&gt;      raise "Cannot override action 'request'"  if sub == :request&lt;br /&gt;      raise "Cannot override action 'response'" if sub == :response&lt;br /&gt;      raise "Cannot override action 'render'"   if sub == :render&lt;br /&gt;      #...&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-7448759000740423432?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/7448759000740423432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=7448759000740423432' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/7448759000740423432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/7448759000740423432'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/04/how-to-make-your-actioncontroller-go-up.html' title='How to Make Your ActionController Go Up In A Bang'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-3748866113366144922</id><published>2007-04-12T01:42:00.000-07:00</published><updated>2007-04-13T19:26:55.192-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Ruby Scoping Shocker</title><content type='html'>&lt;p&gt;Ruby head-scratching magic:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;irb(main):001:0&gt; if false&lt;br /&gt;irb(main):002:1&gt; x = true&lt;br /&gt;irb(main):003:1&gt; end&lt;br /&gt;=&gt; nil&lt;br /&gt;irb(main):004:0&gt; x&lt;br /&gt;=&gt; nil&lt;br /&gt;&lt;/pre&gt;But now:&lt;br /&gt;&lt;pre&gt;irb(main):005:0&gt; y&lt;br /&gt;NameError: undefined local variable or method `y' for main:Object&lt;br /&gt;        from (irb):5&lt;br /&gt;irb(main):006:0&gt;&lt;/pre&gt;&lt;p&gt;This here is very unusual, and I'm not sure if it is part of the Ruby specification or just the implementation. From what I gather, the declaration of 'x' is a side effect of the &lt;span style="font-style:italic;"&gt;parsing&lt;/span&gt; of the conditional block. What other side effects to unexecuted code are there that we should know about?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The oddity does not carry over to the right side of assignment:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;irb(main):001:0&gt; if false&lt;br /&gt;irb(main):002:1&gt; x = y&lt;br /&gt;irb(main):003:1&gt; end&lt;br /&gt;=&gt; nil&lt;br /&gt;irb(main):004:0&gt; x&lt;br /&gt;=&gt; nil&lt;br /&gt;irb(main):005:0&gt; y&lt;br /&gt;NameError: undefined local variable or method `y' for main:Object&lt;br /&gt;        from (irb):5&lt;br /&gt;irb(main):006:0&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-weight:bold;"&gt;Why is the specification/implementation question important?&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Because if we could rely on this behavior we could write more compact code, writing fewer variable declarations. For example:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;if some_condition&lt;br /&gt;  x = true&lt;br /&gt;end&lt;br /&gt;#..&lt;br /&gt;do_something if x&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;rather than:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;x = nil&lt;br /&gt;if some_condition&lt;br /&gt;  x = true&lt;br /&gt;end&lt;br /&gt;#..&lt;br /&gt;do_something if x&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;if we can count on this in future and all implementations of Ruby.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-3748866113366144922?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/3748866113366144922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=3748866113366144922' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/3748866113366144922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/3748866113366144922'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/04/ruby-scoping-shocker.html' title='Ruby Scoping Shocker'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6845919040715696857.post-8334892817549059051</id><published>2007-04-04T14:30:00.000-07:00</published><updated>2007-04-12T02:07:11.974-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Why I Hate Test Fixtures (And What I Am Prepared To Do About It)</title><content type='html'>I have a few complaints against YAML test fixtures:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;They break. Changing your database schema will often leave existing test fixtures invalid. I am extremely lazy, and it becomes a maintenance burden.&lt;/li&gt;&lt;li&gt;I hate switching between files in my editor. Already, I have to switch between my application code and my test code. Switching to a test fixture for something as small as a sample object gives me three files I have to switch between.&lt;/li&gt;&lt;li&gt;The test fixtures centralize concerns from all different test suites. For example, I have several users in my test fixture who are used I-don't-even-know-where among my test classes. It seems bizarre to think that while my tests should remain independent and modular, my test data should be entirely jumbled together.&lt;/li&gt;&lt;li&gt;I can't remember what is what within my test fixtures. I had users named to Bill, Peggy, Joe, Quentin. Who are these people? I switched to the slightly more manageable valid_user, invalid_user, valid_user_sending_message_to_invalid_user, invalid_user_receiving_message_to_valid_user. Even if I try to reuse the same fixture objects as often as possible, bloat eventually happens.&lt;/li&gt;&lt;li&gt;If objects have dependencies, they get tedious. Let us say your objects have dependencies on other objects. Your order requires a user to be valid. Your user requires an account. If I now have to make dummy fixtures for all these, I've got to switch between five or six files now.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;In fairness, I have these positive things to say about externalized test fixtures:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Sometimes they really need to be externalized, as in when your test fixtures are entire documents, like PDFs or spreadsheets.&lt;/li&gt;&lt;li&gt;The YAML fixtures are a vast, vast improvement over using property files, XML, or writing a lot of object instantiation code within your test itself (all of which I used to do back in Java).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;So what do I want instead? I want to create my fixtures within my tests in no more than a line or two with valid defaults:&lt;br /&gt;&lt;pre&gt;def test_signup&lt;br /&gt;  user =  User.sample&lt;br /&gt;  post :signup, { :user =&gt; user.attributes}&lt;br /&gt;  assert_equal 1, User.count&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;I want to create required dependencies automatically:&lt;br /&gt;&lt;pre&gt;def test_signup_creates_account   &lt;br /&gt;  user =  User.sample&lt;br /&gt;  post :signup, { :user =&gt; user.attributes}&lt;br /&gt;  assert_equal 1, Account.count&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;I want attributes to be overridable:&lt;br /&gt;&lt;pre&gt;def test_signup_requires_email&lt;br /&gt;  user =  User.sample(:email =&gt; nil)&lt;br /&gt;  post :signup, { :user =&gt; user.attributes}&lt;br /&gt;  assert_equal 0, User.count&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;I want even nested attributes to be overridable:&lt;br /&gt;&lt;pre&gt;def test_signup_creates_account   &lt;br /&gt;  user =  User.sample(:account =&gt; { :balance =&gt; 5.0 })&lt;br /&gt;  post :signup, { :user =&gt; user.attributes}&lt;br /&gt;  assert_equal 5.0,  Account.find(1).balance&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;And I want to make minimal changes (none if possible) to my model classes to support this stuff.&lt;br /&gt;&lt;br /&gt;Please take note that this kind a testing design pattern has cropped up both in &lt;a href="http://weblog.jamisbuck.org/2006/3/9/integration-testing-in-rails-1-1"&gt;integration testing&lt;/a&gt; and in &lt;a href="http://www.lukeredpath.co.uk/2006/8/29/developing-a-rails-model-using-bdd-and-rspec-part-1"&gt;RSpec&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;ActiveRecord classes can introspect their associations and, with a plug-in, their validation. For 90% of cases, this should be all we need to create the object graph.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6845919040715696857-8334892817549059051?l=rubyssimo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rubyssimo.blogspot.com/feeds/8334892817549059051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6845919040715696857&amp;postID=8334892817549059051' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/8334892817549059051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6845919040715696857/posts/default/8334892817549059051'/><link rel='alternate' type='text/html' href='http://rubyssimo.blogspot.com/2007/04/ddd.html' title='Why I Hate Test Fixtures (And What I Am Prepared To Do About It)'/><author><name>Ara Vartanian</name><uri>http://www.blogger.com/profile/12592706325147338463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://farm1.static.flickr.com/200/446515860_5f3531d5f6.jpg?v=0'/></author><thr:total>0</thr:total></entry></feed>
