Archive for Ruby

Creating File Paths the Easy Way

The Traditional Way

The traditional way to create file paths that are cross platform in Ruby, was to join them up as arguments in a File.join call:

Result:
"./../../config/database.yml"

Now thats all nice and everything but if you want to change it, you would have the inconvenience of having to add or remove commas, or single|double quotes, which can be a bit of a hassle.

Prettying it Up

So how about we pretty it up a little?

Result:
"./../../config/database.yml"

Now doesn’t that look a whole better?

What in the world is %w[...]?

Why does this work just as well?

The %w[...] creates an array of Strings separated by the whitespaces in the list.

Result:
["..", "..", "config", "database.yml"]

But what if you have a space in the file name? Well you can use a backslash as an escape key and presto!

Result:
["..", "..", "config", "a file"]

Note: I’m not so sure what this operator is called, and any help giving it a name would be greatly appreciated.

Comments (3)

The Importance of Naming

What’s in a name? That which we call a rose, By any other word would smell as sweet;

Juliet, Scene II, Romeo and Juliet1

Names make it easier for us to identify both physical objects and abstract ideas and feelings.

As names are important to us, they should not be abused. The same goes with sentences. Adjectives, verbs, nouns, everything comes together to piece a cohesive sentence. Conventions are set in place to ensure that everyone can understand your sentence.2

The same goes with code. Programming languages come with conventions to make your code look readable3, beautiful, poetic, reusable, and hence save you alot of time in coding.4

Code conventions can be top down, and dictated by the Project Manager, or be recommendations from the bottom up.

This post will look at some of the stylistic conventions or syntatic sugar that Ruby5 provides to make life easier for you.

Emo Methods!6

When starting Ruby, a lot of things took me back. Especially the unique inclusion of allowing methods to be named with the exclamation and question mark.

I absoutely love Heart this feature of Ruby, as it gives the language expression.

When I think of this feature, I think of Newspeak, in that our ability to express oneself is only limited to our vocabulary. A larger vocabulary leads to a more expressive language7, and more expression allows one to state their intent clearly.

The Question Mark (?)

Oh Magical Eight Ball 8ball is this array empty?

Magical Eight Ball 8ball responds: Yes — definitely.

Methods with a question mark, are intended to “ask a question” (obviously), and are intended to only return true or false (unlike a Magic Eight Ball 8ball with 20 different possible variations). These methods generally involve looking at what state the object is currently in.

Because everything is an object in Ruby, the context is very clear. You are testing on an Array, and not a Numeric.

In other languages that support dynamic arrays, it may look something like this: (In PHP)

Magical Eight Ball 8ball responds: Reply Hazy, try again.

What am I doing? Oh poor lament souls what does count do?

The Exclamation Mark (!)

Methods ending in a exclamation mark indicates that the method is destructive (in that it will modify itself). Beware, the object will cut it self!

Magic Eight Ball 8ball responds: Don’t count on it.

Here we declare a string, and try to strip it of its whitespace. The second line calls the strip method where the return value’s whitespaces have been removed from both the left and right side. But when you check the variable again (line 3), the dreaded whitespace still exists! You are safe for now little string. This time we specify an exclamation mark (line 4), and check the value (line 5) Destructive!

Lets go through another (more complicated) example, looking at how each object has a different id.

Magic Eight Ball 8ball responds: My sources say no.

In this example, we will once again be using the downcase method to down/lowercase the string. Without the use of the exclamation mark (line 4), a new object is returned (see the object_id). When used with the exclamation mark (line 6), the returned object, is the object itself.

Note:

  • object_id is the integer identifier of the object in program. No two objects share the same object_id.
  • You don’t need to collect it into another variable, I just put it there for demonstration pursepose.

What is the purpose of including these? It makes it easier for the programmer to judge the intention of the method.

Capital Letters Please

Ruby has a naming convention for constants and classes. These should begin with a capital letter, and follow any series of alphanumeric characters or the underscore. There are no other way to define constants. define() or #DEFINE does not exist in the syntactical world of Ruby.

Magic Eight Ball 8ball responds: It is certain.

