Genetically Modified Origin

George's Blog - Digital Adventures in The Big Apple

Exploring Ruby’s Core (Methods, Modules, Classes, and More, Oh My!) Through Metaprogramming & Monkeypatching

| Comments

A general disclaimer: I just learned Ruby ~3 months ago, so please let me know if any of this can be improved upon

As I’ve been learning and becoming familiar with Ruby and its various libraries / gems, one thing I’ve found myself doing often is opening up irb or pry and playing around all different kinds of methods, classes, and modules. However, I’ve found that it’s hard to explore this consistently without having to constantly refer back to the documentation for what methods exist for each class / module or what the structure of the classes or modules are. I just want to play around and avoid constantly going back online or to the source code! The solution: I ended up modifying the core ~/.irbrc and ~/.pryrc files to monkeypatch Ruby’s core classes, so that every time I start up irb, pry, or rails console I get access to my custom methods. Here’s a link to what my .pryrc file looks like:

https://gist.github.com/gglin/5930277

If you want to see an example of all this in action, go to the end of this post

Now, I can much more easily explore methods, classes, modules and other Ruby constructs:

Exploring Methods

  • any method which ends with the word "methods", i.e. returns an array of the defined methods for an object, whether it is all methods, instance methods, private methods, or whatever else, can now be prefixed with "local_" to return a much shorter array of just methods which aren’t already defined for all Ruby Objects (though you can modify this default to return the difference with any class).
    • Ruby does have a built-in way to retrieve only methods defined in the immediate scope, not any mixed-in modules or superclasses, by setting the argument in xxx_methods(arg) so that arg = false. However, having a local_xxx_methods is more customizable, and may be more telling in many cases, such as where you are totally unfamiliar with a class or module and want to see not just how it is different from its immediate ancestors, but overall, i.e. to see the methods it inherited from everything but the Object class.

See code here:

.irbrc or .pryrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Object

  # all methods named 'local_(*)_methods' 
  # should return '(*)_methods' minus those that exist in Object
  def method_missing(method_name, klass = Object, *args, &block)
    if method_name.to_s[0..5] == "local_" && method_name.to_s[-7..-1] == "methods" && !method_name.to_s[6..-1].include?("local")
      subname = method_name.to_s[6..-1]
      self.send(subname, *args, &block) - klass.send(subname, *args, &block)
    else
      super(method_name, *args, &block)
    end
  end

  # core 2.0 documentation says "DO NOT USE THIS DIRECTLY." - why?
  def respond_to_missing?(method_name, include_private = false)
    subname = method_name.to_s[6..-1]
    method_name.to_s[0..5] == "local_" && method_name.to_s[-7..-1] == "methods" && !method_name.to_s[6..-1].include?("local") && respond_to?(subname) or super
  end

end

Exploring Namespaces

  • When I call ancestors on a module, the list of results returned is a mix of the modules mixed in and the superclasses. Breaking these into two methods, module_ancestors and class_ancestors, helps me to better understand the inheritance chain of a given module or class. For example, it’s much clearer now that the class inheritance chain for Fixnum is [Fixnum, Integer, Numeric, Object, BasicObject], while the modules [Comparable, Kernel] are only mixed in.

  • For a given namespace, such as ActiveRecord::Base, I was curious to see what the various modules and classes that exist under that namespace are, as there is (1) no easy way to see all of these without consulting the source code, which is massive for something like ActiveRecord, and not trivial to find and explore, and (2) no easy way to tell the difference between modules, classes, and other constants under that namespace.

    • I initially consulted a StackOverflow post that explains how to do this, and wrote up the methods subclasses and submodules. Unfortunately, these only look for subclasses within subclasses and submodules within submodules…
    • There are many cases where in the nested namespaces, you could have a class in a module in a class in a module, or anything else. Although more complicated, I eventually came up with a way to do this using a “subthing” helper method, which is a ~20 line monstrosity I’m not happy with. Regardless, the methods subconstruct_classes and subconstruct_methods will look into all nested namespaces, no matter how deep, and retrieve all classes or modules.

  • Modifying the above code slightly allows for retrieval of non-module, non-class constants for a given module – for example, finding that the only constants that exist for the Math module are :PI & :E, and that their values are 3.14159… & 2.71828… using subconstants and subconstant_names

See code here:

