Rocu.de

Love, caffeine and omlette

Month: December 2012

My tool belt

Toolbelt
Toolbelt Picture from brockamer. Licensed under CC BY 2.0

As a web developer you need a bunch of good tools. I know that tools are something very personal, but maybe my choice contains some inspiration for your toolbelt.

Mac OS X Software

1Password

1Password Login Window

1Password is my password manager of choice. Why a password manager? Well its the only realistic way of having a different password for every website. 1Password also hold password to servers, my serial numbers + my credit card info etc.

Apart from being more secure it also makes the whole password business much more user-friendly, fills passwords in and submits forms if I want.

There is one downside however: I don't know my passwords any more. When I am at my friends computer I have to look them up in the iPad version of 1Password.

Alfred

Alfred is a marvelous application launcher. I tried Quicksilver and Launchbar but both are not as nice as Alfred.

Alfred

Apart of the use as app launcher, Alfred is a perfect keyboard interface for iTunes and my clipboard history.

Arq

Arq

Backing up ones data is important. I use TimeMachine and Arq. Arq back's
up your Data to Amazon S3 or Amazon Glacier. It encrypts the data,
before it is uploaded.

Bartender

I use a ridicoulus amount of menu bar apps. Bartender is a nice programm, that helps you to organize them.

Bartender

BetterSnapTool

BetterSnapTool

BetterSnapTool manages my windows in an intelligent way. With soon simple grips on the keyboard: I can move them from one screen to another, or arrange them in split view to the left and the right side.

Chrome

Google Chrome

One of my most important tools is Chrome. Not only is it a nifty, fast and clutterfree browser, but also a perfect tool for web developers.

The developer tools are right build in and contain everything that I need on a daily basis: JS Console, network activity, debugging facilities for CSS and some basic checks for front end performance.

iTerm 2

ITerm2

I spend quite a lot of time in the terminal. I use iTerm instead of the build in Mac OS terminal. I like the split-pane view, Tmux-integration and that it just kind of feels much better then the normal build in terminal.

MacVim

Mvim

For reading code or refactorings I prefer to use an IDE - but whenever I create something new I use MacVim.

It was quite hard to get used to it - but after a few month it just feels right 🙂

PHPStorm / Rubymine

PHPStorm

A year ago i used PHPStorm. After my switch to Ruby I use its brother
RubyMine now.

RubyMine is quite expensive and you have to get a new license on a
yearly basis - but its definetly worth every penny.

Pomodoro

Pomodoro

I am a big believer in the Pomodoro Technique. When I started, I used a tomato-shaped kitchen timer. But it constantly fell of my desk and the ticking annoyed my environment. Thats why I choose to use the little app with the name "Pomodoro". Its gorgeous. It has Things Integration and lives in my menu bar.

I also like that you can write little Apple scripts. Currently after
every pomodoro my Mac locks, to ensure that I don't cheat and take the
break.

Reggy

Reggy

Reggy is a small program that helps you create and test-drive regular expressions. Its quite simple and saves a lot of time. I can't imagine how to create complicated regular expressions without rapid feedback any more.

Some of my colleagues had a look at Reggy and instantly wanted this kind of instant feedback for regexe's as well. If you don't have a Mac an alternative might be Rubular

Sparrow

I hate email! They suck the energy out of me. I tried many different clients over the years: Mail, Entourage, Postbox, Thunderbird, GMail. They really don't work for me.

Sparrow

Recently I discovered Sparrow. I like it because it makes email as convenient as using Twitter. You can reply fast and it resides in your menu bar and does not use space in the dock.

What I also like is that it automatically uploads attachments to dropbox and I dont have to send 10 MB big attachment bombs through the internet.

I still don't like emails.. But they are a lot nicer now..

TextExpander

TextExpander

TextExpander stores snippets of texts that i use over and over again. For example boilerplate code that I have to write in PHP to create tests, or email signatures, Lorem Ipsum snippets and such..

TextExpander syncs itself via Dropbox, so that you can share your snippets between different computers.

Things

Tasks in Things

Things is a pretty neat store of the stuff that pops into my mind, while I am working on hard problems.

I can revisit this stuff later and continue to concentrate on the task at hand.

It allows me to plan Tasks, schedule them, create little projects.

Since the last weekend I also use Things Cloud beta, to syncronize my tasks between my Imac at work and my Macbook Pro at home.

Sequel Pro

Sequel Pro