For word delimiters, constants use an underscore (RUBY_VERSION), and classes use camelcase (ActiveRecord).

Here is an example (done within irb) of trying to declare a class that doesn’t start with an uppercase letter.

>> class terror
>>   end
SyntaxError: compile error
(irb):5: class/module name must be CONSTANT
        from (irb):2
        from :0


Magic Eight Ball 8ball responds: Outlook not so good.

Bad. Ruby simply complains! You are doing a bad thing! And bad things come from bad people! Therefore you are a bad person and should be condemned to the fires of SyntaxError Hell! We are not writing Manglish people.

Conclusion

Anyways, just some tips to keep your code looking beautiful throughout the years. Heart

Out of curiosity, are you a “undisciplined_underscore_utopian” or a “CamelCaseConspirator”?

Notes:

  1. This is one of the few lines I can recall from Shakespeare’s plays
  2. Thats right, I’m looking at you Manglish speaking people.
  3. Coding conventions, do not guarantee readable code. You can still make spaghetti code following these conventions.
  4. Actually Ruby has many many ways to do one thing. This is both a pro and a con.
  5. These conventions doesn’t mean Ruby is rigid.
  6. Or other wise known as Descriptive Methods
  7. Of course its up to the person to be familiar with the vocabularly

Comments

Ruby and Metaprogramming

Metaprogramming is something that Ruby developers always get so giddy about. Perhaps because it invokes a high level of power and control over the programming language.

Some would deem it unworldly, unsafe, and perhaps even insane.

Background Behind Metaprogramming

The first paragraph by Wikipedia describes well what Metaprogramming is all about.

Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data or that do part of the work during compile time that is otherwise done at run time. In many cases, this allows programmers to get more done in the same amount of time as they would take to write all the code manually.

Note: Emphasis by me

We’ve all heard about code generating code. For example defining a database schema in Propel (a PHP ORM) and letting that create the files, clsases, and all sorts of things, even the SQL for you to setup your table.

But, Metaprogramming is not that.

It’s about doing it on the fly, while the program is executing.

Similarly like Open Classes, metaprogramming is not commonly found in all languages. In fact in languages that support it, people don’t tend to use it.

Metaprogramming is how Rails does alot of its magic. Associations (belongs_to, has_one, has_many), Acts As (acts_as_list, acts_as_nested_set, acts_as_tree). In fact its not just limited to these, but these are the first ones that come to mind.

Don’t worry if you don’t grok what metaprogramming is at first. Most people didn’t, including myself. In fact, I think this post can be improved, and I’ll try my best to make it a valuable resource.

Simple Example

For starters attr_accessor, attr_reader, and attr_writer are actually class methods. These class methods creates instance methods to access/read and mutate/assign the instance variables of the symbols stated.

  • attr_accessor — Creates both accessor and mutator methods
  • attr_reader — Creates only the accesor method
  • attr_writer — Creates only the mutator methods

This is the fully expanded version:

Note:

  • @variable refers to an instance variable
  • We don’t need to explicitly state ‘return as the last statement is always returned

So the 4 lines of code, expands into a 25 lines. Both blocks of codes, do the exact same thing but the first one is much more readable and maintainable.

Execution Within Classes

Actually code inside the class executes normally. If you want, you can have an if condition in there. Its legal space for you to call functions, and do other magic.

Note:

  • variables starting with a dollar sign ($) are global variables
  • The self in def.self.something, refers to the class, as we are in the class scope. If it was inside a instance method, it would refer to the instance scope. This declaration is creating a class method.

When trying to execute this class with:

The output is:
I’m in the User class, executing your code!
I’m done executing your code, and getting out of your class!
I’m a Class Method
Error: undefined method `something’ for # (NoMethodError)

The first two line you see are the execution class executing those lines.
In the third line we call the class method.
In the fourth line we attempt to call the instance method, but it fails. Because the condition never allowed it to be created.

When we set the $condition to false. This is the following output:

I’m in the User class, executing your code!
I’m done executing your code, and getting out of your class!
Error: undefined method `something’ for User:Class (NoMethodError)