.irbrc or .pryrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
class Module

  def class_methods(*args, &block)
    self.methods(*args, &block) - self.instance_methods(*args, &block)
  end

  def class_ancestors
    self.ancestors.select{|a| a.class == Class}
  end

  def module_ancestors
    self.ancestors.select{|a| a.class == Module}
  end

  def subthings(recursive = false, *args, &block)
    result = self.constants.collect {|const_name| const_get(const_name)}.select {|const| yield(const) }
    return [] if result.include?(self)
    if recursive == false
      result.uniq
    else
      looper = result.clone
      looper.each do |thing|

        thing.subthings(false, *args, &block).each do |subthing|
          subthing.subthings(false, *args, &block).each do |subsubthing|
            recursive = false if result.include?(subsubthing)
          end
          result << thing.subthings(recursive, *args, &block)
        end
      end
      result.flatten.uniq
    end
  end

  # http://www.natontesting.com/2010/06/30/how-to-get-the-submodules-of-a-ruby-module/
  # return only immediate nested namespace modules
  def submodules(recursive = false)
    subthings(recursive) {|const| const.class == Module}
  end

  # return only immediate nested namespace classes
  def subclasses(recursive = false)
    subthings(recursive) {|const| const.class == Class}
  end

  def subconstructs(recursive = false)
    subthings(recursive) {|const| const.class == Class || const.class == Module}
  end

  # returns all nested namespace modules
  def subconstruct_modules
    subconstructs(true).select {|const| const.class == Module}
  end

  # returns all nested namespace classes
  def subconstruct_classes
    subconstructs(true).select {|const| const.class == Class}
  end

  # retrieves non-class, non-module constant names
  # e.g. Math.subconstants => [3.14159, 2.71828]
  def subconstants(recursive = false)
    subthings(recursive) {|const| const.class != Class && const.class != Module}
  end

  # retrieves non-class, non-module constant names
  # e.g. Math.subconstant_names => [:PI, :E]
  def subconstant_names
    constants.select {|const_name| const_get(const_name).class != Class && const_get(const_name).class != Module}
  end

end

Exploring Class Inheritance

  • Finally, for classes, there is an easy built-in way to look up the inheritance chain and find the parent of a class using the superclass method. Unfortunately the opposite isn’t true – there’s no built-in way to find all children of a parent class. Fortunately Ruby has module called ObjectSpace which allows for traversal of all living objects in memory, allowing for a simple child_classes (& alias children) method to be defined. Note that this is NOT the same thing as the subclasses method I mentioned earlier – the latter only cares about namespaces, i.e. BaseModule::AnotherModule::SubClass, while child_classes is concerned with class inheritance, i.e. ChildClass < ParentClass.

See code here:

.irbrc or .pryrc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Class

  def child_classes
    ObjectSpace.each_object(Class).select { |klass| klass < self }
  end

  def children
    child_classes
  end

  def siblings
    self.superclass.child_classes - [self]
  end

end

Not finding giants to stand on the shoulders of, aka It’s been done before

Of course, it was only after I had written all of these that I found there’s much more experienced coders who have done a lot of this already! Here are some (probably better) ways to accomplish what I monkeypatched:

  • There is an entire gem which consists of libraries which extend the core capabilities of Ruby’s built-in constructs: Facets. A lot of the methods from Facets do the above, probably in a better way. Updates to Facets have been infrequent in the last year, but nevertheless it seems to have tons of potentially useful additions to core Ruby.

  • There are in gems which make it much easier to print readable, colorful Ruby – for example, the “y” method in YAML, “pp” for prettyprint, “pretty_generate” in JSON. Among these is a great little gem called Awesome Print, which not only formats and colorizes the output, but also adds additional helpful info, such as the superclass of the printed object, the index of each element in an array, and vertically aligning the hash rocket in a hash so that the keys and values are easier to read. To always include awesome print, I added this to my .pryrc as per instructions:

.irbrc or .pryrc
1
2
require "awesome_print"
AwesomePrint.pry!

Now, this solves the problem of being able to tell the difference between class and module ancestors. For example, with ap enabled, CodeRay::WordList::CaseIgnoring.ancestors returns the following:

This is clearly much easier to read and tells you not only which ancestors are classes, but what each ancestor’s superclass is.

Regardless, by doing these monkeypatches, I’ve found it much easier to navigate around all kinds of objects and methods in Ruby to learn more about it, without necessarily having to go back to the source code – for example, find a specific class within ActiveRecord::Base and then find all the local_methods for that class. Even if there is still a lot of code I could change / clean up, this was a great learning experience to understand Ruby more deeply. As they say, it’s about the journey, not just the destination.

