<?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/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DEIFSHo9fCp7ImA9WhRVFEs.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435</id><updated>2012-01-14T01:55:19.464+11:00</updated><category term="Personal" /><category term="mobile" /><category term="logging" /><category term="ncover" /><category term="pc" /><category term="refactorasp" /><category term="web" /><category term="books" /><category term="localization" /><category term="Misc" /><category term="esent" /><category term="selenium" /><category term="scaling" /><category term="nunit" /><category term="upgrade" /><category term="validation" /><category term="presentation" /><category term="firefox" /><category term="Australia" /><category term="thoughworks" /><category term="smile" /><category term="css" /><category term="git" /><category term="mocking" /><category term="nginx" /><category term="rails" /><category term=".net" /><category term="fxcop" /><category term="frustration" /><category term="MyGeneration" /><category term="vim" /><category term="ms-access" /><category term="asp.net mvc" /><category term="resharper" /><category term="business" /><category term="java" /><category term="security" /><category term="mstest" /><category term="jasmine" /><category term="coderush" /><category term="webforms" /><category term="ideas" /><category term="Development" /><category term="rspec" /><category term="rhino-unit" /><category term="practices" /><category term="html" /><category term="mac" /><category term="marketing" /><category term="asp.net" /><category term="waterfall" /><category term="testing" /><category term="architecture" /><category term="coffeescript" /><category term="nice" /><category term="castle-monorail" /><category term="elmah" /><category term="eco" /><category term="svn" /><category term="ruby" /><category term="challenge" /><category term="wiki" /><category term="podcast" /><category term="skills" /><category term="javascript" /><category term="visual-studio" /><category term="view-engine" /><category term="js-unit" /><category term="social" /><category term="holydays" /><category term="honesty" /><category term="DevTools" /><category term="it" /><category term="ibm" /><category term="agile" /><category term="model-binder" /><category term="survey" /><category term="screencasts" /><category term="cms" /><category term="licensing" /><category term="Software" /><category term="windows" /><category term="tdd" /><category term="productivity" /><category term="ivona" /><category term="database" /><category term="ndepend" /><category term="linux" /><category term="nhaml" /><category term="tricks" /><category term="cvs" /><category term="sass" /><category term="patterns" /><category term="vici-mvc" /><category term="borland" /><category term="games" /><category term="award" /><category term="ie" /><category term="ruby-on-rails" /><category term="image-processing" /><category term="terminal" /><category term="expression-web" /><category term="sql" /><category term="unix" /><category term="ext-js" /><category term="razor" /><category term="standards" /><category term="remember" /><title>Art of Programming</title><subtitle type="html">Can Technical Excellence be a Reality?
(Dmytrii Nagirniak ~ Dmitriy Nagirnyak)</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.approache.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.approache.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>168</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/DmitriyNagirnyak" /><feedburner:info uri="dmitriynagirnyak" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DkUFSXcyeSp7ImA9WhRXFUQ.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-1179714613254103096</id><published>2011-12-22T20:31:00.002+11:00</published><updated>2011-12-23T09:50:18.991+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-23T09:50:18.991+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="Development" /><category scheme="http://www.blogger.com/atom/ns#" term="coffeescript" /><category scheme="http://www.blogger.com/atom/ns#" term="DevTools" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="html" /><title>KnockoutJS Validations Screencast</title><content type="html">&lt;div&gt;
If you wonder how you can use KnockoutJS with Rails in a similar way to Backbone.js or Spine.js then &lt;a href="http://www.youtube.com/watch?v=cJzQl-bpmUI"&gt;watch the video&lt;/a&gt;. It also shows how easy it is to apply client side validations that work alongsite with the server-side validations.&lt;br /&gt;
&lt;br /&gt;

&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/cJzQl-bpmUI?hd=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;div&gt;
Have a look at the &lt;a href="https://github.com/dnagir/knockout-rails"&gt;knockout-rails&lt;/a&gt; project for more details.
&lt;/div&gt;

&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-1179714613254103096?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/vjx4oPVQgqY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/1179714613254103096/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/12/knockoutjs-validations-video.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/1179714613254103096?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/1179714613254103096?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/vjx4oPVQgqY/knockoutjs-validations-video.html" title="KnockoutJS Validations Screencast" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/cJzQl-bpmUI/default.jpg" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://blog.approache.com/2011/12/knockoutjs-validations-video.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYASH04fip7ImA9WhRRFU4.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-4808080793396208656</id><published>2011-11-29T11:51:00.001+11:00</published><updated>2011-11-29T13:19:09.336+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-29T13:19:09.336+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="Development" /><category scheme="http://www.blogger.com/atom/ns#" term="DevTools" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><title>Issues switching to JRuby from MRI 1.9</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;b&gt;UDPATE&lt;/b&gt;: The reason for switching to JRuby the native neo4j API. Have to use REST API with MRI.&lt;br /&gt;
&lt;br /&gt;
This is just a quick recap of what issues I have had trying to switch existing app from MRI Ruby (1.9.3) to JRuby (1.6.4).&lt;br /&gt;
&lt;br /&gt;
Unfortunately I stepped back and didn't want to spend more time as it felt an unbreakable chain of issues. Resolving one, you think "huh, awesome". But very soon you hit the next.&lt;br /&gt;
And I couldn't see it stopping.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;But PLEASE bear in mind&lt;/b&gt; that I only spent a couple of hours on that. With a little bit more persistence, you may be able to the end of the tunnel.&lt;br /&gt;
&lt;br /&gt;
The overall impression is that it is not a big deal really. The problems arise when trying to use other libraries. And unfortunately, not all of the gems &lt;b&gt;care deep enough to support JRuby&lt;/b&gt;. And this is the biggest issue in my opinion, there are very little issues with JRuby itself. The transition (from the syntax perspective) was extremely easy.&lt;br /&gt;
&lt;br /&gt;
The application is pretty standard Rails 3.1 app that uses gems like Dragonfly, inherited_resources, cancan, paper_trail, Authlogic, CoffeeScript, Haml, Sass, Formtastic etc. For testing - things like rspec-rails, cucumber-rails, capybara-webkit, guard (rspec and cucumber), database_cleaner etc.&lt;br /&gt;
&lt;br /&gt;
So here is a quick list of the things that I faced on my way.&lt;br /&gt;
&lt;br /&gt;
Before everything else I enabled support for 1.9 syntax in JRuby (export JRUBY_OPTS=--1.9).&lt;br /&gt;
&lt;br /&gt;
It all first started with &lt;a href="https://gist.github.com/1402753"&gt;the weird issue&lt;/a&gt; where the &lt;b&gt;wrong arguments were passed to RSpec shared example&lt;/b&gt;.&lt;br /&gt;
Unfortunately I did not figure out why it happened and just patched it as you can see in the comments there.&lt;br /&gt;
&lt;script src="https://gist.github.com/1402753.js?file=sample_spec.rb"&gt;
&lt;/script&gt;

&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After fixing this issue I had another one related to &lt;b&gt;database_cleaner&lt;/b&gt;. So I ended up with a &lt;a href="https://github.com/bmabey/database_cleaner/pull/83"&gt;pull request&lt;/a&gt; that worked for me.&lt;br /&gt;
&lt;br /&gt;
The other issue was a&lt;b&gt; huge stack trace&lt;/b&gt;. I scrolled 3 pages in the terminal to get to the top. Most of that stack trace is deep inside Java. Additionally I got &lt;b&gt;wrong line number&lt;/b&gt; on exception. This "features/step_definitions/company_steps.rb:234" makes me thing that the exception is at line 234. But that file only had 49 lines of code. Now, go figure.&lt;br /&gt;
&lt;br /&gt;
Going on... &lt;a href="https://github.com/colszowka/simplecov"&gt;SimpleCov&lt;/a&gt; gem didn't work out of the box and gave the warning that I need to enable debugging. That's fine and understandable. But after half an hour of debugging of unrelated exception, it turned out that &lt;b&gt;SimpleCove threw an exception&lt;/b&gt; because of that. So had to go and explicitly disable it.&lt;br /&gt;
&lt;br /&gt;
Then I managed to run all of my specs. But I was pretty surprised how &lt;b&gt;slow&lt;/b&gt; it was:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
# rvm use 1.9.3
# time rspec # real=14s, rspec time ~ 12s

# rvm use jruby
# time rspec # real=52s, rspec time ~ 30s

&lt;/code&gt;
&lt;/pre&gt;
But this is expected as JRuby doesn't have enough time to optimise here. It should be much better in production. But it will be also shit slow after deployment.&lt;br /&gt;
Ok. That's fine. &lt;b&gt;I can trust it's fast&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Then I tried running the cucumber specs and had to file the &lt;a href="http://jira.codehaus.org/browse/JRUBY-6237"&gt;issue&lt;/a&gt; to support &lt;b&gt;new Ruby 1.9.3 syntax&lt;/b&gt; (a = b = f 1). Not a big deal, easily fixed with parens: a = b = f(1).&lt;br /&gt;
&lt;br /&gt;
Next and the &lt;b&gt;final issue&lt;/b&gt; - I could not run the &lt;b&gt;headless cucumber specs&lt;/b&gt; (capybara-webkit). It just got stuck (no CPU used) and feels like there is a &lt;b&gt;dead-lock&lt;/b&gt; or something similar.&lt;br /&gt;
&lt;br /&gt;
I couldn't see way of fixing it easily and decided that for now I am &lt;b&gt;done with&lt;/b&gt; it. So going &lt;b&gt;back to Ruby 1.9.3&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;To summarise&lt;/b&gt;, I &lt;b&gt;did not feel like it's a problem&lt;/b&gt; to switch to JRuby. But it's really a &lt;b&gt;big deal to actually use&lt;/b&gt; it due to the number of &lt;b&gt;C extensions&lt;/b&gt; that JRuby doesn't really support.&lt;br /&gt;
&lt;br /&gt;
Again, to emphasise, there is nothing horribly wrong with JRuby and it seems to be pretty good. But the real showstoppers are the C extensions.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-4808080793396208656?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/gHlJAnAwSzw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/4808080793396208656/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/11/issues-switching-to-jruby-from-mri-19.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/4808080793396208656?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/4808080793396208656?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/gHlJAnAwSzw/issues-switching-to-jruby-from-mri-19.html" title="Issues switching to JRuby from MRI 1.9" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.approache.com/2011/11/issues-switching-to-jruby-from-mri-19.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04HQn07fSp7ImA9WhRRF0U.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-189850392774184506</id><published>2011-11-19T20:47:00.000+11:00</published><updated>2011-12-02T11:32:13.305+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-02T11:32:13.305+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="coffeescript" /><category scheme="http://www.blogger.com/atom/ns#" term="vim" /><category scheme="http://www.blogger.com/atom/ns#" term="git" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="tdd" /><category scheme="http://www.blogger.com/atom/ns#" term="screencasts" /><category scheme="http://www.blogger.com/atom/ns#" term="sass" /><category scheme="http://www.blogger.com/atom/ns#" term="jasmine" /><title>Rails Plugin with Tested Assets Screencast</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
Some of the most valuable things you can learn are not written in books, not shown in the presentations and demos. Those come from seeing how &lt;i&gt;others&lt;/i&gt; work.&lt;br /&gt;
&lt;br /&gt;
How do they do all those small things? What tricks do they have? How would they approach that problem?&lt;br /&gt;
&lt;br /&gt;
Unfortunately, I can't remember seeing people sharing the way they actually work (unless they pair). I want to see what mistakes they make, how they fix those, how they try to come up with a word erasing a line 10 times.&lt;br /&gt;
I believe all this is of a great value for a lot of us.&lt;br /&gt;
&lt;br /&gt;
What I described is &lt;i&gt;partially&lt;/i&gt;&amp;nbsp;done by PeepCode's Play By Play series and Tekpub. Those are amazing (usually). But that's not exactly what I am after. Those screencasts are high quality, polished and prepared ones. YOU are NOT featuring there. I want to see YOU there. All of you, guys.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So I decided to make a first step (or maybe not so) and screencast myself while working on a Rails Plugin.&lt;br /&gt;
&lt;br /&gt;
This is mostly real-time work. You'll see how I fail, you'll spot the mistakes I've done and did not even notice, you'll see how I write README. And, most importantly, you will hopefully see some of the things that will help &lt;i&gt;yourself&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
This video features the following tools/technologies:&lt;br /&gt;
&lt;br /&gt;
&lt;ul style="text-align: left;"&gt;
&lt;li&gt;Ruby, Ruby On Rails&lt;/li&gt;
&lt;li&gt;CoffeeScript&lt;/li&gt;
&lt;li&gt;SASS&lt;/li&gt;
&lt;li&gt;Git, Github&lt;/li&gt;
&lt;li&gt;Vim (MacVim and Terminal)&lt;/li&gt;
&lt;li&gt;Jasmine and basic testing of JavaScript and even CSS assets&lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Additionally, before watching, make sure you Turn On the Volume. Rare person doesn't like the music that my wife helped me prepare. Even if you don't not like the video, you should like the music :)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I hope you enjoy it. &lt;strong&gt;UPDATE: Please watch it in full screen as the quality is lower than I expected.&lt;/strong&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;

&lt;iframe width="560" height="315" src="http://www.youtube.com/embed/MWvLofLz04k?hd=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;