It only outputs three lines, as its expecting a class method to exist, but due to the if condition, it was never created. Though the instance method will execute just fine.

Note: This is only sample code, you can do funkier things with it. It is simply to show that the execution follows within the class itself.

eval

Some may consider eval to be a sin! It lets you execute a string as if it was normal running code. That doesn’t make it evil, but it can cause unexpected results if those strings are magically composed together, and didn’t come out as you expected it to be.

Note: The method respond_to? is to test whether the object will “respond to” a method call, in this case kazaam. It returns false first because the method hasn’t been created yet.

In this example the MagicLamp creates a instance method only when the class method remember_incantation is called. The instance method corresponds to the incantation that the MagicLamp was told to remember.

class_eval, instance_eval, module_eval

Ruby has several evals (which make it even more confusing). eval, class_eval, instance_eval, module_eval.

Why does someone need so many evals? They each execute the code within a certain context, class, instance, or module, or whatever. I won’t go into further details, but its good to be aware that they exist.

The Rails Example

So here is another Rails Example using both Open Classes and Metaprogramming to make life easier ™. As you are aware, there exists the attr_accessor, attr_reader, and attr_writer for instance variables. But these methods only exist for instance variables. How about for class variables? How dare they discriminate such variables! But don’t worry. With the power of Ruby you can easily fix this…mixup.

So here is an example from the ActiveSupport (v1.4.2 — corresponds to Rails v1.2.3) libraries located at activesupport/lib/active_support/core_ext/class/attribute_accessors.rb File

So my dear readers, how many of you understand that? Raise your hands now! Good, good, now for those of you who don’t understand. Let me guide you.

The first line indicates that we are working with the class Class. Class is the class, that all classes belong to. So a String class is actually an instance of the Class class. Grok that? If not, try having a look at my post on Everything Is An Object In Ruby.

So in this block of code, we are defining 3 methods: cattr_reader, cattr_writer, and cattr_accessor.

cattr_accessor is the easy one. It just calls the other two methods. The asterisk (*sym) in an arguments list indicates that it wants all arguments from this current argument forward to be collected in an array variable, in this case sym.

If you are having a problem understanding that, pull up irb and try the following:

cattr_reader iterates through the array, and calls class_eval with the arguments for <<-EOS, __FILE__ and __LINE__.

The <<-EOS is referred to as a heredoc, another method of creating strings without using the single or double quotation marks. To indicate the end of the string you enter the first characters preceding the heredoc (EOS), which yup, you’ve guessed it! It stands for “End of String“. These characters can be anything really.

__FILE__ and __LINE__ are magic constants. They aren’t exactly constants per se, but indicate the current state of the execution, in which file and line it currently is in.

So class_eval is taking in a very large string which describe three components.

The first section tests to see if the class variable has been created, and unless it has, it is assigned the value of nil. @@variable refers to a class variable.

The second section creates the class method to return the value of the class variable.

This final section creates the instance method to return the value of the class variable.

So whenever you call cattr_reader from an executing class. These class variable is created, unless it already has, and the class and instance methods to access that variable is created as well.

cattr_writer is slightly different in that it also accepts options, via the last argument being an Hash.

If the Hash is the last element in the array, it is simply popped off.

Here we are creating the class method to write to the class variable.

What you see here is actually a block whose result will be outputted as a string. Inside the block, you’ll actually see the string contents, where it declares the method to be created. But at the very end you’ll notice the unless condition, which is where the options come into play. So unless you specify a :instance_writer => true, in your arguments an instance method will be created allowing to access the class variable

Well that pretty much describes the whole file.

How to use this then?

Note: Due to its brevity, this example sucks big time and it can be highly improved. But I can’t think of one now. I’ll replace it later.

Conclusion

You can do some really sweet things with Metaprogramming, but the examples here are not sufficient to describe what you can do. They are too succinct, and don’t give a context on how it is to be used. But I hope this provides a helpful insight to the existence and usage of Metaprogramming.

At least you know that Metaprogramming exists, so if ever need be. Ruby is there for you.

Comments (5)

« Previous entries