Example of Usage

As an example of how I can use the code I wrote, I started pry and typed in:

pry
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[1] pry(main)> CodeRay.subconstruct_modules
[
    [0] CodeRay::FileType,
    [1] CodeRay::Styles,
    [2] CodeRay::Encoders,
    [3] CodeRay::PluginHost,
    [4] CodeRay::Plugin,
    [5] CodeRay::Scanners,
    [6] CodeRay::GZip,
    [7] CodeRay::Tokens::Undumping
]
[2] pry(main)> CodeRay.subconstruct_classes
[
    [ 0] CodeRay::TokensProxy < Object,
    [ 1] CodeRay::Tokens < Array,
    [ 2] CodeRay::WordList < Hash,
    [ 3] CodeRay::Duo < Object,
    [ 4] CodeRay::Encoders::Encoder < Object,
    [ 5] CodeRay::Encoders::Terminal < CodeRay::Encoders::Encoder,
    [ 6] CodeRay::PluginHost::PluginNotFound < LoadError,
    [ 7] CodeRay::PluginHost::HostNotFound < LoadError,
    [ 8] CodeRay::Scanners::Scanner < StringScanner,
    [ 9] CodeRay::Scanners::Ruby < CodeRay::Scanners::Scanner,
    [10] CodeRay::WordList::CaseIgnoring < CodeRay::WordList,
    [11] CodeRay::FileType::UnknownFileType < Exception,
    [12] CodeRay::Styles::Style < Object
]

Now if I want to know the local class methods available for CodeRay::WordList and local instance methods available for CodeRay::TokensProxy, I can type:

pry
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[3] pry(main)> CodeRay::Styles::Style.local_methods
[
    [0]      aliases()       Class (CodeRay::Plugin)
    [1]  plugin_host(*host)  Class (CodeRay::Plugin)
    [2]    plugin_id()       Class (CodeRay::Plugin)
    [3] register_for(id)     Class (CodeRay::Plugin)
    [4]        title(*title) Class (CodeRay::Plugin)
]

[4] pry(main)> CodeRay::TokensProxy.local_instance_methods
[
    [ 0]    block()                  CodeRay::TokensProxy (unbound)
    [ 1]   block=(arg1)              CodeRay::TokensProxy (unbound)
    [ 2]     each(*args, &blk)       CodeRay::TokensProxy (unbound)
    [ 3]   encode(encoder, *options) CodeRay::TokensProxy (unbound)
    [ 4]    input()                  CodeRay::TokensProxy (unbound)
    [ 5]   input=(arg1)              CodeRay::TokensProxy (unbound)
    [ 6]     lang()                  CodeRay::TokensProxy (unbound)
    [ 7]    lang=(arg1)              CodeRay::TokensProxy (unbound)
    [ 8]  options()                  CodeRay::TokensProxy (unbound)
    [ 9] options=(arg1)              CodeRay::TokensProxy (unbound)
    [10]  scanner()                  CodeRay::TokensProxy (unbound)
    [11]   tokens()                  CodeRay::TokensProxy (unbound)
]

Some other fun things to try out:

pry
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
[5] pry(main)> Fixnum.class_ancestors
[
    [0] Fixnum < Integer,
    [1] Integer < Numeric,
    [2] Numeric < Object,
    [3] Object < BasicObject,
    [4] BasicObject
]
[6] pry(main)> Fixnum.siblings
[
    [0] Bignum < Integer
]
[7] pry(main)> require 'active_record'
true
[8] pry(main)> ActiveRecord::Base.subconstant_names
[
    [0] :ACTIONS,
    [1] :UNASSIGNABLE_KEYS,
    [2] :CALLBACKS,
    [3] :ATTRIBUTE_TYPES_CACHED_BY_DEFAULT,
    [4] :NAME_COMPILABLE_REGEXP,
    [5] :CALL_COMPILABLE_REGEXP,
    [6] :CALLBACK_FILTER_TYPES
]
[9] pry(main)> ActiveRecord::Base.subconstants
[
    [0] [
        [0] :create,
        [1] :destroy,
        [2] :update
    ],
    [1] [
        [0] "id",
        [1] "_destroy"
    ],
    [2] [
        [ 0] :after_initialize,
        [ 1] :after_find,
        [ 2] :after_touch,
        [ 3] :before_validation,
        [ 4] :after_validation,
        [ 5] :before_save,
        [ 6] :around_save,
        [ 7] :after_save,
        [ 8] :before_create,
        [ 9] :around_create,
        [10] :after_create,
        [11] :before_update,
        [12] :around_update,
        [13] :after_update,
        [14] :before_destroy,
        [15] :around_destroy,
        [16] :after_destroy,
        [17] :after_commit,
        [18] :after_rollback
    ],
    [3] [
        [0] :datetime,
        [1] :timestamp,
        [2] :time,
        [3] :date
    ],
    [4] /\A[a-zA-Z_]\w*[!?=]?\z/,
    [5] /\A[a-zA-Z_]\w*[!?]?\z/,
    [6] [
        [0] :before,
        [1] :after,
        [2] :around
    ]
]

