Feb 28

Back in January I announced a small but useful plugin called AppConstants, that basically provides a central place where you can store environment specific constants. And since I started using Rails 3 in the past week, I thought I’d make it Rails 3 compatible.

The code is really simple and - as I expected - the upgrade process was quite straight forward.

I’m not gonna write a guide here on how to upgrade your plugins to Rails 3 - there is plenty about that around the web - but instead, just show the steps I went through to upgrade mine. Similar plugins might have a similar upgrade path.

- Generators

My plugin makes use of a simple generator that copies its default constants file and initializer to Rails.root/config and Rails.root/config/initializers, respectively. In Rails 2.x it was located under Rails.root/vendor/plugins/app_constants/generators/app_constants and it was defined like so:

class AppConstantsGenerator < Rails::Generator::Base
  def manifest
    record do |m|
      m.directory('config')
      m.file('constants.yml', 'config/constants.yml')
      m.directory('config/initializers')
      m.file('load_app_constants.rb', 'config/initializers/load_app_constants.rb')
    end
  end
end

In Rails 3, the generators had to be moved to Rails.root/vendor/plugins/app_constants/lib/generators. Notice the root directory app_constants under generators has been removed as well. And the code was changed to this:

class AppConstantsGenerator < Rails::Generators::Base
  def self.source_root
    @source_root ||= File.expand_path('../templates', __FILE__)
  end  
 
  def copy_config_files
    copy_file('constants.yml', 'config/constants.yml')
    copy_file('load_app_constants.rb', 'config/initializers/load_app_constants.rb')
  end
end

We had three simple changes here:

- The generator now extends from Rails::Generators::Base: This class uses the Thor infrastructure to handle generators. - more info here.

- I had to implement the source_root class method, which basically tells your generator where to find your template files.

- The manifest method is now called copy_config_files - or anything you want.

The way this works is that, once you invoke the generator, Thor will sequentially call all instance methods in your generator class - or the only instance method in the example above. If your generator does a lot, it will allow for a better organization of your tasks.

And that’s it! I did change a couple of other things but that had to be changed anyway and are not related to the migration.

For Rails 2.3.x users, you’ll find a 2.3.x branch on github that should work for you.

Cheers

Tagged with:
Feb 25

Learning new programming languages is fun. And if it’s your 2nd, 3rd…Nth programming language you will eventually look for features you already know and love.

Coming from Ruby - but after having done my fair amount of Java for many years, among other things - I end up looking for features like blocks, open classes and syntax sugar like automatic generation of attribute accessors. These are hard to let go of.

Having decided to learn Objective-C recently, I was delighted to find out that all of these are available - for better or for worse - and wanted to share this analogy with its Ruby counterparts.

- Attribute accessors

In ruby, this class definition

class Person
  attr_accessor :name
end

implements for you the getters and setters of the instance variable name.

In Objective-C, the combination of the @property and @synthesize directives provides you with roughly the same result:

// in the interface file
@interface Person : NSObject
{
	NSString *name;
}
 
@property(retain) NSString *name;
 
@end
 
//in the implementation file
@implementation Person
 
@synthesize name;
 
@end

Now the compiler is responsible for writing those getters/setters for you.

- Open classes & blocks

Blocks in ruby are the structures that allow you to - among other things - iterate over arrays like this:

my_array.each do |item|
  puts(item)
end

Objective-C doesn’t have an ‘each’ method in its root array class (NSArray) but since it does support blocks and open classes, you could just write it yourself:

//in the interface file
@interface NSArray (each)
-(void) each: (void (^)(id *))block;
@end
 
//in the implementation file
@implementation NSArray (each)
 
-(void) each: (void (^)(id *))block {
	for (id *object in self) {
		block(object);
	}
}
@end

Yes, I know the syntax isn’t appealing, but using it in your program is a bit better:

[myArray each: ^(id *item){ 
    NSLog(@"Current item: %@", item); 
}];

Given the syntactic differences, the code above is very similar to its ruby counterpart. Iterating over an array is just one of the many things blocks are useful for. Others might include dealing with files, network sockets etc…

Blocks are powerful structures and are not created everyday, but it’s nice to know that you can resort to them when the time comes. ;)

Tagged with:
Feb 03

What?

In Ruby you have basically two ways of defining private methods:

# this is the first way to do it
class Test
  def say_hello
    puts "I'm a private method"
  end
  private :say_hello
end
 
# and this is the second way
class Test
  #other methods this class might have
  private
  def say_hello
    puts "I'm a private method"
  end
end

I see a small problem with both approaches. In the first one, and the most obvious, is that you need to duplicate the method name as well as add an extra method call - private - just to change its visibility.

The second approach avoids this but adds the risk of accidentally putting a method that is intended to be public under the private section of the source file, which can render an annoying debugging session.

Why?

Personally, I like to have a smooth reading flow in my source files. That means that if the public method_a makes use of the private method_b, I want method_b defined right below its caller, which is possible - but verbose - using the private method call:

class Test
  def method_a
    method_b
  end
 
  def method_b
    puts "I'm a private method"
  end
  private :method_b
end

But can be somewhat harder to accomplish if you decide to split your source file in sections:

class Test
  def method_a
    method_b
  end
 
  #just another public method. We might have several
  def method_c
    method_b
  end
 
  private
 
  def method_b
    puts "I'm a private method"
  end
end

I wanted to be able to define a private method with a single reserved keyword…

How?

What if I could define a private method using this new syntax:

class Test
  def_p say_hello
    puts "I'm a private method"
  end
end

It turns out I can.

Notice the def_p keyword? This is a new keyword I created by changing ruby’s parser and that behaves mostly like the def keyword, except that it defines a private method instead.

If you wanna read the code that allows this behavior and try it yourself, download the patch I wrote and apply it to the ruby source code - I patched version 1.9.1-p376.

After applying the patch, just build ruby as usual:

$ ./configure
$ make

And then try running this script:

class Test
  def_p say_hello
    puts "I'm a private method"
  end
end
Test.new.say_hello

You should see the following output:

pvt.rb:10:in `': private method `say_hello' called for # (NoMethodError)

Happy hacking :)

Tagged with:
preload preload preload