I already recommended Sequel Pro in the past a while ago. In the meantime it even got better.

If you work with MySQL and a Mac and you don't have it - get it. Now!

It makes working with the database fun again. You can have favorite queries, browse your database, alter tables, kill queries in a simple, elegant and time-saving way.

Soulver

Soulver is a really nice application that you can use to do quick calculations.

I love it and use it for all my simple calculations.

Transmit

Xenu LinkSleuth

I rarely need it, since we deploy using GIT these days - but whenever I have to transfer stuff from a server I use Transmit.

Xenu LinkSleuth

Xenu LinkSleuth

Xenu is a real gem! I used it for many years now. Xenu is supposed to search for broken links - but I use it in another way..

The last time it came handy was, when I ported one of our projects to a new Ruby version. We have a pretty decent test-coverage - but I did not feel very comfortable anyway.

That's typically when I start Xenu to discover if something terrible is wrong with the system.

Xenu is a tool for Windows but works just great with Wine.

Terminal

Homebrew

Homebrew is the missing package manager for OS X. It my preferred way to install *NIX tools. It works like a charm and just feels better than the alternatives.

Bashmarks

Bashmarks is a little shell script that allows you to save bookmarks to directories. With a few keystrokes you can jump everywhere in the system.

To bookmark a directory:

cd ~/Ruby/amazing-project/
s amaz

To jump back in:

g amaz

GIT

My swiss army VCM system. I use it for nearly everything that is related to text. For example also to write blog-articles:

toolbelt.md on GitHub

Todo-Void

For my daily small tasks I use Todo-Void. A small task-manager that I created as a toy-project.

Todo-Void

As a long-term task manager I use Things.

Mac OS X

Terminal

Ruby: Reading the source code of OpenStruct.

Ruby version: 1.9.3-p327

Open Struct

Here is another read of a Ruby core class: OpenStruct.

Initializing an OpenStruct

You can create an OpenStuct using hash - or without any attributes.

def initialize(hash=nil)  
  @table = {}
  if hash
    hash.each_pair do |k, v|
    k = k.to_sym
    @table[k] = v
    new_ostruct_member(k)
  end
 end

If you use a hash openstruct will go ahead and store all the key/value pairs in an internal hash called table.

def new_ostruct_member(name)  
  name = name.to_sym
  unless respond_to?(name)
    define_singleton_method(name) { @table[name] }
    define_singleton_method("#{name}=") { |x| modifiable[name] = x }
  end
  name
end  
protected :new_ostruct_member  

It will also create getters / setters using definesingletonmethod.

require 'ostruct'
coordinate = OpenStruct.new(:x => 1, :y => 2)
#<OpenStruct x=1, y=2>

OpenStruct.new
#<OpenStruct>

Modifiable

But wait.. What does this modifiable thing in the dynamic setter do? Lets have a look at the code.

def modifiable  
  begin
    @modifiable = true
   rescue
     raise TypeError, "can't modify frozen #{self.class}", caller(3)
   end
   @table
end  
protected :modifiable  

Huh? It sets a attribute modifiable and if it does not succeed it throws an exception? If it is modifiable it returns the @table?

Well to be honest this is not clear at all. The text of the exception states that this is about frozen objects. Hm lets validate this:

foo = OpenStruct.new
 #<OpenStruct>
foo.send(:modifiable)
# {}
foo.freeze
# nil
foo.send(:modifiable)
# TypeError: can't modify frozen OpenStruct

Ah! - It acts as kind of a gatekeeper to the table, by preventing you from changing the OpenStruct if it's frozen. I'm not sure if I like this - it not to clear to me - on the other hand it is tell don't ask. I guess I have to think about it.

Method missing

There is another feature of OpenStruct. It has setters for attributes that do not yet exist.

foo = OpenStruct.new
#<OpenStruct>
foo.x = 1
foo.y = 2
foo
#<OpenStruct x=1, y=2>

In Ruby you can achieve this using method_missing.

def method_missing(mid, *args) # :nodoc:  
  mname = mid.id2name
  len = args.length
  if mname.chomp!('=') && mid != :[]=
    if len != 1
      raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
    end
    modifiable[new_ostruct_member(mname)] = args[0]
  elsif len == 0 && mid != :[]
    @table[mid]
  else
    raise NoMethodError, "undefined method `#{mid}' for #{self}", caller(1)
  end
end  

Hm… Wow there is some stuff I have never seen before. Lets try to read it line by line.