&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
P.S.: Screencasting is really hard. And that's my first. So&amp;nbsp;apologies&amp;nbsp;if something isn't in-place.&lt;/div&gt;
&lt;div&gt;
(If you can't see the video here, open it on&amp;nbsp;&lt;a href="http://vimeo.com/32357445"&gt;Vimeo&lt;/a&gt;. Alternatively, try &lt;a href="http://www.youtube.com/watch?v=MWvLofLz04k"&gt;YouTube&lt;/a&gt; - it should work with HTML5-only browser).&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-189850392774184506?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/i4VT-nf1Mt0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/189850392774184506/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/11/rails-plugin-with-tested-assets.html#comment-form" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/189850392774184506?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/189850392774184506?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/i4VT-nf1Mt0/rails-plugin-with-tested-assets.html" title="Rails Plugin with Tested Assets Screencast" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/MWvLofLz04k/default.jpg" height="72" width="72" /><thr:total>8</thr:total><feedburner:origLink>http://blog.approache.com/2011/11/rails-plugin-with-tested-assets.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQCRHc8fCp7ImA9WhdUFkQ.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-756166959564621001</id><published>2011-10-04T12:53:00.000+11:00</published><updated>2011-10-04T12:56:05.974+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-04T12:56:05.974+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Development" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="unix" /><category scheme="http://www.blogger.com/atom/ns#" term="mac" /><category scheme="http://www.blogger.com/atom/ns#" term="terminal" /><title>Use your Terminal like a Pro</title><content type="html">&lt;div&gt;
Keep your config in a separate dotfiles directory and under source control with the structure like:&lt;br /&gt;

&lt;pre&gt;&lt;code&gt;
~/dotfiles:
--+ bashrc, bash_profile
--+ ssh/config
--&gt;--bash -&amp;gt; (env, config, aliases). bash has source bach/env, bash/config etc.
&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt;
Then:&lt;br /&gt;
&lt;code&gt;ln -s ~/.bashrc ~/bin/dotfiles&lt;/code&gt;
&lt;br /&gt;
&lt;code&gt;echo ". ~/.bashrc" &gt; ~/.bash_profile&lt;/code&gt;

&lt;br /&gt;
&lt;br /&gt;

Put everything into .bashrc except any long running tasks.&lt;br /&gt;
.bash_profile - for interactive shells. But you can just usually source .bashrc.&lt;br /&gt;

Now some keyboard shortcuts:&lt;br /&gt;
&lt;br /&gt;

&lt;ul&gt;
&lt;li&gt;Cntrl-a - go to the beginning of line&lt;/li&gt;
&lt;li&gt;Cntrl-e - go to the end of line&lt;/li&gt;
&lt;li&gt;Cntrl-k - delete everything to the right&lt;/li&gt;
&lt;li&gt;Cntrl-w - delete previous word&lt;/li&gt;
&lt;li&gt;ESC-&gt;-b - go back one word&lt;/li&gt;
&lt;li&gt;ESC-&gt;-f - go forward one word&lt;/li&gt;
&lt;/ul&gt;

&lt;br /&gt;
If you often connect via SSH like so:
&lt;code&gt;ssh -p 2323 username@my-server.example.com&lt;/code&gt;

Then you can shorten it to &lt;code&gt;ssh my-server&lt;/code&gt; if you will add entry to &lt;code&gt;~/.ssh/config&lt;/code&gt;:
&lt;pre&gt;&lt;code&gt;
Host my-server
    HostName my-server.example.com
    Port 2323
    User username
&lt;/code&gt;&lt;/pre&gt;

Then you can use it as:

&lt;pre&gt;&lt;code&gt;
# Tunnelling
ssh -L7997:127.0.0.1:7979 my-server

# Copy folder to server
scp my_folder my-server:my_other_folder/

# Or even use it with git
git clone my-server:repo-name.git

&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt;&lt;br /&gt;

Now some useful things you can do in the terminal:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;!!&lt;/code&gt; - run previously executed command (you can do `sudo !!` for example)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!$&lt;/code&gt; - last argument of previous command&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!60&lt;/code&gt; - run the command #60. Number comes from &lt;code&gt;history&lt;/code&gt; command&lt;/li&gt;
(for example: run &lt;code&gt;tail file.log&lt;/code&gt; and then &lt;code&gt;cat !$&lt;/code&gt; is same as &lt;code&gt;cat file.log&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!echo&lt;/code&gt; - rerun last command starting with echo&lt;/li&gt;
&lt;li&gt;Ctrl-r - interactive search on history of commands; Use Ctrl-j to abandon.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!?file.log?!&lt;/code&gt; - run the last matching command (not interactive)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^file.log^another-file.log&lt;/code&gt; - run the last matching command replacing file.log with another-file.log&lt;/li&gt;
&lt;li&gt;&lt;code&gt;!?file.log?!&lt;/code&gt; - run the last matching command (not interactive)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mv README.{txt,markdown}&lt;/code&gt; - same as &lt;code&gt;mv README.txt README.markdown&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;br /&gt;&lt;br /&gt;

You will also appreciate power of the shell when using aliases and functions:
&lt;pre&gt;&lt;code&gt;
alias ss=&amp;quot;./script/server&amp;quot;
alias s=&amp;quot;git status&amp;quot;
alias gca=&amp;quot;git commit -am&amp;quot;
alias zipr=&amp;quot;zip -r&amp;quot;

function take {
  mkdir $1
  cd $1
}
# take create-and-go-here

function gg() {
  git commit -v -a -m &amp;quot;$*&amp;quot;
}
# gg Commit message with no quotes
&lt;/code&gt;&lt;/pre&gt;

&lt;br /&gt; &lt;br /&gt;
But when functions get more complicated, you might want to use a scripting language (Ruby, Python etc).

&lt;br /&gt;
Put those scripts into your ~/bin directory and add it to your PATH variable.

&lt;br /&gt;&lt;br /&gt;
There are also number of Mac specific tricks.
&lt;br /&gt;
One is is &lt;code&gt;open anything&lt;/code&gt; command that will open the file/directory in the default application.
&lt;br /&gt;
You can also force it to use a specific app:
&lt;code&gt;open -a /Applications/Firefox.app index.html&lt;/code&gt;.
&lt;br /&gt;
This one becomes a good candiate for an alias.

&lt;br /&gt; &lt;br /&gt;
You can also pipe output of any command into &lt;code&gt;pbcopy&lt;/code&gt; command to copy it to the clipboard.
&lt;br /&gt;
For example:
&lt;code&gt;cat index.html | pbcopy&lt;/code&gt; will copy the content of the file into clipboard.
&lt;br /&gt;&lt;br /&gt;
You can also do it the other way around: &lt;code&gt;pbpaste &amp;gt; index.html&lt;/code&gt; or 
&lt;code&gt;pbpaste | grep "jquery"&lt;/code&gt;.
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;

Another useful thing &lt;a href='http://homepage.mac.com/thomasw/OpenTerminal/'&gt;OpenTerminal&lt;/a&gt; (drag the app to finder toolbar).
It allows you to open terminal with the current directory set to the Finder window.

&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
You can also use the keyboard to open terminal using &lt;a href='http://www.obdev.at/products/launchbar/'&gt;LaunchBar&lt;/a&gt;. It does much more though. It acts like a global terminal for the system.


&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;
You can also try to use &lt;code&gt;zsh&lt;/code&gt; shell. It will work with the existing bash aliases just fine.
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;

Most of the tips here come from the PeepCode's Advanced Command Line screencast.
&lt;br /&gt;

Hope this helps you on your way to becoming a Terminal Guru.

&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-756166959564621001?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/oPdy2aSwTaY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/756166959564621001/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/10/tips-on-usingterminal-in-mac.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/756166959564621001?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/756166959564621001?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/oPdy2aSwTaY/tips-on-usingterminal-in-mac.html" title="Use your Terminal like a Pro" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2011/10/tips-on-usingterminal-in-mac.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YEQngzeSp7ImA9WhdbGUQ.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-3439022726777198381</id><published>2011-08-19T19:26:00.000+10:00</published><updated>2011-10-19T13:25:03.681+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-19T13:25:03.681+11:00</app:edited><title>Templating done easy - JavaScript HAML with Rails</title><content type="html">&lt;h3&gt;
HAML templating with no worries: native, precompiled HAML. Blazing fast and as easy to use as it can be. &lt;/h3&gt;

&lt;h3&gt;
&lt;strong&gt;
&lt;em&gt;UPDATE: this functionality moved into &lt;a href='https://github.com/dnagir/ruby-haml-js'&gt;ruby-haml-js&lt;/a&gt; gem, please use it instead.&lt;/em&gt;
&lt;/strong&gt;
&lt;/h3&gt;

Recently I have been working on a Ruby gem that packs a set of common JavaScript libraries in one place so you can just reference those easily from &lt;b&gt;Rails 3.1&lt;/b&gt; app.  But now I want to write a bit about a very handy tool that the gem includes.  I needed to work on a &lt;a href='http://documentcloud.github.com/backbone'&gt;Backbone&lt;/a&gt; app and, unfortunately, there was no very simple and easy way of using HAML markup for my client side templates. Main problems: &lt;ol&gt;
&lt;li&gt;I don't want to &lt;b&gt;embed&lt;/b&gt; the template into the document.&lt;/li&gt;
&lt;li&gt;The Underscore.js templating is ok, but it is &lt;b&gt;too verbose&lt;/b&gt; for me (as most of others).&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/creationix/haml-js"&gt;haml-js&lt;/a&gt; is great, but I do not want to bother &lt;b&gt;precompiling&lt;/b&gt; the templates.&lt;/li&gt;
&lt;li&gt;I do not want to think about templating as another layer or component. I want it to &lt;b&gt;just work&lt;/b&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;div&gt;
Fortunately it was pretty easy solve these &lt;em&gt;problems&lt;/em&gt; with the &lt;a href="https://github.com/sstephenson/sprockets"&gt;Sprockets&lt;/a&gt; and Rails 3.1.
&lt;/div&gt;

&lt;div&gt;
So from now on you can just write normal HAML templates and consume those with no worries from JavaScript.
&lt;/div&gt;

&lt;div&gt;
All you need to do, is to add &lt;a href="https://github.com/dnagir/pakunok"&gt;pakunok&lt;/a&gt; gem to your Rails 3.1 Gemfile.  This will give you templates as &lt;b&gt;native JavaScript functions&lt;/b&gt; that you can use.
&lt;/div&gt;


&lt;div&gt;
It's better to &lt;a href='https://gist.github.com/1156409'&gt;see than hear&lt;/a&gt;
&lt;/div&gt;

&lt;div&gt;
&lt;script src="https://gist.github.com/1156409.js"&gt;
&lt;/script&gt;
&lt;/div&gt;

&lt;div&gt;
 Feel free to head to the &lt;a href="https://github.com/dnagir/pakunok/issues"&gt;issues&lt;/a&gt; and provide some feedback or &lt;a href="https://github.com/dnagir/pakunok/"&gt;read more&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-3439022726777198381?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/cic0PLRHvIo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/3439022726777198381/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/08/templating-done-easy-javascript-haml.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/3439022726777198381?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/3439022726777198381?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/cic0PLRHvIo/templating-done-easy-javascript-haml.html" title="Templating done easy - JavaScript HAML with Rails" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2011/08/templating-done-easy-javascript-haml.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAERHc4eCp7ImA9WhZWF04.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-2875382844380801266</id><published>2011-05-19T00:58:00.000+10:00</published><updated>2011-05-19T00:58:25.930+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-19T00:58:25.930+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="nginx" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby-on-rails" /><title>Easy Rails deployment with Capistrano and custom Nginx configs</title><content type="html">&lt;p&gt;
In my &lt;a href="http://blog.approache.com/2011/05/setting-up-ubuntu-1104-server-for-rails.html"&gt;previous post&lt;/a&gt; I provided some info about setting up the server for rails app.

&lt;/p&gt;

&lt;p&gt;
Now I am going to describe the Nginx configuration and example of Capistrano deployment file.
&lt;/p&gt;

&lt;p&gt;
One thing that I don't want to do for every new app I deploy is to go to the web server and change the settings (as a root user) so that the web server picks the Rails application.
&lt;/p&gt;

&lt;p&gt;
In order to avoid that I decided to use nginx's &lt;a href="http://wiki.nginx.org/CoreModule#include"&gt;include&lt;/a&gt; command. It allows to add include multiple nginx config files using UNIX wildcards.
&lt;/p&gt;

&lt;p&gt;
So by simply adding this line to the nginx.config I make it possible to configure Nginx from Rails applicatoins themselves:
&lt;code&gt;include /home/*/apps/*/current/nginx.conf;&lt;/code&gt;.

I decided to include all configs within &lt;code&gt;http&lt;/code&gt; tag so that a Rails app can configure multiple servers for itself.
&lt;/p&gt;

&lt;p&gt;
There are obvious drawbacks for this:

&lt;ol&gt;
&lt;li&gt;It is less "safe" as on application might affect others if you will start adding Nginx settings outside of the &lt;code&gt;server&lt;/code&gt; tag. But I am ready to sacrifice this for the sake of having more flexibility by assuming all server citizens are good guys.&lt;/li&gt;
&lt;li&gt;We still need to have root access to restart the Nginx. We shouldn't need to do it often, so that's ok with me.&lt;/li&gt;
&lt;/ol&gt;

Now relying on a very simple conventions, I can configure Nginx from within the app. Just in case you've missed it, the conventions are:

&lt;ol&gt;
&lt;li&gt;To deploy a rails app (and any Rack based app), user should put the app under his home directory in &lt;code&gt;apps/[name]/current&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;To "enable" an app, user should put &lt;code&gt;nginx.conf&lt;/code&gt; file in &lt;code&gt;apps/[name]/current&lt;/code&gt;.&lt;/li&gt;&lt;/ol&gt;

&lt;/p&gt;


&lt;p&gt;
But for now, all this cool structure isn't very helpful unless we deploy the app.
&lt;/p&gt;

&lt;p&gt;
I went with the Ruby de-facto deployment tool - Capistrano. There are enough resources on the net on how to "Capify" your application, so I won't go into details. I assume you have just done &lt;code&gt;capify .&lt;/code&gt; and understand what is going in there.
&lt;/p&gt;

&lt;p&gt;
Briefly, what I need to do is following:

&lt;ol&gt;
&lt;li&gt;Deploy the app explicitly to a particular domain (staging, production, local server etc).&lt;/li&gt;
&lt;li&gt;On every deployment - backup SQLite database (I know, I'll use something better when I'll have 1 million users).&lt;/li&gt;
&lt;li&gt;Prepare Nginx config file for the server (it depends on the domain we deploy at).&lt;/li&gt;
&lt;li&gt;Pre-Compile assets (SCSS in my case).&lt;/li&gt;
&lt;/ol&gt;

&lt;/p&gt;

&lt;p&gt;
So grab &lt;a href="https://gist.github.com/978737"&gt;the gist&lt;/a&gt; (embedded below) with all the details and let me know what can be improved there. The usage is pretty simple: 
&lt;/p&gt;

&lt;p&gt;
&lt;code&gt;cap deploy user=dnagir domain=connecty.approache.com&lt;/code&gt;
&lt;/br /&gt;
You can deploy the same app multiple times to the same server with different subdomains and they will not conflict:
&lt;br /&gt;

&lt;code&gt;cap deploy user=dnagir domain=staging.connecty.approache.com&lt;/code&gt;
&lt;br /&gt;
&lt;code&gt;cap deploy user=dnagir domain=demo.connecty.approache.com&lt;/code&gt;

&lt;/p&gt;

&lt;p&gt;
The most interesting I think is that the &lt;code&gt;nginx.conf&lt;/code&gt; file is created during deployment using default Ruby templating engine and transfered over to the right location on the server. (But still remember root-ed Nginx restart is still required).
&lt;/p&gt;

&lt;p&gt;You can look at the complete source in the &lt;a href="https://github.com/dnagir/connecty/tree/bdd10b8e2bcd946a62cc66075d87ac107e513305"&gt;Connecty project&lt;/a&gt; at Github.
&lt;/p&gt;

&lt;p&gt;Please feel free to tell me what you think about this process.&lt;/p&gt;

&lt;script src="https://gist.github.com/978737.js?file=deploy.rb"&gt;&lt;/script&gt;
&lt;script src="https://gist.github.com/978737.js?file=nginx.production.conf.erb"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-2875382844380801266?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/qU92f4kkiFY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/2875382844380801266/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/05/easy-rails-deployment-with-capistrano.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/2875382844380801266?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/2875382844380801266?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/qU92f4kkiFY/easy-rails-deployment-with-capistrano.html" title="Easy Rails deployment with Capistrano and custom Nginx configs" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.approache.com/2011/05/easy-rails-deployment-with-capistrano.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEACQn84cCp7ImA9WhZbEks.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-2378598853761640921</id><published>2011-05-19T00:09:00.001+10:00</published><updated>2011-06-17T08:19:23.138+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-17T08:19:23.138+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby-on-rails" /><title>Setting up Ubuntu 11.04 server for Rails with RVM</title><content type="html">&lt;p&gt;
I had to set up the server (Ubuntu 11.04) for running couple of Rails apps and thought I could share the notes I've written while doing that. 

Any feedback and improvements are welcome.

&lt;/p&gt;

&lt;p&gt;

&lt;code&gt;
&lt;pre&gt;
apt-get update ; apt-get upgrade

# set timezone
dpkg-reconfigure tzdata


# RVM
bash &lt; &lt;(curl -s https://rvm.beginrescueend.com/install/rvm)

# update /etc/bash.bashrc


# -y to answer YES for questions
aptitude -y install build-essential bison openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev

rvm install 1.9.2; rvm use 1.9.2 --default

# while ruby is being installed prepare nginx
cd /usr/src
wget http://nginx.org/download/nginx-1.0.0.tar.gz
tar -xf nginx-1.0.0.tar.gz
cd nginx-1.0.0

# Use one place for installation
rm -r /opt/ &amp;&amp; ln -fs /usr/local /opt

gem update --system ; gem update
gem install bundler
#install imagemagic
apt-get -y install imagemagick

# proceed with passenger
apt-get -y install libcurl4-openssl-dev
gem install passenger
passenger-install-nginx-module
# additional otions:
# --prefix=/opt/nginx
# --with-http_gzip_static_module --with-http_stub_status_module --with-http_sub_module


# add nginx autostart script: http://wiki.nginx.org/Nginx-init-ubuntu
# verify the correct paths
cd /opt &amp;&amp; \
wget -O init-deb.sh http://library.linode.com/assets/602-init-deb.sh &amp;&amp; \
mv /opt/init-deb.sh /etc/init.d/nginx &amp;&amp; \
chmod +x /etc/init.d/nginx &amp;&amp; \
/usr/sbin/update-rc.d -f nginx defaults


# add to /opt/nginx/conf/nginx.conf
include /home/*/apps/*/current/nginx.conf;
/etc/init.d/nginx restart



# copy ssh keys (from local computer)
cat ~/.ssh/id_rsa.pub | ssh root@my.server.com "mkdir ~/.ssh ; cat - &gt;&gt; ~/.ssh/authorized_keys"

# change default ssh port from 22 to something to get rid of nasty attacks
vim /etc/ssh/sshd_config # change the port number
service ssh reload

#install firewall?? No need for now as only openning 80,443 ports
# apt-get install ufw
&lt;/pre&gt;
&lt;/code&gt;

&lt;/p&gt;

&lt;p&gt;
That should be enough for you to start using the server.
In the &lt;a href="http://blog.approache.com/2011/05/easy-rails-deployment-with-capistrano.html"&gt;future post I plan to describe my setup to make deploying new applications easier&lt;/a&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-2378598853761640921?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/jEI52vfvNuw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/2378598853761640921/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/05/setting-up-ubuntu-1104-server-for-rails.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/2378598853761640921?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/2378598853761640921?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/jEI52vfvNuw/setting-up-ubuntu-1104-server-for-rails.html" title="Setting up Ubuntu 11.04 server for Rails with RVM" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.approache.com/2011/05/setting-up-ubuntu-1104-server-for-rails.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUHQnY5fip7ImA9WhZWF08.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-4894299514644435487</id><published>2011-05-19T00:00:00.000+10:00</published><updated>2011-05-19T00:00:33.826+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-19T00:00:33.826+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby-on-rails" /><title>Unix - do not reinvent the wheel</title><content type="html">&lt;p&gt;
One of the most interesting videos I watched from the &lt;a href="http://video2010.scottishrubyconference.com/"&gt;Scottish RubyConf 2010&lt;/a&gt; is &lt;a href="http://video2010.scottishrubyconference.com/show_video/6/1"&gt;Unix: Rediscovering the wheel&lt;/a&gt;. If you use Ruby/Rails and POSIX systems you gotta know those things.
This is just a quick list of notes to keep it mind. So you will have to Google if something catches your attention.
&lt;/p&gt;

&lt;p&gt;

&lt;code&gt;
&lt;pre&gt;

Scheduling tasks with Cron
==========================
- define all tasks in cron
- don't make Ruby do scheduling


Background processing with ATD daemon
======================================
echo "convert image.jpg image.png" | batch


Logging with syslog
======================================
- don't use rails log

Resource limiting with rlimit
======================================
ulimit -v 102400
ruby -e "' ' * 1024 * 1024 * 1024 *1"
failed to allocate memory (NoMemoryError)

CPU and Disk IO priorities
======================================
nice -n 19 rake xapian:update # run rake with priority 19
ionice -c3 rake xapian:update # same for disk IO


Atomic renames
======================================
- don't use locks
- write to temp then rename

Secure self-cleaning temporary files
======================================
- create temp fie
- delete it while holding it open
- write/read securely


Page cache expiry with find
======================================
find public/cache -type f --mmin +10 -delete # del all files 10 mins old in a "transaction"

Log rotation with logrotate
======================================
- Rails sucks at it, use time proven and tested UNIX


Managing daemons with start-stop-daemon
==========================================
- don't reinvent the wheel starting/stoping daemons (mogrels etc)
    start-stop-daemon -d $railsdir -b -o -p $pidfile --start --starts rake xapian:update
- run cron tasks using start-stop-daemon to avoid race condition (it will exit if process already runs)


Real time signals
==========================================
use it in ruby:
trap("USR1") { reopen_xapian_db }


Raliable messaging with... SMTP!
==========================================
Due to atomic and reliable delivery it can be use as a message queue.
Can replace RabbitHQ etc


dbus
==========================================
UNIX based Messaging system


Self-organising systems with AVAHI
==========================================
Bonjour??


Modularised config files
==========================================
/etc/cron.d/rails-myapp
/etc/logrotate.d/rails-myapp


Watchdog daemon
==========================================





&lt;/pre&gt;
&lt;/code&gt;

&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-4894299514644435487?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/CmaT6jAsCjs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/4894299514644435487/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/05/unix-do-not-reinvent-wheel.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/4894299514644435487?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/4894299514644435487?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/CmaT6jAsCjs/unix-do-not-reinvent-wheel.html" title="Unix - do not reinvent the wheel" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2011/05/unix-do-not-reinvent-wheel.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAAQ3w9eip7ImA9WhZWF08.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-6283584295998980033</id><published>2011-05-18T23:52:00.000+10:00</published><updated>2011-05-18T23:52:22.262+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-18T23:52:22.262+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="vim" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby-on-rails" /><title>What I've learned from Scottish RubyConf</title><content type="html">&lt;p&gt;
I watched the videos from the &lt;a href="http://video2010.scottishrubyconference.com/"&gt;Scottish RubyConf 2010&lt;/a&gt; and thought I could share some interesting moments as simple notes. So there you go:
&lt;/p&gt;

&lt;p&gt;

&lt;code&gt;
&lt;pre&gt;

Harmony for browser testing

Capybara.driver = :rack_test # uses Harmony and can run JS

Good talk about Arel: 1LT_04-mp4_500mbs.mp4

Rack GeoIP.
Rack GoogleAnalytics
Rack::Cache (standard)
Rack::CacheBuster

Server side include to render page without parts of content that fail
(Nginx + Rack)

EvenMachine:: WebSockets add-on uses JS like API.
Other options:
-em-websocket
-cramp (higher level websocket)
-sunshowers
-node.js
pusherapp.com

Initialise multiple variables in JS:
var a = 1, b = 2, noInitialised;
jQuery has "end" method to go up in the chain.



VIM
:copen - opens the console output
f - find next occurence of char in this line
dap - delete paragraph
cap - change
yap - yank
ytCHAR - yank from here to next CHAR
Ctrl-v - visual block mode
:split, :sp, :vspilt, :vsp - split into 2 wins
ls - list buffers touched
q1, q2, q3... - record macro into register
@1, @2, @3... - play the macro from register

:R - Rails related file
:A - Rails alternate file
:Rextract - Rails partial extract
Shift-k - integrated Ruby ri

figutive.vim - more extensions: Glog, Gblame, Gstatus, Gdiff, Ggrep etc
snippets.vim
nerdtree.vim - files tree view
surround.vim
unimpaired.vim - auto-brackets
Hashrocket configured Vim at Github hashrocket/dotmatrix
Vimium, Vimperator - Vim in browser
Remotely connect and pair in Vim


UTF-8 is backwards compatible with ASCII
Ruby doesn't know about UTF-16 - it's messy

Globalization TODO:
- Do same as .NET CultureInfo
- Do different ways to localize different kinds of langs


You can generate UML model of Rails model using:
railroad -M | dot Tpng &gt; model.png
uml dumper

Metrics:
- rake stats # LOCs
- FLOG Weighting the code AST - Assignment Branch Condition (ABC)
- FLAY - code similarities
- Saikuro - cyclomatic complexity
- Roodi - design issues
- Reek - design issues and specific smells
- Churn - changes to file with Git
- Rcov - test coverage
- Heckle - test coverage with code mutation
- metric_fu


&lt;/pre&gt;
&lt;/code&gt;

&lt;/p&gt;

&lt;p&gt;
You can also grab the &lt;a href="https://gist.github.com/978593"&gt;Gist&lt;/a&gt;. Hope you find some moment useful.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-6283584295998980033?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/Y-42S1JMfjM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/6283584295998980033/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/05/what-ive-learned-from-scottish-rubyconf.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/6283584295998980033?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/6283584295998980033?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/Y-42S1JMfjM/what-ive-learned-from-scottish-rubyconf.html" title="What I've learned from Scottish RubyConf" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2011/05/what-ive-learned-from-scottish-rubyconf.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkIASXY_eip7ImA9WhZTFE0.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-3075939678353673827</id><published>2011-03-18T11:35:00.001+11:00</published><updated>2011-03-18T11:35:48.842+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-18T11:35:48.842+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Development" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc" /><category scheme="http://www.blogger.com/atom/ns#" term="nunit" /><title>Unit test actions with ValueProviderFactories in ASP.NET MVC3</title><content type="html">&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; In the process of upgrading from MVC2 to MVC3 we have faced an issue where some of the &lt;a href="http://stackoverflow.com/questions/4603741/how-to-unit-test-valueproviderfactories-in-asp-net-mvc3"&gt;ValueProviders gain explicit access to static HttpContext&lt;/a&gt; thus making it too hard to test complex actions.&lt;/p&gt;  &lt;p&gt;The solution was not obvious at first and I want to provide enough context before the solution. The way I test the controllers is this:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;[TestFixture]
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CurrentUserControllerTest : BaseTestFixture {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; CurrentUserController controller;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; Mock&amp;lt;ICurrentUserService&amp;gt; userService;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; FakeHttpContext http;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Init() {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        userService = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Mock&amp;lt;ICurrentUserService&amp;gt;();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        controller = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; CurrentUserController(Services.Account, userService.Object)
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            .FakeContext(context =&amp;gt; http = context);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    [Test]
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; CanSeeSecuritySettingsPage() {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        userService.Setup(x =&amp;gt; x.ViewUser()).Returns(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; User {SecurityQuestion = &amp;quot;&lt;span style="color: #8b0000"&gt;sq&lt;/span&gt;&amp;quot;});
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        controller.SecuritySettings()
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            .ShouldHaveModel&amp;lt;CurrentUserController.SecuritySettingsInfo&amp;gt;()
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            .User.SecurityQuestion.Should().Be(&amp;quot;&lt;span style="color: #8b0000"&gt;sq&lt;/span&gt;&amp;quot;);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    [Test]
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SuccesfulUpdateRedirects() {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        controller.UpdateSecuritySettings()
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            .ShouldRedirectTo(action: &amp;quot;&lt;span style="color: #8b0000"&gt;Index&lt;/span&gt;&amp;quot;, controller: &amp;quot;&lt;span style="color: #8b0000"&gt;Dashboard&lt;/span&gt;&amp;quot;);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;The most relevant piece of code here is the extension method &lt;strong&gt;FakeContext&lt;/strong&gt;. It ensures the controller is not going to access real HttpContext. The main difference between MVC2 and 3 is that the latter uses HttpContext in FormValueProviderFactory and QueryStringValueProviderFactory. So we need to get rid of it. And of course we don’t want to modify all our tests and complicate them providing explicitly &lt;a href="http://weblogs.asp.net/scottgu/archive/2008/10/16/asp-net-mvc-beta-released.aspx#six"&gt;FormCollection&lt;/a&gt;. Additionally we definitely do not want to go into trouble &lt;a href="http://stackoverflow.com/questions/1686778/why-mock-httpcontext-if-it-can-be-constructed"&gt;instantiating HttpContext&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fortunately MVC is extensible enough and has number of hook that we can use. In this case we need to replace those two bustards (FormValueProviderFactory and QueryStringValueProviderFactory). Which can be done with this simple extension method:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ValueProviderFactoresExtensions {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; ValueProviderFactoryCollection ReplaceWith&amp;lt;TOriginal&amp;gt;(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; ValueProviderFactoryCollection factories, Func&amp;lt;ControllerContext, NameValueCollection&amp;gt; sourceAccessor) {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        var original = factories.FirstOrDefault(x =&amp;gt; &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(TOriginal) == x.GetType());
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (original != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            var index = factories.IndexOf(original);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            factories[index] = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; TestValueProviderFactory(sourceAccessor);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; factories;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; TestValueProviderFactory : ValueProviderFactory {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; Func&amp;lt;ControllerContext, NameValueCollection&amp;gt; sourceAccessor;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; TestValueProviderFactory(Func&amp;lt;ControllerContext, NameValueCollection&amp;gt; sourceAccessor) {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.sourceAccessor = sourceAccessor;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; IValueProvider GetValueProvider(ControllerContext controllerContext) {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollectionValueProvider(sourceAccessor(controllerContext), CultureInfo.CurrentCulture);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;}&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;And the final implementation of FakeContext extension that I use (you will need to trim it to your particular case) is:&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; TController FakeContext&amp;lt;TController&amp;gt;(this TController controller, Action&amp;lt;FakeHttpContext&amp;gt; exposeAction = null) where TController: Controller {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    ApplicationMetaData.RegisterAll(); // Additionally register all ModelBinder so tests behave &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; production
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (ViewEngines.Engines.Where(x =&amp;gt; x &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; SparkViewEngine).Empty()) {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        // We only use Spar view engine that can render view during testing
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        ViewEngines.Engines.Clear();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        ViewEngines.Engines.Insert(0, GetTestViewFactory());
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }            
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    // That &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; the entry &lt;span style="color: #0000ff"&gt;to&lt;/span&gt; all the fakes, implementation &lt;span style="color: #0000ff"&gt;is&lt;/span&gt; trivial so &lt;span style="color: #0000ff"&gt;not&lt;/span&gt; here
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    var context = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; FakeHttpContext();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    controller.ControllerContext = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ControllerContext(context, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; RouteData(), controller);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    controller.Url = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; UrlHelper(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; RequestContext(context, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; RouteData()));
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    // &lt;span style="color: #0000ff"&gt;And&lt;/span&gt; &lt;span style="color: #0000ff"&gt;finally&lt;/span&gt;, here we ensure no ValueProviders access HttpContext
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    ValueProviderFactories.Factories
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        .ReplaceWith&amp;lt;FormValueProviderFactory&amp;gt;(ctx =&amp;gt; ctx.HttpContext.Request.Form))
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        .ReplaceWith&amp;lt;QueryStringValueProviderFactory&amp;gt;(ctx =&amp;gt; ctx.HttpContext.Request.QueryString));
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (exposeAction != null)
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        exposeAction.Invoke(context);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; controller;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;}        &lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Hope that helps. Have fun!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-3075939678353673827?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/Io1m3u8SdrA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/3075939678353673827/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2011/03/unit-test-actions-with.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/3075939678353673827?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/3075939678353673827?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/Io1m3u8SdrA/unit-test-actions-with.html" title="Unit test actions with ValueProviderFactories in ASP.NET MVC3" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.approache.com/2011/03/unit-test-actions-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQMRHc-eCp7ImA9Wx9REUQ.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-4783018963934862649</id><published>2010-12-13T09:53:00.001+11:00</published><updated>2010-12-13T09:53:05.950+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-13T09:53:05.950+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="mobile" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="screencasts" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby-on-rails" /><category scheme="http://www.blogger.com/atom/ns#" term="web" /><title>Screencasts for this weekend</title><content type="html">&lt;p&gt;This weekend I was watching the screencasts instead of Sunday movies. It left me with a lot of inspiration and impressions. So I thought I would share the stuff you might also be interested in:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://tekpub.com/conferences/ndc2010/aspnet-mvc-vs-ruby-on-rails---the-net-rocks-smackdown"&gt;ASP.NET MVC vs Ruby on Rails - The .NET Rocks Smackdown&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://tekpub.com/conferences/rubyconf2010/dhh"&gt;Why Ruby?&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://tekpub.com/conferences/ndc2010/testing-csharp-and-aspnet-applications-with-ruby"&gt;Testing C# and ASP.NET Applications with Ruby&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://tekpub.com/conferences/ndc2010/ruby-for-net-developers"&gt;Ruby for .NET developers&lt;/a&gt; (Scott Belware is awesome BTW)&lt;/li&gt;    &lt;li&gt;&lt;a href="http://tekpub.com/conferences/ndc2010/riding-ironruby-on-rails"&gt;Riding IronRuby On Rails&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Other things are:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a title="http://tekpub.com/conferences/ndc2010/monotouch-deep-dive" href="http://tekpub.com/conferences/ndc2010/monotouch-deep-dive"&gt;MonoTouch DeepDive&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://peepcode.com/pages/rails-3-screencasts"&gt;Meet Rails 3&lt;/a&gt; by PeepCode (a producer of high-quality screencasts)&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;I think if you are a software engineer with open mind then you do need to watch some of the videos. This is especially true if you are a .NET developer who wants to explore other areas and technologies.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-4783018963934862649?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/F1jN1JqvZ50" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/4783018963934862649/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/12/screencasts-for-this-weekend.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/4783018963934862649?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/4783018963934862649?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/F1jN1JqvZ50/screencasts-for-this-weekend.html" title="Screencasts for this weekend" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/12/screencasts-for-this-weekend.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEGQ3w5eCp7ImA9Wx9SGEk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-3126716132083507095</id><published>2010-12-09T09:50:00.000+11:00</published><updated>2010-12-09T09:50:22.220+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-09T09:50:22.220+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="Development" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby-on-rails" /><title>Stuff learned today - Ruby and Rails</title><content type="html">&lt;ol&gt;
&lt;li&gt;Ruby ignores underscores in numbers, so you can write 53782156 as&amp;nbsp;53_782_156 which is much nicer.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://groups.google.com/group/formtastic/browse_thread/thread/d4b200e3d8073329"&gt;Suggested&lt;/a&gt; localisation for Formtastic's collections.&amp;nbsp;Not sure whether it is important as it is still pretty easy to workaround.&lt;/li&gt;
&lt;li&gt;To use all the ActiveSupport (v3), do &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;require 'active_support/all'&lt;/span&gt; (note the underscore!).&lt;/li&gt;
&lt;li&gt;We can add methods to associations by opening a block and (but scopes are much cleaner on the other end of association class).&lt;/li&gt;
&lt;li&gt;Testing "access denied" and "requires user" is easier with custom matchers.&lt;/li&gt;
&lt;li&gt;Rails URL helpers are not available in custom matchers for some reason.&lt;/li&gt;
&lt;li&gt;Shoulda's RSpec matcher validates_presence_of does not work with non-persistent models.&lt;/li&gt;
&lt;li&gt;Rails params hash has string keys, not symbols. Got issues with it when relying on keys being symbols.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-3126716132083507095?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/rT7teeyMNNk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/3126716132083507095/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/12/stuff-learned-today-ruby-and-rails.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/3126716132083507095?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/3126716132083507095?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/rT7teeyMNNk/stuff-learned-today-ruby-and-rails.html" title="Stuff learned today - Ruby and Rails" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/12/stuff-learned-today-ruby-and-rails.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YFSHczfip7ImA9Wx9SEE0.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-46127608899807873</id><published>2010-11-29T15:29:00.000+11:00</published><updated>2010-11-29T15:31:59.986+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-29T15:31:59.986+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="agile" /><category scheme="http://www.blogger.com/atom/ns#" term="practices" /><category scheme="http://www.blogger.com/atom/ns#" term="productivity" /><category scheme="http://www.blogger.com/atom/ns#" term="Development" /><category scheme="http://www.blogger.com/atom/ns#" term="patterns" /><category scheme="http://www.blogger.com/atom/ns#" term="skills" /><category scheme="http://www.blogger.com/atom/ns#" term="presentation" /><title>Rules of Productivity</title><content type="html">&lt;p&gt;How do we get more work done? It is a question that every manager and every passionate worker faces. Yet, for the most part, teams operate on gut instinct and habit. The results are less than optimal. [&lt;a href="http://www.lostgarden.com/2008/09/rules-of-productivity-presentation.html"&gt;source&lt;/a&gt;]&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;What is productivity?&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;+ Work accomplished &lt;/li&gt;    &lt;li&gt;- Work required to fix defects &lt;/li&gt;    &lt;li&gt;- Work required to fix bad design decisions &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Productivity can be &lt;strong&gt;&lt;em&gt;negative &lt;/em&gt;&lt;/strong&gt;when there is more harm than good.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_6a0bIbZ1HXw/TPMsQV26e9I/AAAAAAAAEx4/W_cKdhYLIEc/s1600-h/image%5B9%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_6a0bIbZ1HXw/TPMsREicCvI/AAAAAAAAEx8/UGFxiCYKKxc/image_thumb%5B5%5D.png?imgmax=800" width="455" height="347" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h2&gt;&amp;#160;&lt;/h2&gt;  &lt;h2&gt;Experiment 1: Overtime&lt;/h2&gt;  &lt;p&gt;Working more than&amp;#160; 40 hours a week leads to decreased productivity.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;lt; 40 hours/week – working not “enough”. &lt;/li&gt;    &lt;li&gt;&amp;gt; 60 hours/week – small productivity boost. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The boost only lasts for 3 to 4 weeks and then turns &lt;em&gt;&lt;strong&gt;negative&lt;/strong&gt;&lt;/em&gt;. Though can be used for a short-time productivity increase.&lt;/p&gt;  &lt;p&gt;So, work 40 hours a week with time for rest and family. Never work 2 months of 60 hrs/week. Overall productivity will be lower, despite the initial boost.&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h2&gt;Experiment 2: Work harder in bursts.&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;Take advantage of the burst during overtime. &lt;/li&gt;    &lt;li&gt;Crunch for a week and work only 40 hrs on another week. &lt;/li&gt;    &lt;li&gt;Any more efficient work patterns? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Anything over 40 hrs/week results in a recovery period, no matter how you split it up. 40 hrs/week can be 10 hrs/day for 4 days and one day off. This pattern of work can increase productivity by 10-70%.&lt;a href="http://lh4.ggpht.com/_6a0bIbZ1HXw/TPMsSG9AnZI/AAAAAAAAEyA/Wq0Ax8mVAgc/s1600-h/image%5B5%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_6a0bIbZ1HXw/TPMsS0R9wwI/AAAAAAAAEyE/3C1FYViAnek/image_thumb%5B3%5D.png?imgmax=800" width="468" height="357" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;So:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Raise productivity immediately with short spurts &amp;lt; 3 weeks. &lt;/li&gt;    &lt;li&gt;Overtime temporarily to meet deadlines. &lt;/li&gt;    &lt;li&gt;Plan for the reduction in productivity immediately afterwards. &lt;/li&gt;    &lt;li&gt;Consider 4-day work week as a flexitime option. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Experiment 3:&amp;#160; Performance for knowledge workers declines after 35 hrs, not 40.&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;Creativity and problem solving decreases faster with fatigue than manual labour. &lt;/li&gt;    &lt;li&gt;Grinding&amp;#160; out problems by working longer&amp;#160; on average result in inferior solutions. &lt;/li&gt;    &lt;li&gt;Lack of sleep is particularly damaging. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Overtime kills creativity. &lt;/li&gt;    &lt;li&gt;If you are stuck on a problem, go home or take a break. &lt;/li&gt;    &lt;li&gt;Get 8 hrs of sleep to improve your problem solving abilities. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Experiment 4: Teams on overtime feel like they are doing more, but actually accomplish less.&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;Team with overtime feels like they are doing much more than the team without overtime. &lt;/li&gt;    &lt;li&gt;Team without overtime produces the better product and accomplishes more. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_6a0bIbZ1HXw/TPMsTkqVtLI/AAAAAAAAEyI/HZvCvNe_lNY/s1600-h/image%5B13%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_6a0bIbZ1HXw/TPMsUp4sGLI/AAAAAAAAEyM/IHbhVUR7D-k/image_thumb%5B7%5D.png?imgmax=800" width="476" height="363" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Humans ignore the systematic costs and physiological biases:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Failure to measure (cost of defects, bad design decisions, missed opportunities). &lt;/li&gt;    &lt;li&gt;Linear extrapolation (initial productivity boost is seen as same in the future). &lt;/li&gt;    &lt;li&gt;Habit (a bad one!). &lt;/li&gt;    &lt;li&gt;Self reported excellence (behaviour rewarded independent of the results). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The feeling of increased long-term productivity is FALSE. &lt;/li&gt;    &lt;li&gt;Use customer metrics to determine the productivity. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Experiment 5: Productivity is maximised in small teams of 4-8 people.&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;Productivity of a small group is 30-50% higher than groups over 10 people. &lt;/li&gt;    &lt;li&gt;Too high cost of communication for groups with &amp;gt; 10 people. &lt;/li&gt;    &lt;li&gt;Smaller teams don’t have enough breadth to solve a wide array of problems. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Split your teams into cross-functional teams. &lt;/li&gt;    &lt;li&gt;Link small teams using '”scrum-of-scrums”. &lt;/li&gt;    &lt;li&gt;Create processes for:      &lt;ul&gt;       &lt;li&gt;growing new teams; &lt;/li&gt;        &lt;li&gt;splitting large teams; &lt;/li&gt;        &lt;li&gt;transitioning to new projects; &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Experiment 6: Seat people on the same team together in a closed team room.&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;&lt;em&gt;&lt;strong&gt;100% increase &lt;/strong&gt;&lt;/em&gt;in productivity. &lt;/li&gt;    &lt;li&gt;Faster communication and problem-solving. &lt;/li&gt;    &lt;li&gt;Fewer external interruptions to the team increase overall productivity. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Seat the team in their own room. With walls. &lt;/li&gt;    &lt;li&gt;Give at least 5 sqr/meters per person. &lt;/li&gt;    &lt;li&gt;Create side rooms for private conversations, phone calls, meetings. &lt;/li&gt;    &lt;li&gt;Minimise non-team distractions. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Experiment 6: Cross-functional teams outperform siloed teams&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;Produced more effective solutions in the same time. &lt;/li&gt;    &lt;li&gt;Much more likely to generate breakthrough solutions. &lt;/li&gt;    &lt;li&gt;Short-term loss of negotiation of norms. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This is why:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Fewer external dependencies mean fewer lengthy blockages. &lt;/li&gt;    &lt;li&gt;Team has the breadth to see the forest, not just the trees. &lt;/li&gt;    &lt;li&gt;Different perspectives mean lower chance of groupthink. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Create the team where every skill needed to solve the problem at hand is in the same room. &lt;/li&gt;    &lt;li&gt;Limit the charter: “Do everything = big team”. &lt;/li&gt;    &lt;li&gt;Fulltime: focused team member efforts. &lt;em&gt;&lt;strong&gt;Multitasking = 15% drop in productivity&lt;/strong&gt;&lt;/em&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Experiment 8: Scheduling at 80% of team capacity produces better products.&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;Scheduling at 100% doesn’t give space to creativity. &lt;/li&gt;    &lt;li&gt;No lost time: passionate workers keep thinking. &lt;/li&gt;    &lt;li&gt;The 20% goes into new idea generation and process improvements. &lt;/li&gt;    &lt;li&gt;&lt;em&gt;&lt;strong&gt;Producing 20 great features is usually far more profitable than 100 competent features&lt;/strong&gt;&lt;/em&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Why?&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Allows employees to explore many options cheaply. &lt;/li&gt;    &lt;li&gt;Gives time to prototype breakthrough solutions that sound crazy on paper. &lt;/li&gt;    &lt;li&gt;&lt;em&gt;&lt;strong&gt;Allows people to pursue passions&lt;/strong&gt;&lt;/em&gt;. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Schedule 20% below possible velocity. &lt;/li&gt;    &lt;li&gt;Hold periodic reviews of side projects and award interesting ideas. &lt;/li&gt;    &lt;li&gt;Publicise and reward side projects that make their way into production. &lt;/li&gt;    &lt;li&gt;Keep a public list of important things if anyone runs out of work (happens rarely). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h2&gt;Other productivity Techniques&lt;/h2&gt;  &lt;h3&gt;Experimentation culture:&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Fail faster to find success sooner. &lt;/li&gt;    &lt;li&gt;Short iterations. &lt;/li&gt;    &lt;li&gt;User metrics such as A/B testing. &lt;/li&gt;    &lt;li&gt;State gate portfolio management. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Safety nets:&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Test-Driven-Development. &lt;/li&gt;    &lt;li&gt;Daily/weekly access to real customers. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Empower the team&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Constraints-based requirements, not mandates from above. &lt;/li&gt;    &lt;li&gt;Training. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;See the original &lt;a href="http://www.lostgarden.com/2008/09/rules-of-productivity-presentation.html"&gt;PDF&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-46127608899807873?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/DtlrNuCDsjY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/46127608899807873/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/11/rules-of-productivity.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/46127608899807873?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/46127608899807873?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/DtlrNuCDsjY/rules-of-productivity.html" title="Rules of Productivity" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_6a0bIbZ1HXw/TPMsREicCvI/AAAAAAAAEx8/UGFxiCYKKxc/s72-c/image_thumb%5B5%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/11/rules-of-productivity.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck8DQn0zcSp7ImA9WhdTFEk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-3098345605095043327</id><published>2010-11-28T23:59:00.002+11:00</published><updated>2011-07-12T13:21:13.389+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-12T13:21:13.389+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="webforms" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby-on-rails" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc" /><category scheme="http://www.blogger.com/atom/ns#" term="web" /><title>Ruby On Rails vs ASP.NET MVC</title><content type="html">I have been watching the ASP.NET MVC vs Ruby On Rails talk from the &lt;a href="http://tekpub.com/conferences/ndc2010"&gt;Norwegian Developers Conference 2010&lt;/a&gt; and just want to make a number of quotes that I particularly liked. My apologies if I missed something, but I believe it would be interesting to read it for those who don’t want to spend 48 minutes to watch the whole thing. I believe the quotes here really summarise the atmosphere during the talk.&lt;br /&gt;
So here we go:&lt;br /&gt;
&lt;blockquote&gt;
Rails was extracted from the real world work sweat, blood, tears, everything..&lt;/blockquote&gt;
And it feels like it is.&lt;br /&gt;
&lt;blockquote&gt;
ASP.NET MVC is a "me too" framework - trying to compete with other solutions. ASP.NET MVC is not part of the story for WebForms, not quite fit.&lt;/blockquote&gt;
Aha. Try to tell WebForms guy about MVC :)&lt;br /&gt;
&lt;blockquote&gt;
Microsoft promotes it as an option. Option for what?&lt;/blockquote&gt;
These words from Rob Conery probably mean that MVC is something that was not “designed” to be mainstream. But rather an “option” for… well web development on .NET.&lt;br /&gt;
&lt;blockquote&gt;
[About TekPub]…rewrite point for startup - reconsidered BizSpark. We wanted to stay small.We needed fast, easy framework. Up in the cloud, scalable, zero cost, everything.&lt;/blockquote&gt;
There was a lot of buzz behind the &lt;a href="http://blog.approache.com/2010/05/quotes-moving-from-aspnet-mvc-to-ruby.html"&gt;decision to move to Rails&lt;/a&gt; by Rob Conery who was a .NET advocate. But it was a happy business AND technical decision.&lt;br /&gt;
&lt;blockquote&gt;
Rails came out of a need. MVC hasn't. NHibernate came out of a need. Entity Framework hasn't. It's always the same: solving problems they personally don't have, so they are not in the context of their problems.&lt;br /&gt;
Microsoft projects often come out of suppositions.&lt;/blockquote&gt;
That is very common with Microsoft. They have to be everywhere and at the same time nowhere. Anything “new” that comes out from Microsoft has already been adopted and they are just catching up.&lt;br /&gt;
&lt;blockquote&gt;
Dell is rebuilding everything in &lt;a href="http://asp.net/"&gt;ASP.NET&lt;/a&gt; MVC (instead of WebForms).&lt;/blockquote&gt;
Good for them. In any case, ASP.NET MVC&amp;nbsp; IS a good thing to have in .NET world. And that’s my preference for Web development in .NET. Probably same goes with Dell.&lt;br /&gt;
&lt;blockquote&gt;
MVC redirected the attention back to .NET after .NET Web developers started moving to Rails.&lt;/blockquote&gt;
True. And in fact, most of the features of ASP.NET MVC were borrowed from Rails. So that was one of the easiest ways to hold .NET gurus back.&lt;br /&gt;
&lt;blockquote&gt;
Why would .NET developers move to Rails?      &lt;br /&gt;Testing in rails is…uhh… it’s something you realise when you do it. Testing tools like RSpec and Cucumbet are just natural.       &lt;br /&gt;Deployment – Capistrano, Heroku – just unbelievable.&lt;/blockquote&gt;
Cannot agree more on this. Testing “just works”, deployment “just works” it all “just works”.&lt;br /&gt;
&lt;blockquote&gt;
In .NET we like to overcomplicate ourselves. Something too simplistic can’t be good. [No worries with SRP principle – objects aware of the persistence and similar].      &lt;br /&gt;In .NET we question more.&lt;/blockquote&gt;
Speaking about myself, I do agree with it. Partially due to the nature of .NET (C#), partially because testing is harder, but also just because .NET developers try to solve problems in advance assuming those will exists (while in many cases they will not).&lt;br /&gt;
&lt;blockquote&gt;
The MVC/MonoRail and Ruby On Rails have the same features.&lt;/blockquote&gt;
Read on…&lt;br /&gt;
&lt;blockquote&gt;
You have the same names of the features, but the experience is dramatically different. There’s incredible amount of software out of the box to do anything.      &lt;br /&gt;ASP.NET NVC hasn’t even got a plug-in mechanism.&lt;/blockquote&gt;
So true! So true!&lt;br /&gt;
&lt;blockquote&gt;
Why do we have to wait for 2 years to get the innovation that we already have available to us right now in Rails?&lt;/blockquote&gt;
The rails community moves with small changes all the time, while .NET – with large in couple of years time. So for Rails it is a normal evolution, while for .NET it is rather a revolution.&lt;br /&gt;
&lt;blockquote&gt;
[about Rails]… it means you are building a web site, and you are not rebuilding the stuff that has already been built. You are building Business.&lt;/blockquote&gt;
Oh, yes. Having higher level plug-ins (nearly as Service-Oriented-Architecture components) it opens much more opportunities for business.&lt;br /&gt;
&lt;blockquote&gt;
Not everybody is fortunate of making decisions at work [on choosing technology].&lt;/blockquote&gt;
Try to push a new technology in a corporate environment with all the bureaucratic procedures. No f…ing way! Unless you are the one who decides.&lt;br /&gt;
&lt;blockquote&gt;
Building web sites on .NET is about building web sites in a corporate environment. And that’s not about productivity. That’s not about really, really, really compressed budget where every decision is your life and death decision…[and then] It’s like we have a budget, but is is rather a suggestion.&lt;/blockquote&gt;
Not much to comment on here. Don’t care about money – you are a .NET shop. Otherwise – probably Rails.&lt;br /&gt;
&lt;blockquote&gt;
It’s about how fast you can turn your ideas into money.&lt;/blockquote&gt;
Well said!&lt;br /&gt;
&lt;blockquote&gt;
Most of the cost of long lived projects is re-learning. Ruby code is just scan and get it.&lt;/blockquote&gt;
Indeed, Rails, would not even exist without such a beautiful language as Ruby. It makes code easy to understand.&lt;br /&gt;
&lt;blockquote&gt;
In Ruby there is just less code to see where a problem might be. A lot less code! And the code is so usable that you can really spot the problems really quickly.&lt;/blockquote&gt;
Again so true. Just have a look, for example, at some OSS projects. They do so much with so little code. That’s just amazing.&lt;br /&gt;
&lt;br /&gt;
At the end, I must admit that I do like the .NET platform, but Ruby and Rails just feels much better to me and ALL of the things I currently do for myself, I do using Ruby/Rails.&lt;br /&gt;
It is just much more fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-3098345605095043327?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/SPjOfZHtRws" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/3098345605095043327/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/11/ruby-on-rails-vs-aspnet-mvc.html#comment-form" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/3098345605095043327?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/3098345605095043327?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/SPjOfZHtRws/ruby-on-rails-vs-aspnet-mvc.html" title="Ruby On Rails vs ASP.NET MVC" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>7</thr:total><feedburner:origLink>http://blog.approache.com/2010/11/ruby-on-rails-vs-aspnet-mvc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04BSHc4eip7ImA9Wx5aFEg.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-879497308855314026</id><published>2010-11-11T17:05:00.001+11:00</published><updated>2010-11-11T17:12:39.932+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-11T17:12:39.932+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net" /><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc" /><title>Render any ASP.NET MVC ActionResult to a string</title><content type="html">&lt;p&gt;I often see questions on the net about how to render a view to a string so it can be used somewhere.&lt;/p&gt;  &lt;p&gt;My approach allows doing it without thinking about all the boilerplate code. Additionally not only the ViewResult can be rendered into a string but just about any type of the result. Here is example on how to return a JSON including the result of the view as additional information:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #008000"&gt;// Controller Action:&lt;/span&gt;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; JsonResult DoSomething() {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    var viewString = View(&amp;quot;&lt;span style="color: #8b0000"&gt;TheViewToRender&lt;/span&gt;&amp;quot;).Capture(ControllerContext);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; JsonResult {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        JsonRequestBehavior = JsonRequestBehavior.AllowGet,
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        Data = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            time = DateTime.Now,
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            html = viewString
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    };
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;}
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;This can be done with 2 simple utility classes below. Just include them somewhere into your project.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ResponseCapture : IDisposable {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; HttpResponseBase response;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; TextWriter originalWriter;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; StringWriter localWriter;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ResponseCapture(HttpResponseBase response) {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.response = response;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            originalWriter = response.Output;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            localWriter = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StringWriter();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            response.Output = localWriter;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ToString() {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            localWriter.Flush();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; localWriter.ToString();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Dispose() {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (localWriter != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;) {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                localWriter.Dispose();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                localWriter = &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                response.Output = originalWriter;
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ActionResultExtensions {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Capture(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt; ActionResult result, ControllerContext controllerContext) {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            &lt;span style="color: #0000ff"&gt;using&lt;/span&gt; (var it = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ResponseCapture(controllerContext.RequestContext.HttpContext.Response)) {
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                result.ExecuteResult(controllerContext);
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;                &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; it.ToString();
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;            }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;        }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;    }
&lt;/pre&gt;&lt;pre style="background-color: #ffffff; margin: 0em; width: 100%; font-family: consolas,&amp;#39;Courier New&amp;#39;,courier,monospace; font-size: 12px"&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Enjoy and let me know if it works for you.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-879497308855314026?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/bUbYOKEiWnk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/879497308855314026/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/11/render-any-aspnet-mvc-actionresult-to.html#comment-form" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/879497308855314026?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/879497308855314026?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/bUbYOKEiWnk/render-any-aspnet-mvc-actionresult-to.html" title="Render any ASP.NET MVC ActionResult to a string" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>10</thr:total><feedburner:origLink>http://blog.approache.com/2010/11/render-any-aspnet-mvc-actionresult-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ENR3o5eyp7ImA9Wx5bGUk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-9166866352749145002</id><published>2010-11-05T20:33:00.001+11:00</published><updated>2010-11-05T20:34:56.423+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-05T20:34:56.423+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="rspec" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="mocking" /><title>RSpec 2.0 cheat sheet by example</title><content type="html">&lt;p&gt;The Ruby developers know and hear a lot of buzz about RSpec BDD framework. The RSpec specifications code is so easy to read, but for my it is often hard to write. So I intend to produce a small cheat-sheet for RSpec syntax for myself.&lt;/p&gt;  &lt;p&gt;Most of it come from the &lt;a href="http://www.pragprog.com/titles/achbd/the-rspec-book"&gt;RSpec Book&lt;/a&gt; in rather unusual way. As a RSpec itself (unfortunately not runnable for now).&lt;/p&gt;  &lt;p&gt;Please feel free to use it in any way you want and correct the mistakes.&lt;/p&gt;  &lt;p&gt;So &lt;a href="https://gist.github.com/663876"&gt;here we go&lt;/a&gt;:&lt;/p&gt; &lt;script src="https://gist.github.com/663876.js?file=rspec-syntax-cheat-sheet.rb"&gt;&lt;/script&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-9166866352749145002?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/e0ZAHN4-Rho" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/9166866352749145002/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/11/rspec-hints-and-techniques.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/9166866352749145002?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/9166866352749145002?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/e0ZAHN4-Rho/rspec-hints-and-techniques.html" title="RSpec 2.0 cheat sheet by example" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/11/rspec-hints-and-techniques.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MDQHg4eyp7ImA9Wx5UFEk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-7921250391125865030</id><published>2010-10-19T10:30:00.001+11:00</published><updated>2010-10-19T10:44:31.633+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-19T10:44:31.633+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="Development" /><category scheme="http://www.blogger.com/atom/ns#" term="DevTools" /><category scheme="http://www.blogger.com/atom/ns#" term="standards" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Securities and Exchange Commission – comment on comment</title><content type="html">&lt;p&gt;I have been going through the &lt;a href="http://www.sec.gov/comments/s7-08-10/s70810-89.pdf"&gt;comments submitted&lt;/a&gt; to the US Securities and Exchange Commission.&lt;/p&gt;  &lt;p&gt;I feel like I have to add my 2 cents on it. My first &lt;em&gt;impression &lt;/em&gt;is that the analysis was not performed in full and the authors are being very affiliated with a company (which seems to be Microsoft).&lt;/p&gt;  &lt;p&gt;One and most important issue with this document is that authors do not seem to fully understand the dynamic languages and they have not even taken into account (possibly) the most suited language for the task – &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt;. Of course I may be wrong.&lt;/p&gt;  &lt;p&gt;I have to say that I have nothing against authors or anything like that.&lt;/p&gt;  &lt;p&gt;My point is that &lt;em&gt;I believe&lt;/em&gt; that the analysis could have been performed more deeply with close interaction with professionals of the particular languages.&lt;/p&gt;  &lt;p&gt;So now, I would like to comment on the submission:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Safe execution of code written by one party on a machine owned by a different party was not a strong concern in the design of Python. It was a strong concern in the design of other systems, including Java and the .Net framework&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is neither sufficient nor necessary to achieve the security. The security is the effort of the developers, IT administrators and the people working with the system. Even when using an interpreted language it can be executed inside a virtual machine (be it JVM, .NET, SmallTalk etc) providing that sandbox mentioned above. Most common examples are – Jython, IronPython, JRuby, IronRuby etc. This cannot be served as a decision point.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;A domain-specific language would support writing waterfall programs that are shorter and easier to read, and should help ensure consistency between the program and the narrative description.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is exactly what Ruby, Python and other dynamic languages are good at. And this is exactly what C#, Java and other static typed languages are bad at. Not sure why having it as a crucial requirements the wrong tool for the job is advocated.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Efficiency&lt;/strong&gt;. … Java, C#, and F# are designed to be executed efficiently, Python and Perl implementations are significantly less efficient.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is true in many cases. But having the requirements in mind, the language inefficiency can be compensated with additional hardware. Its cost is significantly less than the cost of development time using strongly/statically typed languages.    &lt;br /&gt;If additional performance needed – then the just-in-time compiler can be used instead of interpretation (this includes Rubinius, IronRuby, JRuby, MacRuby etc)&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Typing&lt;/strong&gt;. Statically typed languages are generally considered to produce more reliable and easier to maintain code, while dynamically typed languages are generally considered to produce more flexible code and to be better suited for prototyping. Java, C#, F# are statically typed; Python and Perl are dynamically typed.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This can phrase exactly the other way around and is neither sufficient nor necessary to achieve supportability.&lt;/p&gt;  &lt;p&gt;The wording is rather weird here:&amp;#160; “&lt;em&gt;…languages are .. considered to produce more reliable and easier to maintain code&lt;/em&gt;”. The languages do NOT produce code. It is a developer who does it.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;. Some programming languages have been designed with security in mind, and some of their implementations include “sandboxes” that can securely execute untrusted code. Java, C#, and F# are such languages; Python and Perl are not.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;As I mentioned above it cannot be the the deciding point because most of the dynamically typed languages can be easily run inside that sandbox using either a JVM, JIT or just a virtual machine; also sandboxing in the sense above does not eliminate the security issues. And we have a &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/09/18/important-asp-net-security-vulnerability.aspx"&gt;fairly recent example&lt;/a&gt; of that.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Domain-specific languages&lt;/strong&gt;. Any programming language can serve as a basis for a domain-specific language by augmenting it with suitable libraries. Experience seems to show that higher-order programming languages such as F# provide a particularly good basis for domain-specific languages. There are financial domain-specific languages available in F#.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I don’t understand why F# is the only recommendation here. Ruby is one of the greatest languages to produce DSLs. Clojure may also be considered. For that matter Martin Fowler’s Domain Specific Languages book can be used as the starting point.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I do advocate Ruby language here and believe it can be used with a great success. Only one huge disadvantage of it is the absence of a formal specification (which in my opinion is the advantage as it allows better evolution of the language).&lt;/p&gt;  &lt;p&gt;And of course there are many factors that have to be taken into account that may roll Ruby out, but it must be considered at least.&lt;/p&gt;  &lt;p&gt;Additionally inviting professionals from Ruby, Python, Perl communities to suggest on the subject will provide much more information and will allow making an informative decision.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-7921250391125865030?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/zIpYSDHTAO0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/7921250391125865030/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/10/securities-and-exchange-commission.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/7921250391125865030?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/7921250391125865030?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/zIpYSDHTAO0/securities-and-exchange-commission.html" title="Securities and Exchange Commission – comment on comment" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/10/securities-and-exchange-commission.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMHQX46fip7ImA9Wx5SGUk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-5316807935722128111</id><published>2010-08-09T18:53:00.001+10:00</published><updated>2010-08-16T17:23:50.016+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-16T17:23:50.016+10:00</app:edited><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="challenge" /><category scheme="http://www.blogger.com/atom/ns#" term="Development" /><category scheme="http://www.blogger.com/atom/ns#" term="ideas" /><title>Ruby Challenge for Newbies reborn</title><content type="html">&lt;p&gt;A question has been raised whether or not &lt;a href="http://ruby-challenge.rubylearning.org/"&gt;Ruby Challenge for Newbies&lt;/a&gt; should exist or not. The main concern is:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;…today, probably due to lack of time or other commitments, not many experienced Rubyists are willing to set a Ruby challenge for the newbies&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I guess many Rubysts DO want to set the challenges, but unfortunately very few people these days have enough time.&lt;/p&gt;  &lt;p&gt;Another problem with such challenges is that they are somewhat “detached” from the real life. Though I am not saying they are not interesting or educating. Don’t get me wrong, definitely they ARE. But still, I guess, many people would love to see how Ruby should be used correctly (the Rubyish way) in real-world applications. Especially in web apps.&lt;/p&gt;  &lt;p&gt;So if there is the problem trying to find new challenges, then either WE need to set up new challenges and recommend people who can do that or, if that is not possible, the challenge itself might need to be &amp;quot;converted&amp;quot; to something different.&lt;/p&gt;  &lt;p&gt;It seems the latter is the better choice at this moment.&lt;/p&gt;  &lt;p&gt;Having said that, I believe that a good challenge should have attributes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;driven by people; &lt;/li&gt;    &lt;li&gt;not dependent on one person (though may be controlled by one or a group); &lt;/li&gt;    &lt;li&gt;winner(s) appointed by the people (though influenced by the owner/controller); &lt;/li&gt;    &lt;li&gt;collaborative; &lt;/li&gt;    &lt;li&gt;“shareable”; &lt;/li&gt;    &lt;li&gt;role-playing; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;These are the ideas from the top of my head, but it is possible to play around those…&lt;/p&gt;  &lt;p&gt;I personally feel like it brings us to the following idea of a challenge: &lt;strong&gt;Ruby Project Development challenge&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Somebody suggests an idea to implement (interesting web application, some kind of useful tool, etc). Then the challenge becomes a project that people have to deliver. There are main two roles in this challenge:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;product owners; &lt;/li&gt;    &lt;li&gt;development team. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The &lt;em&gt;product owners&lt;/em&gt; group consists of number of people who do like the idea but may not have time, ability to develop that. This group decides where the &lt;em&gt;development team&lt;/em&gt; is heading to, and negotiates the requirements.&lt;/p&gt;  &lt;p&gt;The &lt;em&gt;development team&lt;/em&gt; is a group of self-organised people who do the actual development. Multiple development teams may exist to develop the same application.&lt;/p&gt;  &lt;p&gt;The duration for the challenge may vary from weeks to couple of months. The winner of the challenge is the person who gets most number of votes from either product owners/development team or both (not sure yet). If there are multiple teams – then the winning team may also be chosen.&lt;/p&gt;  &lt;p&gt;So the process of the challenge would be something like this:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Somebody comes up with a project idea. &lt;/li&gt;    &lt;li&gt;People join this project either as &lt;em&gt;product owner&lt;/em&gt; or as &lt;em&gt;development team&lt;/em&gt;. &lt;/li&gt;    &lt;li&gt;People get organised in couple of development teams and a couple of product owners if too many guys have joined. &lt;/li&gt;    &lt;li&gt;The countdown begins: &lt;em&gt;product owners&lt;/em&gt; and &lt;em&gt;development teams&lt;/em&gt; start working together (not necessarily at the same time). &lt;/li&gt;    &lt;li&gt;During the work people should be able to see what others do, and help each other to deliver the product. &lt;/li&gt;    &lt;li&gt;At the end of the challenge winners in following categories may be selected:      &lt;ul&gt;       &lt;li&gt;best developer; &lt;/li&gt;        &lt;li&gt;best team; &lt;/li&gt;        &lt;li&gt;best team-mate; &lt;/li&gt;        &lt;li&gt;incredible inventor; &lt;/li&gt;        &lt;li&gt;etc &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;This of course is the basic idea, but it has sooo many variations.&lt;/p&gt;  &lt;p&gt;So I propose the first challenge of this kind: &lt;strong&gt;Web applications supporting the challenge itself&lt;/strong&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-5316807935722128111?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/LQ3TJln7oIM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/5316807935722128111/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/08/ruby-challenge-for-newbies-reborn.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/5316807935722128111?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/5316807935722128111?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/LQ3TJln7oIM/ruby-challenge-for-newbies-reborn.html" title="Ruby Challenge for Newbies reborn" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.approache.com/2010/08/ruby-challenge-for-newbies-reborn.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8NRXk6cSp7ImA9WxFaGUg.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-2455457630347364082</id><published>2010-07-24T15:32:00.001+10:00</published><updated>2010-07-24T16:44:54.719+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-24T16:44:54.719+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="marketing" /><category scheme="http://www.blogger.com/atom/ns#" term="honesty" /><category scheme="http://www.blogger.com/atom/ns#" term="Personal" /><category scheme="http://www.blogger.com/atom/ns#" term="business" /><title>Caring, selling and appreciating technology era</title><content type="html">I have watched the &lt;a href="http://www.youtube.com/watch?v=-QWHkcCP3tA"&gt;RailsConf 2010 by Gary Vaynerchuk&lt;/a&gt; and I believe that was &lt;b&gt;one of the best presentations I have seen&lt;/b&gt; in a very long while.&lt;br /&gt;
&lt;br /&gt;
Gary is just outstanding and I highly recommend you to watch this video it (but be prepared - there is a log of swearing, which I actually like).&lt;br /&gt;
&lt;br /&gt;
There is nothing about Ruby (On Rails), .NET, Java or any other technology.&lt;br /&gt;
This is just a talk about what you &lt;b&gt;should care about&lt;/b&gt; as a business owner, this is about &lt;b&gt;appreciation of the digital era&lt;/b&gt; we are living in. Also it is about &lt;b&gt;caring&lt;/b&gt; about people, and &lt;b&gt;cutting bullshit&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Sit, make yourself comfortable and DO WATCH it:&lt;br /&gt;
&lt;object height="385" width="640"&gt;&lt;param name="movie" value="http://www.youtube.com/v/-QWHkcCP3tA&amp;amp;hl=en_US&amp;amp;fs=1"&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/-QWHkcCP3tA&amp;amp;hl=en_US&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;br /&gt;
Hope you'll enjoy it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-2455457630347364082?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/yzWSRUkNC-Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/2455457630347364082/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/07/honest-and-sales-please-care.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/2455457630347364082?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/2455457630347364082?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/yzWSRUkNC-Y/honest-and-sales-please-care.html" title="Caring, selling and appreciating technology era" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/07/honest-and-sales-please-care.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0EDRHszfCp7ImA9WxFaGUk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-523599601392404934</id><published>2010-07-05T22:48:00.006+10:00</published><updated>2010-07-24T15:34:35.584+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-24T15:34:35.584+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="asp.net mvc" /><category scheme="http://www.blogger.com/atom/ns#" term="view-engine" /><category scheme="http://www.blogger.com/atom/ns#" term="razor" /><title>Razor - ASP.NET MVC View Engine - first impression</title><content type="html">&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;
The new view engine is being released by Microsoft and looking at &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx" target="_blank"&gt;the announcement&lt;/a&gt; I feel a bit confused. Two questions flying in my head:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Why not take existing one and just help to make it better/sponsor?&lt;/li&gt;
&lt;li&gt;Is it going to be a new productive thing or will it just make the view to be more spaghetti-like?&lt;/li&gt;
&lt;/ol&gt;
Not sure now. Time will show, but there are some things I feel I just must comment on. I'll try to look at it as a developer with no any politics and trying to think how it can help me.&lt;br /&gt;
&lt;blockquote&gt;
Unit Testable: The new view engine implementation will support the ability to unit test views (without requiring a controller or web-server, and can be hosted in any unit test project – no special app-domain required).&lt;/blockquote&gt;
&lt;br /&gt;
For me this one would probably be enough to jump onto that with head. I still have &lt;a href="http://stackoverflow.com/questions/2781027/test-views-in-asp-net-mvc2-ala-rspec" target="_blank"&gt;the question&lt;/a&gt; on StackOverflow about testing the view hanging around. It &lt;i&gt;looks like&lt;/i&gt; now I have the answer.&lt;br /&gt;
&lt;blockquote&gt;
the start of a code block with Razor using a @ character. Unlike &amp;lt;% %&amp;gt; code nuggets, Razor does not require  you to explicitly close the code-block&lt;/blockquote&gt;
This is a huge typing and "mistake" saver. I like it, but still have the concern about the readability and ambiguity of such syntax. I need to give it a try first to tell whether this helps to do the job or screws things up. But the intention is definitely good.&lt;br /&gt;
Next, the code blocks mixed together with HTML:&lt;br /&gt;
&lt;code&gt;  &amp;lt;ul&amp;gt;&lt;br /&gt;    @foreach(var p in products) {&lt;br /&gt;      &amp;lt;li&amp;gt;@p.Name ($@p.Price)&amp;lt;/li&amp;gt;&lt;br /&gt;    }&lt;br /&gt;  &amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;br /&gt;
Currently it looks a bit weird to me. We need to get used to it.&lt;br /&gt;
&lt;br /&gt;
So you can do lots of interesting things using such syntax. Additionally I have to state that the engine has a special tag - &lt;i&gt;text&lt;/i&gt;. It is used actually to avoid adding any wrapping tag to markup serving the purpose of grouping things together.&lt;br /&gt;
&lt;blockquote&gt;
By default content emitted using a @ block is automatically HTML encoded to better protect against XSS attack scenarios.&lt;/blockquote&gt;
That is something that I would expect from any view engine - encode by default. So far so good.&lt;br /&gt;
&lt;blockquote&gt;
create re-usable HTML helpers using a more declarative approach.&lt;/blockquote&gt;
I like this part &lt;b&gt;a lot (and I mean it)&lt;/b&gt;, I won't repeat what it is said in the post, but will explain how I can benefit from it.&lt;br /&gt;
Currently I create a whole bunch of HTML helpers (written in .cs file in C#) which look very ugly should you have more than just a couple of them.&lt;br /&gt;
It just becomes messy, hard to change, support and maintain. And the fact that C# generates HTML is very annoying for the same reasons. That should be the view's concern.&lt;br /&gt;
Now we have it - just create a file, mark its content as helper and it is available on all the pages. Beauty!&lt;br /&gt;
(&lt;b&gt;NOTE&lt;/b&gt;: actually after a bit more thinking we can do &lt;i&gt;similar&lt;/i&gt; in Spark or NHaml. The word &lt;i&gt;similar&lt;/i&gt; is used intentionally).&lt;br /&gt;
&lt;blockquote&gt;
One other useful (and extremely powerful) feature we are enabling with Razor is the ability to pass “inline template” parameters to helper methods.  These "inline templates" can contain both HTML and code, and can be invoked on-demand by helper methods.&lt;/blockquote&gt;
Previously we, generally, injected C# code into the template. Now we can do the other way around. Absolut power. Only God knows where it can bring us :) &lt;br /&gt;
&lt;h3&gt;



What I want from it&lt;/h3&gt;
One of the most frustrating things working with views in ASP.NET MVC is passing the values from a controller to a view. So the syntax that would read values from ViewData dictionary would the biggest time saver. Something along this:&lt;br /&gt;
&lt;code&gt;
@currentTime.ToString("d")
&lt;/code&gt;
&lt;br /&gt;
which would be equivalent for &lt;br /&gt;
&lt;code&gt;
((DateTime)ViewData["currentTime"]).ToString("d")
&lt;/code&gt;

So that we do not even need to provide the time of the object in the ViewData.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;


Summary&lt;/h3&gt;
The first impression is &lt;b&gt;very positive&lt;/b&gt;. Though I have some doubts in the syntax acceptance.&lt;br /&gt;
But I have no doubt that this engine is the way better than WebForms. Can't yet say it is better than NHaml and Spark (and would not be fair to say that as they solve a bit different problems).&lt;br /&gt;
This time I feel that &lt;b&gt;Microsoft has listened&lt;/b&gt; to the developers and produced something that really brings value, productivity, less frustration and more fun (and fun is the starting point of being a happy developer who can bring value to a company).&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_3276E6B4.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_3276E6B4.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_2EE4DDA5.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_2EE4DDA5.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_5DE7197C.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_5DE7197C.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_2EB52DE5.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_2EB52DE5.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_22B33DB1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_22B33DB1.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_78EFC2BD.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_78EFC2BD.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_775B2E84.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_775B2E84.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_5F279E5C.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_5F279E5C.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_1DACEC03.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_1DACEC03.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_43366964.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://weblogs.asp.net/blogs/scottgu/image_43366964.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-523599601392404934?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/loqwhNhgyEc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/523599601392404934/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/07/razor-aspnet-mvc-view-engine-first.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/523599601392404934?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/523599601392404934?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/loqwhNhgyEc/razor-aspnet-mvc-view-engine-first.html" title="Razor - ASP.NET MVC View Engine - first impression" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.approache.com/2010/07/razor-aspnet-mvc-view-engine-first.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AFQXo7fSp7ImA9WxFaGUk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-1033639674852607638</id><published>2010-07-02T08:54:00.002+10:00</published><updated>2010-07-24T15:35:10.405+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-24T15:35:10.405+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="firefox" /><category scheme="http://www.blogger.com/atom/ns#" term="ie" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><category scheme="http://www.blogger.com/atom/ns#" term="ibm" /><title>IBM is moving to Firefox</title><content type="html">The big corporations are usually very conservative and in order to change something inside the huge bureaucracy people have to go through many obstacles and justify their decisions.&lt;br /&gt;
I wonder how ones could justify that &lt;a href="http://www.sutor.com/c/2010/07/ibm-moving-to-firefox-as-default-browser/" target="_blank"&gt;IBM is moving to the Firefox web browser&lt;/a&gt;. Whatever the justification is I believe it the positive decision for the word-wide-web and normal people using the web.&lt;br /&gt;
Do the corporations still have a passion and not only the financial benefits? Maybe both: complementing each other? That would be an idealistic world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-1033639674852607638?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/owPW8iQIOOI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/1033639674852607638/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/07/ibm-is-moving-to-firefox.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/1033639674852607638?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/1033639674852607638?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/owPW8iQIOOI/ibm-is-moving-to-firefox.html" title="IBM is moving to Firefox" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/07/ibm-is-moving-to-firefox.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08ESHk6eyp7ImA9WxFaGUk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-524851359246155821</id><published>2010-07-01T09:31:00.002+10:00</published><updated>2010-07-24T15:36:49.713+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-24T15:36:49.713+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="standards" /><category scheme="http://www.blogger.com/atom/ns#" term="html" /><category scheme="http://www.blogger.com/atom/ns#" term="css" /><title>HTML5 and CSS3: Develop with Tomorrow's Standards Today</title><content type="html">If you are not living under the rock, you must know a lot of buzzing around HTML5 and CSS3.&lt;br /&gt;
And if you want to keep up with technologies so that you won’t become a grand daddy saying “I work with HTML1 and no CSS which works on all browsers”, then you DO HAVE to learn HTML5.&lt;br /&gt;
And there is one more opportunity for that, a great book from the great publisher (PragProg):&lt;br /&gt;
&lt;a href="http://pragprog.com/titles/bhh5/html5-and-css3" target="_blank"&gt;HTML5 and CSS3: Develop with Tomorrow's Standards Today&lt;/a&gt;&lt;br /&gt;
Looking at the excerpts, I do like it for now and will get it as soon as I will have finished some of my other readings.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-524851359246155821?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/_--hIxzJI_Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/524851359246155821/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/07/html5-and-css3-develop-with-tomorrow.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/524851359246155821?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/524851359246155821?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/_--hIxzJI_Q/html5-and-css3-develop-with-tomorrow.html" title="HTML5 and CSS3: Develop with Tomorrow's Standards Today" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/07/html5-and-css3-develop-with-tomorrow.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08HRHo_eSp7ImA9WxFaGUk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-121210869636928108</id><published>2010-06-19T21:22:00.003+10:00</published><updated>2010-07-24T15:37:15.441+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-24T15:37:15.441+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="agile" /><title>Agile Manifesto to Agile Principles</title><content type="html">A while ago I wrote about &lt;a href="http://blog.approache.com/2010/02/agile-manifesto-reminder.html"&gt;agile manifesto&lt;/a&gt; everybody should keep in mind (when they claim to be agily-ish). Now I want to quote the principle of the Agile. This is another reminder for my after reading the great book - &lt;a href="http://www.pragprog.com/news/the-agile-samurai"&gt;The Agile Samurai&lt;/a&gt;. Highly recommend it.&lt;br /&gt;
So here &lt;a href="http://agilemanifesto.org/principles.html" target="_blank"&gt;they are&lt;/a&gt;:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Our highest priority is to &lt;b&gt;satisfy the customer       &lt;/b&gt;through &lt;b&gt;early and continuous delivery&lt;/b&gt;      &lt;br /&gt;of valuable software.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Welcome changing requirements&lt;/b&gt;, even late in      &lt;br /&gt;development. Agile processes harness change for      &lt;br /&gt;the customer's competitive advantage.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Deliver working software frequently&lt;/b&gt;, from a      &lt;br /&gt;couple of weeks to a couple of months, with a      &lt;br /&gt;preference to the shorter timescale.&lt;/li&gt;
&lt;li&gt;Business people and developers must &lt;b&gt;work       &lt;br /&gt;together &lt;/b&gt;daily throughout the project.&lt;/li&gt;
&lt;li&gt;Build projects around &lt;b&gt;motivated individuals&lt;/b&gt;.      &lt;br /&gt;Give them the environment and support they need,      &lt;br /&gt;and &lt;b&gt;trust them &lt;/b&gt;to get the job done.&lt;/li&gt;
&lt;li&gt;The most efficient and effective method of     &lt;br /&gt;conveying information to and within a development      &lt;br /&gt;team is &lt;b&gt;face-to-face conversation&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Working software&lt;/b&gt; is the primary &lt;b&gt;measure of progress&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Agile processes promote &lt;b&gt;sustainable development&lt;/b&gt;.      &lt;br /&gt;The sponsors, developers, and users should be able      &lt;br /&gt;to maintain a constant pace indefinitely.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Continuous&lt;/b&gt; attention to &lt;b&gt;technical excellence&lt;/b&gt;      &lt;br /&gt;and good design enhances agility.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Simplicity&lt;/b&gt; - the art of maximizing the amount      &lt;br /&gt;of work not done - is essential.&lt;/li&gt;
&lt;li&gt;The best architectures, requirements, and designs     &lt;br /&gt;emerge from &lt;b&gt;self-organizing teams&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;At regular intervals, the team reflects on how     &lt;br /&gt;to &lt;b&gt;become more effective&lt;/b&gt;, then tunes and adjusts      &lt;br /&gt;its behavior accordingly.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-121210869636928108?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/q0qvu39hnrU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/121210869636928108/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/06/agile-manifesto-to-agile-principles.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/121210869636928108?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/121210869636928108?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/q0qvu39hnrU/agile-manifesto-to-agile-principles.html" title="Agile Manifesto to Agile Principles" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/06/agile-manifesto-to-agile-principles.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEHQHg9eCp7ImA9WxFXFkg.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-8373387537450431028</id><published>2010-05-24T09:33:00.001+10:00</published><updated>2010-05-24T09:33:51.660+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-24T09:33:51.660+10:00</app:edited><title>Quotes: Moving from ASP.NET MVC to Ruby On Rails</title><content type="html">&lt;p&gt;I am being reading the &lt;a href="http://www.infoq.com/articles/architecting-tekpub"&gt;Architecting TekPub - Moving from ASP.NET MVC to Ruby on Rail&lt;/a&gt;. There are number of interesting things in there that I would like to quote.&lt;/p&gt;  &lt;p&gt;First most notable is COST. ASP.NET MVC and thus Microsoft stack is pretty expensive and you cannot always justify the cost:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&lt;strong&gt;RB:&lt;/strong&gt; If the platform [ASP.NET MVC] was holding up fine, what prompted the change of architecture?&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;RC: &lt;/strong&gt;Money. We were enrolled in &lt;a href="http://www.microsoft.com/bizspark/"&gt;Microsoft BizSpark Program&lt;/a&gt; and it was great for getting off the ground, but projecting into the future we realized that everything - from our database down to our development environment would have to be paid for after 3 years. This might not be an issue for a large company, but when we sat down to assess what the bills would be - well let's just say that it was about 5 figures. We put our business hats on and &lt;strong&gt;tried to justify that cost - and we couldn't&lt;/strong&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Additionally the tooling around Ruby On Rails is just great:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&lt;strong&gt;RB:&lt;/strong&gt; Why did you choose Ruby on Rails?&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;RC: &lt;/strong&gt;It's what James and I both knew, and the plug-in story is very compelling. For instance - New Relic is a god-send. I don't worry about the server freaking out, and I can see the &amp;quot;choke points&amp;quot; of all the code. They also track the highest-occurring queries and will even suggest improvements.&lt;/p&gt;    &lt;p&gt;MongoMapper is an incredible data tool and MongoDB itself is faster than lightning. The Rails platform has matured to the point where it's almost &lt;strong&gt;difficult to justify *not* using it&lt;/strong&gt;. &lt;/p&gt;    &lt;p&gt;&lt;strong&gt;JA:&lt;/strong&gt; All the problems we had (licensing, testing, deployments) could have been overcome. We could have used workarounds, written our own deployment framework, etc. What is comes down to is that we both really enjoy working with Rails and we enjoy the Rails community and the tools and libraries available. One of the best parts about running the show is that we get to do what &lt;strong&gt;makes us happy&lt;/strong&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;And the benefits seem to be huge. I am looking at that from the perspective of a TDD developer:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&lt;strong&gt;RB:&lt;/strong&gt; What immediate benefits have you seen from the rewrite and the new design?&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;RC: &lt;/strong&gt;Immediate - the first thing people notice is the &lt;strong&gt;speed of it all&lt;/strong&gt;. They also notice a bit of a &amp;quot;tighter&amp;quot; design which we were allowed to focus on a bit more as &lt;strong&gt;the server-side stuff is really trivial&lt;/strong&gt;, to be honest.&lt;/p&gt;    &lt;p&gt;Not only that - but we've had some &lt;strong&gt;issues that we were able to iron out within seconds&lt;/strong&gt; as the deployment story is so very, very simple with Capistrano. Issue a fix and push - takes seconds.&lt;/p&gt;    &lt;p&gt;Our testing suite grew tremendously as well - Cucumber is a joy to use and lets you do some things that are a bit hard with ASP.NET MVC. For instance - &lt;strong&gt;testing PayPal's IPN posts are pretty tough with ASP&lt;/strong&gt;. It's possible to do - if you create a FormCollection and push it through - but couple that with the anti-forgery protection and the story gets a bit more difficult.&lt;/p&gt;    &lt;p&gt;With Rails/Cucumber/Webrat, &lt;strong&gt;it's a matter of filling out a hash and posting it…&lt;/strong&gt;.&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;JA:&lt;/strong&gt; The most immediate benefit has been the &lt;strong&gt;speed at which we are making changes&lt;/strong&gt; and &lt;strong&gt;pushing them up to production&lt;/strong&gt;. On the ASP.NET MVC site I would often write SQL scripts to handle complicated support requests, like changing someone's OpenID or combining accounts, but now I just spend the 30-60 minutes to write a couple of lines of Ruby and push it up.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;And of course I could not miss quoting the comparison of Microsoft-based technologies with Ruby-based:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&lt;strong&gt;RB:&lt;/strong&gt; How does your current testing methods compare to what you had on Microsoft?&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;RC:&lt;/strong&gt; 100% difference. It was a &lt;strong&gt;pain to test with the Microsoft&lt;/strong&gt; stuff and when you're poor and have 3 months until the money runs out, &lt;strong&gt;testing is something that you have a hard time justifying&lt;/strong&gt;...&amp;#160; [Then talking about ASP.NET MVC testing]… So I had some tests, but nothing to gives me the comfort I wanted. We did wrap the PayPal stuff in a ton of tests, you have to. When it comes to their API and I torched their sandbox environment for 3 straight days and STILL had issues rolling live.&amp;#160; &lt;/p&gt;    &lt;p&gt;&lt;strong&gt;JA:&lt;/strong&gt; &lt;strong&gt;Microsoft testing is always a fight, mainly because C# and static languages&lt;/strong&gt; don't lend themselves well to testing. It always feels like you are jumping through hoops when testing on .NET. That being said the SpecFlow framework on .NET does look very promising, but I doubt it can overcome all of the drawbacks of testing in .NET.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;And this is probably really what it means to be Agile:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&lt;strong&gt;RB:&lt;/strong&gt; What lessons or takeaways have you gotten from a total redesign?&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;RC: &lt;/strong&gt;None really - I think both James and I knew that we'd hit a point where we would need to adjust and rewrite…&lt;/p&gt;    &lt;p&gt;We were lucky in that the idea took hold - we then moved into &amp;quot;&lt;strong&gt;OK let's plan for the next 3-5 years and go into controlled-growth mode&lt;/strong&gt;&amp;quot; - which is where we are now. We &lt;strong&gt;don't want to be huge, we don't want IT people or a group of developers who work on stuff&lt;/strong&gt;. We want to &lt;strong&gt;do it ourselves and stay small&lt;/strong&gt; - focusing on the idea that got us here.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;And the lessons learned are just a ton of satisfaction:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&lt;strong&gt;RB:&lt;/strong&gt; Do you see any weaknesses to the current architecture?&amp;#160; What would you change if you were starting over again today?&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;RC:&lt;/strong&gt; Nothing on my end - I love it all. It's weird for me - I've been a Microsoft person for a long time but putting on my business hat... well it just doesn't make any sense at all for us. I like the idea that scaling comes at the cost of hardware&amp;#160; - and it will be a really long time that we'll need any. Our servers are essentially &amp;quot;liquid&amp;quot; and we can buff as needed. Can't do that with the Microsoft boxes (from what I know) and if you try to latch on separate machines, you end up with a big bill. &lt;/p&gt;    &lt;p&gt;&lt;strong&gt;JA:&lt;/strong&gt; The only change I would like to the current architecture is to break out MongoDB from our single server, it makes sense to run MongoDB in a pair whenever possible but with replica pairs being depreciated it makes sense for us to wait on the MongoDB team to develop their new pairing strategy and start with that. The cost of an addition two VMs and the fact that everything is running fine on our single server also deters us from doing this right now.&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-8373387537450431028?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/9aLk90X0CWE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/8373387537450431028/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/05/quotes-moving-from-aspnet-mvc-to-ruby.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/8373387537450431028?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/8373387537450431028?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/9aLk90X0CWE/quotes-moving-from-aspnet-mvc-to-ruby.html" title="Quotes: Moving from ASP.NET MVC to Ruby On Rails" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/05/quotes-moving-from-aspnet-mvc-to-ruby.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04HRnk4fCp7ImA9WxFaGUk.&quot;"><id>tag:blogger.com,1999:blog-6711253058798651435.post-2274685427435547784</id><published>2010-04-20T20:55:00.002+10:00</published><updated>2010-07-24T15:38:57.734+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-24T15:38:57.734+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="standards" /><category scheme="http://www.blogger.com/atom/ns#" term="html" /><category scheme="http://www.blogger.com/atom/ns#" term="css" /><title>HTML 5 Readiness</title><content type="html">A friend of mine just sent me the link:&amp;nbsp;&lt;a href="http://html5readiness.com/"&gt;HTML 5 Readiness&lt;/a&gt;.&lt;br /&gt;
Check it out - it shows browsers support for HTML5.&lt;br /&gt;
&lt;br /&gt;
As always Internet Explorer is far behind. Chrome is doing very, very well.&lt;br /&gt;
&lt;br /&gt;
And one more link (not really related) for myself as a note: &lt;a href="http://everytimezone.com/"&gt;visual time zone representation&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6711253058798651435-2274685427435547784?l=blog.approache.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DmitriyNagirnyak/~4/apVn7EE2wwY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.approache.com/feeds/2274685427435547784/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.approache.com/2010/04/html-5-readiness.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/2274685427435547784?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6711253058798651435/posts/default/2274685427435547784?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DmitriyNagirnyak/~3/apVn7EE2wwY/html-5-readiness.html" title="HTML 5 Readiness" /><author><name>Dmytrii Nagirniak</name><uri>https://profiles.google.com/116807208912177719748</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-_LswLlXfFNw/AAAAAAAAAAI/AAAAAAAAAAA/I6q1ysqSzXM/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.approache.com/2010/04/html-5-readiness.html</feedburner:origLink></entry></feed>