Thanks to the following posts on StackOverflow for guidance:

  1. http://www.natontesting.com/2010/06/30/how-to-get-the-submodules-of-a-ruby-module/
  2. http://stackoverflow.com/questions/2393697/look-up-all-descendants-of-a-class-in-ruby

Summary - Extending Ruby With Ruby

| Comments

I find metaprogramming to be a fascinating subject. Code that writes itself! Keep DRY! Do crazy things in 10 lines that might otherwise take 100 or even be impossible!

Naturally, I was attracted to a presentation Michael Fairley gave entitled “Extending Ruby with Ruby”. Well, that and the fact that Michael’s name reminded me of Michelle Fairley, who plays Catelyn Stark on my favorite show, Game of Thrones.

His central thesis is that Rubyists usually think of metaprogramming as a tool used for two things – keeping DRY and saving some typing, and monkeypatching a library that doesn’t work as well as you would like. However, Ruby’s metaprogramming capabilities are much more powerful than this, and you can use Ruby to easily add new, awesome features to the language itself. He gives a few specific examples, drawing inspiration from other languages:

Function Decorators from Python

Python has a design pattern called “function decorators”, which allow us to inject or change code directly into a method, for additional clarity and to avoid writing a lot of boilerplate code. For example:

Function Decorator Example in Python
1
2
3
4
5
6
@transactional
def send_money(from, to, amount):
  from.balance -= amount
  to.balance += amount
  from.save()
  to.save()

This allows the send_money method to be wrapped in a “transactional” function, i.e. the send_money method won’t execute to the database unless every transaction in it is successful; otherwise all changes are rolled back. This is defined by the “transactional” function, defined elsewhere but used to “decorate” the top of this method. In Ruby we could use blocks or modify the method after the fact, but this is not clean as you can no longer trace execution of the method from top to bottom.

Luckily, even though Python has this cool feature that doesn’t exist in Ruby, we can add this functionality to Ruby itself given its extensible nature. Michael created a neat gem, method_decorators, which does exactly this (there is another gem which does something similar). The amazing thing is that the core added functionality is accomplished in a little more than a dozen lines of code! The result of that is we can now mimic function decorators in Ruby:

Function Decorator Added to Ruby
1
2
3
4
5
6
7
+Transactional
def send_money(from, to, amount)
  from.balance -= amount
  to.balance += amount
  from.save()
  to.save()
end

Partial Applications from Scala

In Scala, bulk operations on a collection of items (aka enumerables in Ruby), such as map, filter, and reduce, can be shorthanded using an underscore (“_”) for clarity. This is part of a concept known as partial applications:

Making code pretty in Scala
1
2
List(1,2,3).map(i => i.toString) // List("1", "2", "3")
List(1,2,3).map(_.toString)      // List("1", "2", "3")

Ruby has something similar:

Making code pretty in Ruby
1
2
[1,2,3].map{ |i| i.to_s } # ["1", "2", "3"]
[1,2,3].map(&:to_s)       # ["1", "2", "3"]

However, Scala has support for more complex versions of these anonymous functions which Ruby does not:

Making code pretty in Scala which doesn’t work in Ruby
1
2
3
4
5
List(1,2,3).reduce((i,j) => i + (j * 2)) // 11
List(1,2,3).reduce(_ + (_ * 2))          // 11

List(1,2,3).filter(i => 2 * i < 3)       // List(1)
List(1,2,3).filter(2 * _ < 3)            // List(1)

