Freezing classes and the nearest thing to “unfreezing”

Freezing is a way to stop classes from being changed in ruby, it’s a way to be a bit of a tyrant with your code.

A preferable way to manage other contributors is to use git and merge changes that other coders have committed, and if the code is below par, just ask the nicely for the functionality to be extended via modules for example or just reject those changes.

Here’s how you add method to a class using monkey patching.

class Freeza # you can define a class once
 def hello
   puts "hello"
 end
end

f = Freeza.new
f.hello

class Freeza # twice
  def goodbye
    puts "goodbye"
  end
end

f.goodbye

I have now decided that I don’t want anything added to this class.

Freeze it

Freeza.freeze

Now I have changed my mind, or another coder wants to add functionality.
Notice how I have wrapped the code in a begin and rescue error catch.

begin

  class Freeza
    def hello
      puts "is it me you're looking for"
    end
  end

rescue RuntimeError # this is what we'll get instead
  puts "Get back to where you once belonged"
end

Now that didn’t work

There is no way to unfreeze the class so we need to find a way to unfreeze somehow.

You can inherit from a frozen class and that will not be frozen.

So let’s try that.

class Defrosted < Freeza
  def hellohello
    puts "hello hello"
  end
end

f = Defrosted.new

f.hellohello

Thats all good, but you might want to convert a variable based on the first class and keep the the values from the old class so this is not very flexible, as you are just replacing a variable.

Freezing isn’t nice

Just don’t freeze, but also keep monkey patching to minimum as it’s one of the most powerful tools in ruby. But it can leave a mess of methods spread across multiple files without form.

Once certain monkey patches become popular then change them to the better way of doing it which is using modules.

You can use modules if you plan to have a variable which has the base functionality of a class, yet with a bit more functionality added.

Here’s how this is done.

module MoCowBell
  def donk
    puts "donk"
  end
end

# i want the variable f to make cowbell noises
f.extend MoCowBell
f.donk

Now that overcomes the potential freezes of objects by extending the functionality.

But I cannot find a legitimate use for freezing, but also modules are nicer than monkey patches.

Posted in Uncategorized

Syntax highlighting and more in ruby

In a previous post I used the ‘syntax’ gem to process text into tags which could then be tagged with terminal colour codes.

There’s a plugin which already does all of this called coderay, I will combine this with highline (to control the input and output and maybe create an interface too)

require "rubygems"
require "highline/import"
require "coderay"

class Editor
  def say(saying)
    puts saying
  end
 
  def getBinding
    return binding()
  end
end

e = Editor.new
e.say("hello world")

# now for a bit of monkey typing
monkey = <<MONKEY
  def reverseSaying(saying)
    self.say(saying.reverse)
  end

  self.reverseSaying("hello world")
MONKEY


puts monkey

eval(monkey,e.getBinding())
eval("reverseSaying('hello world')",e.getBinding)

# now try to monkey patch user input
usermonkeysay = ask("Monkey do?")
puts CodeRay.scan(usermonkeysay,:ruby).term
eval(usermonkeysay,e.getBinding)

One thing you might have noticed is that I have a function called getBinding in the ‘Editor’ class, what this does is return a handle to the current class to modify that class programmatically.

When we have the binding, we can do evil things on that class. I mean ‘eval’, but rather than a straight up eval you can do an eval within the context of that class.

And in ruby you can eval this inside of the context of the class

  def reverseSaying(saying)
    self.say(saying.reverse)
  end

Something like a ‘def’ in the context of the binding will let you run that function later on using the binding.

What does this mean?

A text editor which took advantage of this (something like diakonos, redcar maybe) would be able to provide user friendly commands such as open, save, gotoLine, regex, replace, column(x,y, w, h), select(x,y,w,h), copy, paste.

This would provide a clear level of abstraction between a command mode and text entry in editors.

My plan is to have a 3 pane editor with a readonly text view, a text entry box and a command box.

Posted in Uncategorized