mid.id2name converts the method's id (which is a symbol). Into a string.

If the method name has a = and only argument new_ostruct_member creates a new entry in the table. Afterwards the value if assigned.

The elseif block handles reads on attributes that were not defined. Getter method have no arguments of course.

foo = OpenStruct.new
#<OpenStruct>
foo.something_random
# nil

It looks the mid up in the @table. I have no idea why it does not return nil in the first place here. The effect is the same, because ach time we add a new attributes new_ostruct_member creates dynamic methods. So if the attribute is already defined, we do not end up in method missing.

For all other functions except:
* These that have an "=" and one argument
* And these that have no argument
* And are not :[], :[]=

It raises an exception. If you wondering what this caller(1) thing is:

Returns the current execution stack—an array containing strings in the form “file:line” or “file:line: in method’”. The optional start parameter determines the number of initial stack entries to omit from the result.
Link to the Documentation

Duplicating an OpenStruct

I had quite a hard time of figuring out what the following function was doing. I tried really hard to call it from the console.. :/

 def initialize_copy(orig)
    super
    @table = @table.dup
    @table.each_key{|key| new_ostruct_member(key)}
  end

Ruby uses initialize_copy whenever you .clone or .dup an object. To get the whole picture read this great article about initializedup, initializeclone and initialize_copy!

Inspect

InspectKey = :__inspect_key__ # :nodoc:

def inspect  
  str = "#<#{self.class}"

  ids = (Thread.current[InspectKey] ||= [])
  if ids.include?(object_id)
    return str << ' ...>'
  end

  ids << object_id
  begin
    first = true
    for k,v in @table
      str << "," unless first
      first = false
      str << " #{k}=#{v.inspect}"
    end
    return str << '>'
  ensure
    ids.pop
  end
end  
alias :to_s :inspect  

The last part of this is straightforward. The method prints all attributes like lenght=21. It separates them by a space and a comma and appends the attribute info to the class name.

#<OpenStruct name="Brussel Sprouts">

What this inspect_key stuff is all about? Have a look at this experiment.

  puts :__inspect_key__
  # nil
Thread.new { puts :__inspect_key__ }
#<Thread:0x007fe2b487b650 sleep>

You see? Every thread has its own key.

Thread.new do
    a = OpenStruct.new(:hello => "foo", :world => "bar")
    puts a.inspect
  end
#<OpenStruct hello="foo", world="bar"> => #<Thread:0x007fe2b4817d80 run>

Marshalling support

The marshaling library converts collections of Ruby objects into a byte stream, allowing them to be stored outside the currently active script. This data may subsequently be read and the original objects reconstituted. Link to the Documentation

def marshal_dump  
  @table
end

def marshal_load(x)  
  @table = x
  @table.each_key{|key| new_ostruct_member(key)}
end  

I would have called it serialization / deserialization 😉 There are 2 function that OpenStruct implements to achieve this.

*marshal_dump just returns the table - it's already a hash, so Marshal can handle it.

marshal_load just assign this same hash and creates all the required method to access the attributes.

Lets have a look at this in action.

point = OpenStruct.new(:x => 1, :y => 2)
#<OpenStruct x=1, y=2>

serialized_point = Marshal.dump(a)
"x04bU:x0FOpenStruct{a:x06xix06:x06yia"

Marshal.load(serialized_point)
#<OpenStruct x=1, y=2>

Some changes in trunk

The version in trunk is slightly different from the version disscussed here. It contains the functions [] and []=.

 def [](name)
  @table[name.to_sym]
end

def []=(name, value)  
  modifiable[new_ostruct_member(name)] = value
end  

Last words

OpenStruct is quite nice. It comes in handy when you want to replace a hash with a value object. The addition in trunk will make this even easier in the future because it's a drop in replacement for simple cases and the Tests will stay green 😉

Many people find that the attr_reader part for non-specified attributes is a big problem, when you use OpenStruct. I agree. You have to be aware of this or it will bite you.

It was fun reading this class. I did't like the modifiable method. It's not really as clear as it could be.

  • There's a method called .id2name
  • Some random stuff about Threads
  • Rubyists call serialization marshalling
  • A weired way to detect a frozen object
  • Ways to hook into the dup and clone methods

Go read some code as well! Its a highly educating activity.

Picture of cup licensed under: (CC BY-NC-SA 2.0) Licensor: rebecca∞mahoney

© 2017 Rocu.de

Theme by Anders NorenUp ↑