Once again, thanks to the power of Ruby metaprogramming, we can accomplish something similar in Ruby with just a few lines of code! The key is defining a “_” (underscore) method in the base Object class which can take a block (see slides 88-109 for details). With the added features, Ruby now has a similar functionality:

After monkeypatching Ruby
1
2
3
4
5
[1,2,3].reduce{ |i,j| i + (j * 2) } # 11
[1,2,3].reduce( &_{_ + (_ * 2)} )   # 11

[1,2,3].select{ |i| 2 * i < 3 }     # [1]
[1,2,3].select( &_{2 * _ < 3} )     # [1]

Now, monkeypatching the Object class with something as basic as an underscore is probably not the best idea, but it does show the power of Ruby in being able to extend itself and mimic other languages.

Lazy Evaluation from Haskell

The last example Michael gives is lazy evaluations in Haskell, e.g. not executing an http request until it is needed. We can easily define a Lazy class to be used as a wrapper (or even as a method decorator, ala the first example) to accomplish something similar:

Lazy Evaluation class
1
2
3
4
5
6
7
8
9
10
class Lazy < BasicObject
  def initialize(&block)
    @block = block
  end

  def method_missing(method, *args, &block)
    @result ||= @block.call
    @result.send(method, *args, &block)
  end
end

Now if compare these two blocks of code:

without Lazy Eval
1
2
3
4
5
6
7
8
def three
  puts "2"
  3
end

x = three
puts "1"
puts x
with Lazy Eval
1
2
3
4
5
6
7
8
9
10
def three
  Lazy.new do
    puts "2"
    3
  end
end

x = three
puts "1"
puts x

Now, for something absolutely bonkers, Michael changes the way Ruby as a language works so that EVERYTHING can use lazy evaluation, mimicking Haskell. He is able to do this via the ObjectSpace class and instance_methods method, which allows him to loop through every method in every module and class (with some exceptions):

Craziness in Ruby
1
2
3
4
5
6
7
8
9
10
11
modules = ObjectSpace.each_object(Module)

modules.each do |k|
  k.instance_methods.each do |m|
    next if ... # some exceptions
    im = k.instance_method(m)
    k.send(:define_method, m) do |*args|
      Lazy.new { im.bind(self).call(*args) }
    end
  end
end

This sounds a little dangerous to me, but it does have some practical applications. For example, in a simple Rails app which might fetch tweets from the Twitter API:

Lazy Evaluation applied to Rails
1
2
3
4
5
6
7
8
9
10
# Controller
def index
  @tweets = Lazy.new { get_from_twitter_api }
end

# View
<% @tweets.each do |tweet| %>
  <%= tweet.author_name %>:
  <%= tweet.text %>
<% end %>

Since we want the client browser to fetch the CSS and JS as quickly as possible, we can make the “get_from_twitter_api” request lazy.

The Power of Metaprogramming

Seeing these examples really made me appreciate the power of Ruby even more. Like many things in life, I think the best things should be easy to learn, but hard to master. It should cater to beginners (with convention over configuration) but still be powerful for the advanced (e.g. metaprogramming).

One of the reasons I am where I am now is that I believe in the power of software to change the world, the power to fix problems, and as programmers I think this mindset should apply everywhere – not just the big macro problems in the world, but the small, nitty-gritty micro problems as well. Software should facilitate answers to real-world huge problems such as “how do I get to the nearest train station?” or “what are my friends doing?”, but it should also facilitate answers to problems such as “can I get my programming language to behave the way I want it to?” Before you can change the world, you should be able to change yourself.

You Can Learn a Lot From Shaving a Yak

| Comments

On the third day of class, we learned a term called “yak shaving”. The idea is that you want to do something, let’s say change a lightbulb, but that ends up requiring you to do something else, which in turn requires you to do something else, which requires you to do something again… After diving into subtask after subtask, eventually you find yourself shaving a yak when all you wanted to do was change your lightbulb!

Etymology: the term is thought to have been coined at the MIT AI Lab circa 2000, as inspired by an episode of Ren & Stimpy. Here are some definitions from various sources: MIT, Urbandictionary, Seth Godin (who helped popularize the term)

I didn’t think much about the term until pretty recently. In the last 2 weeks or so, as I’ve been diving heavily into code, I’ve found myself shaving yaks constantly – I can see why it’s a “thing” in programming now!

