Tuesday, August 13, 2013

How Ruby keyword arguments work with hashes

So, Ruby 2.0 had finally embraced keyword (aka named) parameters. Maybe somewhen in future this could suppress usage of opts={} function arguments. This feature had collected quite a few reviews, but reviewers tend to miss one nice pattern of using the feature.

The fact is that hash supplied to a function with only named arguments will match against a particular arguments and overwrite their value. See an example below, plus some additional cases.

Monday, August 12, 2013

Naïve AB with cookies.

So recently I had to run a smoke test for performance optimizations I made in a complex Rails app. First tool I thought of was AB and it all went fine except the fact I it caught me with cookies once again. To avoid stepping onto the same issue again and again, here's a small command line tool that runs AB with all the supplied options plus cookies extracted from a given cookie.txt.
Sample usage: ./cookie-ab.rb cookies.txt http://localhost:3000/

Tuesday, January 1, 2013

High performance messaging

A very solid read about a network performance and high-performance messaging in IP networks: "Topics in High-Performance Messaging".

Wednesday, December 26, 2012

Never underestimate the power of a standard libraries

Recently I started digging into Clojure to try and shift from a mainstream Ruby/Rails concentrated software development and after spending some time with it I must admin I like it pretty much. However there are some rough edges I never wanted to stumble upon. Not surprisingly, most noticeable one is Java. Clojure is very cool language built with a clear design decisions by a bunch of incredible engineers, but it all ends when you need to operate with an outer world. Sockets, data input/output, almost anything related to interoperations with something outside your program is Java. And Java it is with overly verbose concepts, ugly naming conventions and so forth. As a recent example, here's a trivial code that should handle reading lines from a given client socket:
 (defn client-handler [socket]
   (let [is (.getInputStream socket)
         isr (java.io.InputStreamReader. is)
         bir (java.io.BufferedReader. isr)]
     (loop [in-command (.readLine bir)]
       (println in-command)
       (recur (.readLine bir)))))
Beautiful, isn't it? Ok, it isn't. However, as I already said Clojure was made by a very smart people so accidentaly I discovered clojure.java.io namespace with a handful of functions able to hide this bloody mess. Check this:
 (defn client-handler [socket]
   (with-open [input-stream (io/input-stream socket)]
     (let [reader (io/reader input-stream)]
       (doseq [line (line-seq reader)]
         (println line)))))  
Much better now with dirty details hidden behind the IOFactory protocol. It contains implementation of readers and input streams handling specialized for Strings, URIs and Sockets seamlessly converting them into BufferedReader instances. Also check out the line-seq code, it produces a lazy sequence of strings from a given reader. Perfect feature to replace the ugly loop/recur block from the first snippet. So once again, read that manual and/or code.

Tuesday, December 4, 2012

Searching for a string in git history

Whenever you'll need to find an occurence of string in a Git repository, use following command:
git rev-list --all | (while read revision; do git grep -F 'pattern' $revision; done)

Thursday, November 27, 2008

Method overriding check.

Following snippet might help you, if you need to know, wheter method was overriden in given class, or not:

class Foo
def bar
"bar"
end
end

class Qux < Foo
end

class Baz < Foo
def bar
"Baz::bar"
end
end
[Foo, Baz, Qux].map{|klass| klass.instance_methods(false).include?("bar") }
=> [true, true, false]

Calling instance_methods or public_methods with single false argument will give you a list of methods defined straight in given class (or class of given object, in case of public_methods).

Of course it could be wrapped up in a more clean way:

class Class
def defines_method?(name)
self.instance_methods(false).include?(name)
end
end

Monday, November 17, 2008

The Worst Nightmare.

The worst coder's nightmare is to spot his code on The Daily WTF.

Wednesday, November 12, 2008

Emacs is a coding blogger's friend.

My dear coding addict, once you've made some code snippet you'd like to share. You've posted it, and saw that formatting is crap. Literally, there's no formatting. Thanks G-d, you've read W3C papers and know, that there is a <pre> tag, so you wrap your beloved snippet with tags, look at result and see that there's no highlights. Now it's time to google.
Google will show you several results, which you could even like and use. But the point is that most popular solutions for this task require some massive JavaScript code and serious regular expression job to be done at client side, to replace monotone text with all that fancy coloured pieces. Don't know what about you, but I don't like such solutions.
There's also several specific off-line libraries to do highlighting for you, which I don't like either.
What to do? The answer is simple: DRY, why repeat job already been done with your favourite text editor? Go on and install htmlize.el (for me, Debian addict, it worked by typing sudo apt-get install emacs-goodies-el). This piece of magic extracts current colour scheme from your system and creates an HTML code with appropriate highlights. Having a code snippet in buffer, just type M-x htmlize-buffer (or htmlize-region if you want to htmlize just a piece of buffer) and Emacs will pop up a buffer with 100% pure, ready-to-use HTML code, with separate CSS and all that fancy things. If you, just as I do, plan to paste lots of code, simply put code styles to your blog template and that's it. After that you'll just need to copy-and-paste HTML.
God bless Emacs!

Tuesday, November 11, 2008

On Ruby and scopes, again.

Yes, this is definitely another boring post about Ruby scopes. I'm not sure I should go through all that known-to-everyone stuff, but try add a bit a weirdness to usual talks on this topic.

So, the point: sometimes you really do need to mix scopes of two classes together. Well, ok, maybe you don't, but i did once. The situation was like this:

class DeepThought

def seven_and_a_half_millions_years_of_thinking_result
42
end

def thinking_process(&blk)
@tell_me_later = blk
end

def think(asker)
asker.instance_eval &@tell_me_later
end

end

class BogusAsker
def question
"What is the Aswer to Life, the Universe, and Everything"
end
end

dt = DeepThought.new
dt.thinking_process { puts "The question:", question, "The answer: ", seven_and_a_half_millions_years_of_thinking_result }
dt.think(BogusAsker.new) # Epic fail. You can't access #seven_and_a_half_millions_years_of_thinking_result from BogusAsker.


As a result of solving this puzzle, ScopeBlender was born. What it does? It just takes a list of objects to be used as evaluation scopes, and evals given block within itself. The most important (did I just said that?) part is method_missing. It catches all method calls made from given block, and make a sequential lookup for object responding to this method. Crappy, creepy, simple.


module ScopeBlender
class Blender
def initialize(*scopes)
@__scopes__ = scopes
end

def blend(&blk)
self.instance_eval &blk
end

def method_missing(method, *args)
target_scope = @__scopes__.find{|s| s.respond_to?(method) }
return target_scope.send(method, *args) if target_scope
super
end
end


def self.with_blended_scope(*list, &blk)
Blender.new(*list).blend(&blk)
end
end

ScopeBlender::with_blended_scope("123456", -666) do
puts length
puts abs
end

Thursday, July 3, 2008

First post.

Very sad story about wasted time, xmpp4r and Jabber. When you use variables to build JID, never, never ever forget to strip them. If you are sure about it -- check twice. Using non-stripped variables (i.e. with \n in the end) in JIDs can cause silent fail, without any exceptions or other such nice and friendly things.

Due to this i've spent couple of hours reading through a dozen lines of code, including per-char comparsion of identifiers.