<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3584368891378271325</id><updated>2012-01-04T10:21:10.877-08:00</updated><category term='ruby'/><category term='rants'/><category term='code'/><category term='general'/><category term='tips'/><category term='*nix gotchas'/><title type='text'>Apes Strike Back!</title><subtitle type='html'>fightin' against complexity since 1985</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-1350480291903613823</id><published>2009-09-04T16:47:00.001-07:00</published><updated>2009-09-04T17:06:46.905-07:00</updated><title type='text'>Announcing Grate Handle - A Ruby Client for Accessing GoGrid API</title><content type='html'>Some time ago I've &lt;a href="http://kirillishanov.blogspot.com/2009/08/accessing-gogrid-api-from-ruby.html"&gt;posted about&lt;/a&gt; a &lt;a href="http://gist.github.com/175106"&gt;small hack&lt;/a&gt; which allows to use the data, which comes via GoGrid's API requests.&lt;br /&gt;&lt;br /&gt;After a couple of days playing with this snippet I've decided to build a GoGrid-specific Ruby client. As a result, &lt;code&gt;grate-handle&lt;/code&gt; gem was born.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.cast-iron-grate.com/cig22/handle/files/handle%20with%20grate.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 550px; height: 367px;" src="http://www.cast-iron-grate.com/cig22/handle/files/handle%20with%20grate.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In addition to the library &lt;code&gt;grate-handle&lt;/code&gt; ships with a GoGrid's CLI-client. This client was inspired mostly by the &lt;a href="github.com/novel/gg"&gt;gg-tools&lt;/a&gt; - a Python library and a set of CLI tools which I definitely recommend to check.&lt;br /&gt;&lt;br /&gt;Right now &lt;code&gt;grate-handle&lt;/code&gt; is a very tiny lib which only allows to list servers, images, passwords and ips in an easy to view and easy to use in combination with other *nix tools via piping. Project sources and README can be found at &lt;a href="http://github.com/kylichuku/grate-handle"&gt;GitHub&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-1350480291903613823?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/1350480291903613823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/09/announcing-grate-handle-ruby-client-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/1350480291903613823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/1350480291903613823'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/09/announcing-grate-handle-ruby-client-for.html' title='Announcing Grate Handle - A Ruby Client for Accessing GoGrid API'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-6945562812438387838</id><published>2009-09-01T04:31:00.000-07:00</published><updated>2009-09-04T14:32:46.922-07:00</updated><title type='text'>Generate URL params with Javascript (using associative arrays)</title><content type='html'>Javascript is fun. Really fun. So hugely mindbogginly fun, you really won't believe how fun it is. Well, for the person who works with it day in and day out it might be boring and nothing can surprise the mature Javascript'er. But for such n00b as me, it's often acts as an eyeopener, when I occasionally need to write a chunk of code in this language.&lt;br /&gt;&lt;br /&gt;The same thing happened today: I needed to generate an URL with a lot of params in it (for example, in situation with "The Blue Oyster Bar" our heroes may use an URL like this: &lt;code&gt;http://ip.ad.d.r:port/callme?phone=911&amp;reason=epic_fail&amp;address=the_blue_oyster_bar&lt;/code&gt;. The names of all params were given manually, the values came from different sources (values inside input fields, ids of elements and so on).&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/tdbt-sx5MDc&amp;hl=ru&amp;fs=1&amp;"&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/tdbt-sx5MDc&amp;hl=ru&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;The straightforward approach (to generate a string using concatenation, like &lt;code&gt;'reason=' + $('#emergency-phone-number')+ '&amp;reason=' ... &lt;/code&gt;) looked like not the true gangsta's way, so I've decided to apply my Ruby-fu and hashes-djitsu to complete this kata. In the Ruby, it can be done using a simple one-liner:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:ruby"&gt;&lt;br /&gt;params = ({ 'phone' =&gt; '911',&lt;br /&gt;            'reason' =&gt; 'epic_fail',&lt;br /&gt;            'address' =&gt; 'the_blue_oyster_bar'&lt;br /&gt;          }).map { |k, v| "#{k}=#{v}" }.join('&amp;')&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Wait, according to the beginning of this post and the videos of &lt;a href="http://www.crockford.com/javascript/"&gt;this bearded guy&lt;/a&gt;, Javascript is an uber cool. Let's see how this rubyish stuff can be done using Javascript:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:js"&gt;&lt;br /&gt;var kylichuku = {&lt;br /&gt;    // Based on jQuery.map, which works for arrays&lt;br /&gt;    map: function(obj, callback) {&lt;br /&gt;        var ret = [];&lt;br /&gt;&lt;br /&gt;        for (prop in obj) {&lt;br /&gt;            var value = callback(prop, obj[prop]);&lt;br /&gt;            ret[ret.length] = value;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return ret.concat.apply([], ret);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And now, we're ready to use the same approach, as was used in Ruby version, but in Javascript:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:js"&gt;&lt;br /&gt;var params = kylichuku.map({ 'phone': '911',&lt;br /&gt;                             'reason': 'epic_fail',&lt;br /&gt;                             'address': 'the_blue_oyster_bar'&lt;br /&gt;                           }, function(k, v) { return k + '=' + v; }).join('&amp;');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Hi-ya!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-6945562812438387838?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/6945562812438387838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/09/generate-url-params-with-javascript.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/6945562812438387838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/6945562812438387838'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/09/generate-url-params-with-javascript.html' title='Generate URL params with Javascript (using associative arrays)'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-1913183189806644189</id><published>2009-08-25T14:46:00.000-07:00</published><updated>2009-08-25T16:11:42.535-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Accessing GoGrid API from Ruby</title><content type='html'>For the last several months I work on the project which utilize &lt;a href="http://www.gogrid.com"&gt;GoGrid&lt;/a&gt;. For the programmatic access they provide &lt;a href="http://wiki.gogrid.com/wiki/index.php/API"&gt;a simple REST API&lt;/a&gt; to manipulate servers, passwords and so on.&lt;br /&gt;&lt;br /&gt;A couple of days ago I've decided to implement a thin ruby wrapper around this API, which will allow me to manipulate the data, which can be retrieved via API call the same way that I manipulate ruby object. In other words, I wanted to restore the GoGrid's object model (object and relations between them) from response and map this model to Ruby object.&lt;br /&gt;&lt;br /&gt;As a "true REST shop" GoGrid returns the response in 3 available formats: XML, JSON or CSV. The CSV was rejected in a moment, due to the CSV's structure in response is flat and it's very hard to restore object relationships from it.&lt;br /&gt;&lt;br /&gt;Next choice was XML:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/175103.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The XML response was easy to understand and parse, but when it comes to restoring an object model from it there are 3 possible options:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Implement mapping manually (declare classes with all attributes coming from response, and parse XML to assign appropriate data to attributes). This approach seemed boring and required a lot of boilerplate code, which doesn't satisfies the "thinness" requirement for wrapper.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Implement mapping using Ruby metaprogramming-fu (parse an XML and based on this information generate classes with appropriate attributes, than instantiate instances of these classes fed with data from XML). This approach is more advanced than previous one, but the complexity scared me. I wanted effortless solution, not the hard one.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Use on of the existing XML-mappers. After looking at &lt;a href="http://xml-mapping.rubyforge.org/"&gt;several&lt;/a&gt; &lt;a href="http://railstips.org/2008/11/17/happymapper-making-xml-fun-again"&gt;resembling&lt;/a&gt; &lt;a href="http://raa.ruby-lang.org/project/xml-mapping/"&gt;mappers&lt;/a&gt; I've come to the conclusion, that all these mappers will require some non-trivial customizations, due to XML structure relies on "object" attributes.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Looks like the natural lazyness, dislike of XML and fear against complex things did their job. I've finally chosen JSON as a right way to dig deeper:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/175104.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Using JSON.parse from &lt;a href="http://json.rubyforge.org"&gt;Ruby's implementation of JSON&lt;/a&gt; it is possible to get Ruby objects (hashes, arrays, strings, booleans and numbers) from this response. Half of what I needed. But an access to the needed attribute via hash syntax (like &lt;code&gt;resp['list'][0]['server']['name']&lt;/code&gt;) quickly became annoying, luckily a short monkey patch to Hash class made this action more natural, via dot-notation (like resp.list[0].server.name)&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/175106.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Yes, I know, monkey patching is baaaad. Moreover, this patch may look very fragile and error-prone, but for the GoGrid's API responses I haven't seen a lot of problems (the camelCased keys and 'id' as a key are easy to fix).&lt;br /&gt;&lt;br /&gt;With this patch it becomes easy to do the following tricks:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/175107.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;where @gogrid_client is an object which constructs the appropriate URL, send the 'get' request to GoGrid and returns the JSON response. The implementation was taken from &lt;a href="http://wiki.gogrid.com/wiki/index.php/API:Ruby_API_Developer_Home"&gt;GoGrid Ruby Client example&lt;/a&gt;. Easy-peasy-lemon-squeezy :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-1913183189806644189?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/1913183189806644189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/08/accessing-gogrid-api-from-ruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/1913183189806644189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/1913183189806644189'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/08/accessing-gogrid-api-from-ruby.html' title='Accessing GoGrid API from Ruby'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-5526355711110970454</id><published>2009-07-12T08:42:00.001-07:00</published><updated>2009-07-12T09:02:55.367-07:00</updated><title type='text'>VirtualBox Time Synchronization with Guest OS Issue</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.atomictimeclock.com/images/clientserver200w.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 184px;" src="http://www.atomictimeclock.com/images/clientserver200w.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Due to constant issues with Ubuntu installation &amp; proper work on my Dell m1330 XPS laptop, I'm using the Windows Vista with Ubuntu 9.04 installed inside &lt;a href="http://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt; (2.2.4 at the time of writing this post). VirtualBox kicks ass due to its simplicity as a virtualization software, but today I've found a tricky issue with time synchronization between host and guest operating systems.&lt;br /&gt;&lt;br /&gt;Not sure what enables time synchronization (looks like it appeared after installing guest additions to Ubuntu), but I've found that the time in the host Windows OS (which was setup manually a long time ago) is the same as an output of &lt;code&gt;date&lt;/code&gt; command in Ubuntu. The time was about 8 minutes before the real time (which was returned by googling for &lt;code&gt;time Moscow&lt;/code&gt;), so I decided to synchronize the time in Ubuntu using:&lt;br /&gt;&lt;code&gt;ntpdate pool.ntp.org&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The weird thing was that the time wasn't synchronized in Ubuntu due to synchronization with host OS, so the problem was solved only by synchronizing the time in host OS manually. Looks like the right way of doing time synchronization is to configure it in host OS and let the VirtualBox do it automatically for all guest OSs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-5526355711110970454?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/5526355711110970454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/07/virtualbox-time-synchronization-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/5526355711110970454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/5526355711110970454'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/07/virtualbox-time-synchronization-with.html' title='VirtualBox Time Synchronization with Guest OS Issue'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-3846074685605665504</id><published>2009-06-08T12:59:00.000-07:00</published><updated>2009-06-08T13:24:12.333-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Add Pronunciation Capabilities to lingvo.yandex.ru</title><content type='html'>There is a &lt;a href="http://lingvo.yandex.ru"&gt;great web service&lt;/a&gt; for Russians who want to extend their English vocabulary. The functionality includes translation of English words, list of synonyms, usage examples, etc.&lt;br /&gt;&lt;br /&gt;But there is one thing that bothers me a lot - there is a pronunciation transcript of a word but there is no audio file attached. This feature presents in the &lt;a href="http://www.lingvo.ru"&gt;desktop version of Lingvo&lt;/a&gt;, but for the free web service you'll need to search for an alternative solution.&lt;br /&gt;&lt;br /&gt;After some googling I've found the site called &lt;a href="http://www.howjsay.com"&gt;howjsay.com&lt;/a&gt;, which looked like a perfect candidate to fill the gap between translation and pronunciation. There's only one little thing left: to show the "pronunciation icon" (which should point to howjsay.com) on the translate results for each particular words on the lingvo.yandex.ru.&lt;br /&gt;&lt;br /&gt;Luckily, I was aware of &lt;a href="http://en.wikipedia.org/wiki/Greasemonkey"&gt;Greasemonkey&lt;/a&gt; - a great Firefox extension which allows to save and execute user script for specified sites. With some basic knowledge of Javascript I was able to produce the following solution to the problem:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/126034.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;The script is pretty straightforward:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Find the most notable appearence of the translated word in the translation results&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add an "sound icon" which points to the howjsay.com for the pronunciation of this particular word&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;The script is &lt;a href="http://userscripts.org/scripts/show/51055"&gt; available at userscripts.org&lt;/a&gt;. Hope it will make the usage of lingvo.yandex.ru a little bit pleasant :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-3846074685605665504?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/3846074685605665504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/06/add-pronunciation-capabilities-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/3846074685605665504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/3846074685605665504'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/06/add-pronunciation-capabilities-to.html' title='Add Pronunciation Capabilities to lingvo.yandex.ru'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-4027304345259787590</id><published>2009-06-04T14:37:00.000-07:00</published><updated>2009-06-04T15:16:23.836-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Dummy IP Address Validation in Ruby</title><content type='html'>Today I've spent some time playing with my own implementation of &lt;code&gt;ipcalc&lt;/code&gt; utility (just for the purposes to refresh the IP knowledge). The first step was obvious - verify that given IP address was valid.&lt;br /&gt;&lt;br /&gt;Regex would be too boring solution so I decided to come up with more "semantic" one with next possible steps (the algorithm does handles the situation when a subnetwork specified):&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Verify that given argument is a String&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Pick out decimal values of bytes from it&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Verify that the number of grabbed bytes is 4&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Verify that each decimal value is less than 256 and more than 0&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;As a result I've come up with the following method:&lt;br /&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/123870.js"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Personally for me this implementation is good enough: concise and kinda of elegant. But the gut feeling is that it's not the way how this chunk should be written, because:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;It utilizes not the most obvious usage of &lt;code&gt;reduce&lt;/code&gt; method&lt;/li&gt;&lt;br /&gt;&lt;li&gt;To verify that the number is actually a decimal representation of byte I use ranges instead of numeric comparison, which can be confusing&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It may be not so easy to catch what exactly the method returns due to complex last line&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Looks like this implementation introduces more problem than solves. The moral of the story is easy: &lt;strong&gt;always search for the balance between the conciseness and readability.&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-4027304345259787590?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/4027304345259787590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/06/dummy-ip-address-validation-in-ruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/4027304345259787590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/4027304345259787590'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/06/dummy-ip-address-validation-in-ruby.html' title='Dummy IP Address Validation in Ruby'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-3125994638894205536</id><published>2009-06-04T10:21:00.000-07:00</published><updated>2009-06-04T10:28:41.376-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tips'/><title type='text'>Google Way to look for the current time</title><content type='html'>If you are like me work with different customers/colleagues in different timezones and too lazy to setup up a desktop widget/browser plugin/whatsoever to see the current time in their location then google for the location with prefix &lt;code&gt;time&lt;/code&gt;, for example:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;time fremont california&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Bonus&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;The same trick can be done with &lt;code&gt;weather&lt;/code&gt; prefix to get the weather in specific location embedded in search results.&lt;br /&gt;&lt;br /&gt;Happy googling!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-3125994638894205536?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/3125994638894205536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/06/google-way-to-look-for-current-time.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/3125994638894205536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/3125994638894205536'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/06/google-way-to-look-for-current-time.html' title='Google Way to look for the current time'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-554034277683348826</id><published>2009-05-31T12:46:00.000-07:00</published><updated>2009-05-31T13:09:18.331-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='*nix gotchas'/><title type='text'>Reloading Service's Configuration Without Restarting It</title><content type='html'>Every time when I needed to reload the configuration of some service on my Ubuntu box I used the not very convenient approach of restarting the service (for example, using the &lt;code&gt;/etc/init.d/SERVICE_NAME restart&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Today the Holy Grail was found :) It turns out that the &lt;code&gt;kill&lt;/code&gt; command can be used to reload the configuration without restarting the service, namely&lt;br /&gt;&lt;br /&gt;&lt;code&gt;kill -1 `pgrep SERVICE_NAME`&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The explanation that is listed in man page for the kill command says that &lt;code&gt;-1&lt;/code&gt; signal stands for the &lt;code&gt;HUP&lt;/code&gt; signal that does exactly what I needed. Note that all the signals that can be sent to kill command can be listed using&lt;br /&gt;&lt;br /&gt;&lt;code&gt;kill -l&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;There are so many hidden gems that can be found in man pages :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-554034277683348826?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/554034277683348826/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/05/reloading-services-configuration.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/554034277683348826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/554034277683348826'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/05/reloading-services-configuration.html' title='Reloading Service&apos;s Configuration Without Restarting It'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-4502432975099460410</id><published>2009-05-26T11:51:00.000-07:00</published><updated>2009-05-26T12:44:28.290-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rants'/><title type='text'>People-oriented Software Development Methodology</title><content type='html'>Software Development methodologies appears very often. Different flaws of agile is especially a hot topic for last 10 years or so. And every day I see zealots (not so cool as StarCraft ones :) ) of different methodologies.&lt;br /&gt;&lt;br /&gt;I was such kind of zealot too. Tried to read and watch everything tagged with "Agile", then completed a "Certified Scrum Master" course led by &lt;a href="http://www.controlchaos.com/"&gt;Ken Schwaber&lt;/a&gt; (great guy actually), and so on.&lt;br /&gt;&lt;br /&gt;But during the years the best thing that happened personally with me is that I've understood that no single methodology is applicable for everything. Moreover, no single methodology works for &lt;em&gt;everyone&lt;/em&gt;. Each methodology gives some set of rules and not every personality can/will follow this rules for different reasons.&lt;br /&gt;&lt;br /&gt;For a long time I tried to find the minimalistic "methodology" that will satisfy the needs of everyone on the project (the word "methodology" means that it's impossible). I failed for obvious reasons. Than I found 2 rules ("rules" leads to the fail too, but not so scared as "methodology") that work in the most cases:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Don't be an asshole&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Collaborate all the f**king time&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Well, pretty obvious. Can be applied to most of the existing methodologies. The real power of this manifesto that this two postulates is the universal answer to most of the crap that is sold by different methodologies. For example:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Collaborate all the f**king time with customer and your team to find out the most appropriate workflow of the project that everyone agrees on. 2 weeks iterations, 4 week sprints, 3 months cycles, no iterations at all - whatever if it satisfy customer needs and people like it.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Don't be an asshole trying to convince people to use some particular tools to achieve the result. Not everyone (especially from the customer's management) likes to use Jira, git is not for everyone (no matter how sexy it is for engineers). For each particular problem agree on the set of tools that will be an enough minimum to complete the project and not annoy too much&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Collaborate all the f**king time with peers to give everyone the sense of what you're doing. Don't fight alone with the problem and don't keep the secrets of great solutions that you've invented. And don't be an asshole to disturb everyone with stupid questions that you can google yourself in several minutes&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;What I'm trying to say is that there is &lt;strong&gt;no a single methodology that works everywhere and for everyone&lt;/strong&gt;. People should drive the process and modify it when necessary and for each particular situation find the most comfortable solution, no matter what methodology says. In every situation people should &lt;strong&gt;solve the problems, not follow the rules&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-4502432975099460410?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/4502432975099460410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/05/people-oriented-software-development.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/4502432975099460410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/4502432975099460410'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/05/people-oriented-software-development.html' title='People-oriented Software Development Methodology'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3584368891378271325.post-5976518500661182676</id><published>2009-05-26T11:42:00.000-07:00</published><updated>2009-05-26T11:50:15.053-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='general'/><title type='text'>Lost and Found Department is open!</title><content type='html'>Just another "coding monkey blog" was born today. Just need a place where can I put something that I found interesting (not links, but solutions from day-to-day work) that is too technical/geeky to put in my &lt;a href="http://kylichuku.blogspot.com"&gt;personal Russian blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Stay tuned :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3584368891378271325-5976518500661182676?l=kirillishanov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kirillishanov.blogspot.com/feeds/5976518500661182676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://kirillishanov.blogspot.com/2009/05/lost-and-found-department-is-open.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/5976518500661182676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3584368891378271325/posts/default/5976518500661182676'/><link rel='alternate' type='text/html' href='http://kirillishanov.blogspot.com/2009/05/lost-and-found-department-is-open.html' title='Lost and Found Department is open!'/><author><name>Кирилл Ишанов</name><uri>http://www.blogger.com/profile/14008911434054389383</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_jKbDHnfcg9c/SqGH0Gft88I/AAAAAAAAAwA/oa044Dhqv8I/S220/p7190191.jpg'/></author><thr:total>0</thr:total></entry></feed>