Case in point – the jukebox. As my teammates can attest, I’ve been building a command-line interface jukebox which when given a list of songs, will retrieve the songs’ artists and genres, and allow the user to browse or choose by category and select a song to “play” (it only displays the song & doesn’t actually play it yet, haha). Well technically, this was an assignment everyone had to do, but since I liked the idea I decided to take it a lot further. (Also, to order to generate a song list, we parsed a directory for mp3 files and built a library of artists, songs, and genres)

My current version of the CLI jukebox can not only browse by “artist”, “song”, or “genre”, but it can also search by artist, song, or genre, and whatever the results are of the current search or browsing results, you can keep entering input to further filter results, as well as choose a result by number (thanks Ning for some of the inspiration!)

Here are some examples of yak shaving while making the CLI jukebox:

  • In order to get the program to understand so many different kinds of user inputs, I ended up having to learn regular expressions (Rubular is awesome!). Specifically, valid commands that the program understands are stored in class constant:
Valid Inputs
1
VALID_COMMANDS = [/^(artist|song|genre)s?$/, /^(artist|song|genre)\s+\S+/, "stop", "help", "exit"]

This allows for the program to understand the input “artist(s)”, “song(s)”, “genre(s)”, as well as the input “artist [name or number]”, “song [name or number]”, “genre [name or number]”.

Here is what my code for seeing whether or not a valid command is recognized looks like:

See if input is valid
1
@valid_command_entered = !VALID_COMMANDS.grep(@command).empty?

This doesn’t work though. After some banging my head on the wall, I ended up reading the “grep” documentation in the Ruby Enumerables module, and discovered the problem:

Problem
1
2
3
4
5
6
7
8
 # [element1, element2, etc].grep(pattern) only matches when pattern === element
 # However, if element is a regular expression grep will fail to find the match
  #    /abc/ === "abc" returns true
  #    However, "abc" === /abc/ returns false

   # We want to enhance the functionality so that it also matches when element =~ pattern
  #    /abc/ =~ "abc"  &  "abc" =~ /abc/ will both find a match
  #    if element and pattern have the same class, "=~" won't work and we will have to use ==

Simple enough. We open the class and give it a new method grep2:

The Fix
1
2
3
4
5
6
7
8
9
10
11
class ::Array
  def grep2(pattern)
    self.select do |element|
      if pattern.class == element.class
        element == pattern
      else
        element =~ pattern
      end
    end
  end
end
  • After creating this program on my own computer, I wanted to import this to the web so that it could run as a CLI “web app” over the internet. I was inspired by a few command-line interface websites: xkcd, goosh, After many futile attempts at finding an answer which made me question my google-fu, I finally found something reasonable which had been staring at me in the first page of google results: a Ruby gem called Rack Webconsole! After installing, more banging my head on the wall and finagling, I finally got it to work:

Now I need to learn how to get “puts” and “gets” to work in the webconsole interface instead of on the server-side console:

To be fixed…
1
2
3
4
5
6
7
8
9
10
11
12
13
  def output(string)
    puts string #=> doesn't work right
    # Ripl.shell.print_result(string)
    # Rack::Webconsole::Shell::eval_query(string)[:result]
    # Ripl.shell.loop_eval(string)
    #   ==> none of the above work...
  end

  def input
    # gets  => no longer works
    # Ripl.shell.loop_once
    #   ==> fix this too...
  end
  • I also learned about a little bit about XRSF, a way for bad people to hack into your website, as I was learning about Webconsole. In retrospect, using this gem probably isn’t the best idea to use in production, though it’s pretty awesome in development. Maybe I’ll learn enough javascript by looking at the source code of sites like xkcd and goosh to make this work someday.

Enjoying the view and striving for the destination

There’s always more to learn, and to do something I thought would be so simple ended up requiring hours and hours of banging my head on the way. However, in retrospect it was all a great learning experience and helped me become a better coder, as I suspect yak shaving can oftentimes be.

It’s the journey that matters, not the destination. However, a program that doesn’t work right isn’t useful either. So I guess both are important – enjoy the view along the way, but to learn the most, don’t stay satisfied until you reach the destination.

I Did It My Way

| Comments

The Web as a Virtual Country

So my parents came into town this weekend to visit, and I was explaining to them all the things I’ve learned in the last month or so: HTML, CSS, Javascript, SQL, Ruby, MVC, Rails, etc.

We’ve only covered HTML, CSS, SQL, and Ruby, and how the Internet works so far in class (the other topics being self-taught so far based on prepwork), but regardless, I was explaining to my parents how I understood all these things fit together. Specifically, what the heck is the difference between PHP, Python, Ruby, Ruby on Rails, and all these terms that outside observers might hear about but not understand the difference between.

Struggling to explain these concepts in a short, concise manner, I remembered an analogy I had heard before: the web as a virtual city. Extending this analogy further:

  • The browser / internet infrastructure =~ cars / highways
  • Websites =~ actual stores or buildings
  • Web application frameworks (e.g. Rails) =~ framework or skeleton of a building
  • Programming languages =~ building materials (e.g., Ruby could be wood, Python could be brick, PHP could be straw – just as an example, not implying anything about the merits of any language)

We always talk about coders as “builders”, and I think it’s even more true than what most people realize. What I essentially learned in the last month were the tools of the craft, the art of carpentry or brick-laying. Now it’s time to learn how to build buildings. But before I start building buildings, I need to understand what a house actually looks like and how it functions.

Introducing: Sinatra

According to the official website, Sinatra “is a DSL for quickly creating web applications in Ruby with minimal effort.” If we keep with the analogy, Sinatra is a much easier framework for building simple houses, while something like Rails is a lot more powerful and allows us to build all kinds of buildings, but at the expense of requiring a lot more complexity.

On a side note, did you know that if you search for “Sinatra” on Google, the first result is actually Ruby Sinatra and not Frank Sinatra? Crazy eh? Thanks @StevenABrooks for the tip!

So obviously it makes sense to learn how to build a simple house before building a skyscraper, eh? And even before I start to build houses, it might be a good idea to look at what other peoples’ houses look like, eh? Luckily thanks to the open source movement, we can see exactly how sites are built and learn how to organize our tools (i.e. codebase) to best start the building process. Thanks, yer ol’ Hub o’ Gits!

I picked a Sinatra web app, and analyzed its codebase to learn how its floors are laid, how rooms are connected, etc, to better design my own floorplans in the future. And what better app to look at than the appropriately-named “Dashing”?

Sinatra is not Dashing, but Dashing is Sinatra?

Dashing by Shopify definitely lives up to its name – check out demos here and here. Dashing is “a Sinatra based framework that lets you build beautiful dashboards”. Its UI is similar to Window 8’s, except without the evil-empirishness of a close-sourced monopoly; I can look behind the curtain to see a well-designed, simple codebase in the repo. Here’s what it looks like:

  • /bin – inside is a single ruby binary for the command line inputs
  • /javascripts – where all the magic of the UI happens. The .js files inside include JQuery, as well as a batman.js file, which seems to be linked to another Shopify product
  • /lib – there is only single file in here, dashing.rb. This appears to be the actual Sinatra application for interfacing with the web servers and ‘net. So even though this file is very small compared to some others, it is essential – without it this would not be a web app.
  • /templates – there are a few miscellaneous templates in here. The biggie is a folder inside called /projects. The way Dashing works, you can generate entire projects with the Dashing gem, by typing ‘dashing new sweet_dashboard_project’ into CLI, which will use this /projects folder as a template
  • /test – a pretty simple set of tests in the test suite
  • .gitignore – pretty standard; this tells git what kinds of files to ignore when creating or changing a repo
  • Gemfile – all Ruby gems have this
  • MIT-LICENSE – pretty standard
  • README.md – pretty standard
  • Rakefile – pretty standard. This rakefile makes it super simple for Ruby to run your test suite
  • dashing.gemspec – This contains gem specifications – pretty standard for when we want package a library into a Ruby gem

What I Learned About Programming From a Delivery Guy

| Comments

So today, as I was heading up the elevator on my way to my apartment, a food delivery guy gets into the elevator.

Some context: I live on the 46th floor of my building, so it’s always slightly annoying when people get into the elevator on the way up – that’s 2 more floors the elevator has to stop at! It’s tough enough having the elevator stop at a bunch of floors on its way down; I’d rather not have it do that on the way up (I know, first world problem)

Now, the delivery guy not only decides to hit another floor (let’s say 35) between the floor he got on (let’s say it was 20) and my floor (46), but he also decides to hit the button for the penthouse floor! This doesn’t really annoy me as I will be getting off the elevator before then, but it does pique my interest…

…as soon as he gets off on the 35th floor, he immediately hits the down button on that floor and then hurries down the hallway to make his delivery.

How strange. I think about this for a second before coming up with an explanation:

Elevator Workflow

This is the delivery guy’s “workflow” – as soon as he gets into the elevator, he wants to make sure the elevator is going to go to the top floor. That way, as soon as he gets off and immediately hits down, he is ensured that there is an elevator – the one he just got off of – which will go to the top floor and then come down to meet him as he finishes his delivery, assuming the time it takes to deliver is similar to the time it takes for the elevator to go to the top and then come down to meet him. If he had not hit the penthouse button, all the elevators might already be at the bottom and he would have to wait much longer for one of them to come up and take him down.

Now I know why delivery people are always so impatient when I don’t come to the door immediately!

Delivery = Programming

So how is this related to programming you ask? It might not be that related. But my head has been swimming in code for the last 3 weeks, so these are the kinds of analogies I’m drawing:

  1. In my experience to the world of programming, it seems that efficiency is huge. Sure, maybe if you don’t know the keyboard shortcut to a common task, you might waste a second each time, but compound this x1000s and you might be wasting hours, days, weeks, or even longer if programming is a lifelong endeavor. In a similar way, this delivery guy’s methodology might save him a minute or two each time, but compound that and it might become pretty substantial.

  2. To an outside observer, these little “hacks” might seem mysterious at first (or maybe just to me), but once understood I have an “Aha!” moment. When thinking about or looking at code, I often find that some of the individual parts don’t make a lot of sense on their own – e.g. “why did the delivery guy press the top floor?? It’s not like he’s going there since he’s getting off before then”. But once understood as part of a whole, the code is crucial or complementary. Conversely, there is some code which makes perfect sense when I see it – e.g. “press the down button as soon as you get off on a floor” – but there’s a lot of nuances that are easy to miss upon cursory inspection, e.g. the elevator going to the top floor complementing the more obvious action.

  3. I was exposed to the method of pressing the penthouse floor button, before seeing the method of pressing down immediately after getting off the elevator. However, pressing down is the first real action after getting off the elevator, and it just so happens that the ideal result occurs as a result of the penthouse method triggering much earlier. Similarly, when reading code, things don’t seem to be as straightforward as reading downwards. Control flow, methods being invoked, etc add complexity to how code is read, and it becomes a skill to mentally conceptualize how things are flowing.

  4. It would probably have been easiest to figure all this out by asking. If I was a delivery guy I might have figured this out on my own, but there is a chance I wouldn’t have and wasted a lot of time. The actual task of delivering things, just like programming, is oftentimes inherently lonely, yet there are so many ways it could/should be social – you have to interact with people in some capacity in order to get the product to the customer. And like many industries, there is so much to learn from others, whether it is through mentorship, apprenticeship, other resources, pair programming, or whatnot.

  5. Software development even uses similar language as food delivery – “shipping”, “delivery / deployment”, etc.

Stand & Deliver

As I’m learning about data modeling and object-oriented programming, what might be interesting is modeling out the actual elevator / food / “hacker” delivery guy in code. More to come on a later date?


First Meetup

On an unrelated note, today was the first meeting this semester of the NYC on Rails Meetup! Here’s a snippet of a great presentation on creating a Gem which uses command line to post directly to Tumblr (ShitAviSays):

Hello World!

| Comments

puts "Hello, world!"

document.write('Hello, world!');

#import <stdio.h>
int main( int argc, const char *argv[] ) {
    printf( "Hello world\n" );
    return 0;
}

public class HelloWorld {
   public static void main(String[] args) {
       System.out.println("Hello, world!");
   }
}

print("Hello, world!")

(display "Hello, world!")

main = putStrLn "Hello, world!"

cat('Hello, world!\n')

“A smooth sea never made a skilled sailor.”

Hello, my name is George, and I’m a student @flatironschool, a 12-week intensive program for aspiring web developers. As part of the program, @avi has all students regularly maintain a blog. So after many years of maintaining a digital footprint via only facebook and twitter, here I am!

Above is a list of languages I am interested in learning, vaguely listed by interest level, though this is bound to change as I get to know more and more.

A little about me:

  • BS Chemical Engineering 2008, MIT
  • Former Management Consultant
  • Places lived: China, Central PA, Central NJ, Boston, NYC
  • DOB: 1986-06-25

OK that’s enough. Back to code. See you next time!