Posts Tagged ‘Programming’

Stop Bitching: Use the Tools You Want

Posted in Programming on December 18th, 2011 by Aviv Ben-Yosef – 1 Comment

Continuing on the thread of the Autonomous Craftsmanship Core, we reach another problem: “they” just won’t let you use the right tool, or in the right way. As I’ve said in the previous posts if anything is so bad you can’t work with it – leave; otherwise, you gotta learn how to make do.

A pragmatic programmer uses the right tool for the job. We all know that if you have a hammer, every problem looks like a nail. In this post I’m talking about the situation where you have an awesome toolbox right there and yet they’re forcing you to unscrew something with your pinky’s nail. Excruciating to your brain.

The thing is, a lot of the times you can just use the right tools and the hell with everyone else. Yes, you can’t just write code in whatever programming language you want, but in a lot of other situations, you can do what you want to. I think this is best shown with a few examples:

“Don’t commit too much. Say once a day”

That’s a real quote a friend’s boss told him. Turns out committing multiple times a day is too messy. Most programmers might just sulk and do as they’re told, but with today’s technology you’re no longer bound to these stupid rules. Your team uses subversion? So what! You can use Git locally, do whatever you like, and just push once a day everything via git-svn. Same solutions are available for just about any VCS combination you can think of! I’ve done this several times working on projects with a VCS I didn’t want to mess with.

“We can’t have a CI server”

Why would someone be against that? Maybe your company doesn’t want to allocate a new server for such a “useless” thing, or maybe the system admins don’t have time for your little “developer toys.” Lucky for everyone, it’s no longer the case that you need complex setup for such stuff. It’s just a matter of looking around. For example, if you’re doing open source you just need to give Travis a look and see you’re suddenly all set. On the other hand if you’re code isn’t open sourced setting up a local Jenkins server is so so easy. You just double click a file and you’ve got it running. If your build isn’t too CPU hogging, you can run it on your box! And I’m almost certain you can find some server with some spare cycles to install it on.

Autonomous Craftsmen Make Do

That sums it up. A craftsman’s gotta do what a craftsman’s gotta do.

You should subscribe to my feed and follow me on twitter!

Your Brain Cares About Code Style

Posted in Programming on December 10th, 2011 by Aviv Ben-Yosef – 8 Comments

My first team had (among many other great attributes) the custom of strictly following a style guide. It was followed so religiously, I’ve yet to come across another place that does so to the same extent. It wasn’t really written down anywhere, but after a couple of weeks of pairing with the other guys you got it.

What does that mean exactly? It means that we wrote code that looked, to a large extent, like it was written like the same guy. We put 2 blank lines between regions. Members had a specific way of documenting. We even used the same idioms for creating empty lists etc. (Java).

If we paired with someone and saw him indent the code the wrong way, we’d go all OCD until it was fixed. And it was regarded totally OK. We didn’t feel like we were nitpicking on each other. It was the way things got done. I even know a guy that would notice extra whitespace at the end of lines (without any IDE help).

Ever since, whenever I see code written with careless indentation and whitespace I feel like the coder who wrote that just doesn’t care enough for the craft. Yes, No Whitespace – No Care!

What’s the big deal?

If code isn’t written in a consistent style in your team, whenever you come across code with the spacing a bit wrong, the first thing your head’s going to process is “I didn’t write this.” This is a natural feeling, and as we all know coders have a hard to restrain impulse to rewrite any piece of code they didn’t write. Once all the code looks the same, that feeling isn’t that hard and you can actually focus on the code itself and have a better sense of ownership. I know, it sounds stupid, but that’s the way our stupid minds work in.

A big part of the Extreme Programming principle Collective Code Ownership is obtained by simply keeping a consistent style. Anything important enough to become a core value of the only methodology that works must be worth the effort to take notice of.

The next time you see code with reckless spacing, change it and let your teammates know. It might be hard at first but the end goal is important – the ability to fluidly read code, without feeling like you’re wearing someone else’s shoes.

You should subscribe to my blog and follow me on twitter!

Stop Bitching: Write Those Damn Tests

Posted in Programming on November 28th, 2011 by Aviv Ben-Yosef – 2 Comments

Diving deeper into the idea of the Autonomous Craftsmanship Core, this time I’d like to talk about one of the first problems a lot of developers face when wanting to start doing clean code.

You read Uncle Bob’s Clean Code, or went to a talk and then go all “Next day at work I’m gonna write tests!!” Then you come to work, and you give the “let’s write tests man!” speech to your teammate, and he just yawns, and slowly the rush fades.

Lots have been written before about introducing tests to a team as a grunt, but I’ll do a quick recap:

You don’t have to ask anyone in order to start and write some tests. Write that first test. Make it pass. Commit. Not that hard, isn’t it?

Usually the next problem is that if no one else on your team runs the tests, they will keep breaking. But can you blame your team? You need to make them understand that running the tests will actually get them something.

For example, I’ve seen that after someone makes a commit that breaks the tests because of a bug, coming over to him and telling him what went wrong and how you found out might make him more interested in the idea of testing. A friend recently told me that he made running tests as simple as a double-click for the developers that don’t write tests. Once it got that easy, they started running them because everyone likes knowing that what they wrote works.

What if your boss won’t let you write tests? Frankly, why the fuck should your boss care? Does he also tell you when to use “while” instead of “for”? I don’t find things such as these to be something any boss should decide about. As I’ve said in the first post, if you find yourself in a place so resistant to change, leave. If you have to stay, do what you have to do. If they won’t let you commit your tests to source control or set up a continuous integration machine, there are solutions, which I’ll discuss on my next post.

In the mean time, focus on writing tests that help your teammates find problems and see how slowly your little tests get more and more traction. It’ll work, because Success begets attention!

You should subscribe to my feed and follow me on twitter!

Stop Bitching: the Autonomous Craftsmanship Core

Posted in Programming on November 12th, 2011 by Aviv Ben-Yosef – 3 Comments

A lot of developers I know keep bitching about how their team isn’t as passionate as they’d like it to be, or about their boss not letting them do things like it should be done. They get into this habit and never advance in the right direction because something is holding them back. I know this situation well, I’m usually one of these guys.

In the spirit of Positivember I’d like to tell you a secret. You can stop whining and start improving. You don’t have to wait for all the stars to align. That cliché about changes starting from yourself is actually right.

I’ve heard almost every complaint in the book:

“My teammates don’t write tests.”
“They won’t let me have a continuous integration server.”
“I can’t use Git.”
“My boss hates it when I make a lot of commits.”
“I was told not to write tests.”
“We’re not doing agile development.”
“I can’t do pair programming.”

If everything above applies, or you really have lots of problems like these, just quit. A developer that really cares about these things usually can find a better job easily. But, if it’s only some of these, remember that no work is perfect. There will always be suboptimal stuff to live with. The trick is not to be all bitter about it, but to actually try and make changes happen, slowly, so you still have fun.

Most if not all of these problems are things you can work around, technologically, mentally or socially. If you just stick to your good ways, you’ll eventually get some followers too.

Step up and realize that everything can start by you and your habits. An Autonomous Craftsmanship Core as I like to call it. Sometimes, you core will seem so awesome from the outside that people will join in on some of your practices. Sometimes it will go unnoticed and you will happily go on programming better and better.

I will blog more on tackling some of the problems I mentioned above, but as a starting point I recommend Apprenticeship Patterns and Driving Technical Change. These great books help a lot in accepting that fact you should take matters into your own hands, and stop bitching.

You should subscribe to my feed and follow me on twitter!

Stepping Up: Do the Pre-Commit Skim

Posted in Programming on November 5th, 2011 by Aviv Ben-Yosef – Be the first to comment

I’m always looking for the easiest way to make my code better, or to train myself to pay more attention to the quality of the code I produce. My latest find is quite obvious yet so very powerful I had to share. Simply put, it’s just going over your code once more before a commit.

Every once in a while, I commit code and forget to add a file. Even worse, I sometimes leave around dead code that I really hate. I’ve found out that simply making a mental note to go over every file I changed before making a commit makes a big difference. It seems like the Boy Scout Rule from Clean Code is a special case of this rule.

The trick is to simply go over every file you’ve changed and look for common pitfalls:

Unused code – Are there methods your changes just made obsolete? Maybe a conditional with an “else” clause that can no longer happen? Delete code! It’s the best code you’ll write today!

Zombie code – Did you start with something that was too complex and is no longer needed? Often in retrospect you can see how to simplify something and spare your colleagues the woes of zombie code.

Overdue refactoring – Look at your changes. Are you pushing a method too far? Maybe making a class too bloated? Maybe it’s time to for some cleaning.

Do you have a better name for it now? Sometimes when you start with something you don’t have a great name for it. After finishing it, you might be able to slap a better name on that class that will make it more obvious to everyone.

Any dangling TODOs? I hate committing TODOs unintentionally.

Make sure it’s all coherent in class-level – Some changes make sense when you’re knee-deep in a change. But step back and make sure it all still makes sense.

 

You should subscribe to my feed and follow me on twitter!

Fight Zombie Code

Posted in Programming on October 28th, 2011 by Aviv Ben-Yosef – 2 Comments

If there’s anything I hate more than dead code, it’s zombie code. Dead code is code that’s remained in the system even though it’s no longer really used.

It might be small, like unused imports, instance variables and methods. It can be whole classes that make up entire features no longer used.

The biggest PITA is when you’re not really aware of the fact the code’s dead and unused, sitting there and occupying precious bits, and stumble across it as part of a task, trying to understand how it influences what you want to do next.

Whenever I recognized something that looks like dead code but I’m not entirely sure, I find it pretty easy to delete it quickly, once I take a look in the version control logs and see when it became no longer in use and why.

Zombie code is code that was never alive, and so couldn’t really become dead. It’s the undead code – code that died right when it was committed. Code that never ran or never worked. The are two reasons I hate zombie code more than “plain” dead code.

The first reason is that it simply wastes more of my time. Looking back in version control won’t help me see the commit in which the code was “decommissioned”, it would just appear to always sit there. That means I have to take extra care to verify that it, in fact, never worked.

The second reason is that it’s plainly someone saying he doesn’t give a damn. I mean, let’s put aside TDD. Heck, let’s put aside unit testing at all. It means the code never even ran the damn thing and saw in his own eyes it did what he claims it did.

Be kind to your teammates. If you’re not a good enough coder to test it, at least see that it runs once in your own eyes.

 

You should subscribe to my feed and follow me on twitter!

TIL: Ruby Classes that Look Callable

Posted in Programming on October 18th, 2011 by Aviv Ben-Yosef – 4 Comments

One of the concept I had to get used to moving from Python to Ruby was that regular objects aren’t callable, and that there was a closed set of objects that can be called. Meaning that where in Python it was possible for any class to implement __call__ and so allow us to call it with obj(), Ruby doesn’t allow this. One of the advantages of that syntax in Python is that each class implements its constructor using this. For example:

class MyClass:
    def __init__(self, value):
        self.value = value

my_class = MyClass(1) # We are calling the class to get
                      # an instance, instead of
                      # MyClass.new(1) in Ruby

This was a nice little trick I liked in Python but quickly got used to living without it. That was until I saw Ruby code that seemed to allow the exact same behavior:

Integer.class
#=> Class

Integer(1)
#=> 1

How’s this so? Can we really make classes callable? A quick glance at Integer’s source code in the Rubinius code reveals that there’s no magic going on in it, and that it actually has no reference for this method I’m looking to call. Instead what we’ll see is that alongside the class definition there’s also a method definition:

class Integer
  #...
end

def Integer(value)
  #...
end
view raw integer.rb This Gist brought to you by GitHub.

So the whole trick is simply to define both. But how exactly does this work? How are names not clashing?

What actually happens is that whenever we define a new class or module, its name is added as a constant that points to the actual class. Similarly, when we define a method at the top level it’s added as a private method to Object. That means that whenever we type in a name that looks like a constant (starts with a capital letter) without parenthesis, Ruby will search for that constant:

Object.const_defined? :Integer
#=> true

But when we add parenthesis, Ruby understands that it should seek for a method instead:

Object.private_method_defined? :Integer
#=> true

This nifty little trick is all it takes for Ruby to allow this nice syntax.

Hope you learned a new thing! In case you want to dig deeper, two great books that really helped me wrap my head around dark corners of Ruby are Eloquent Ruby and Metaprogramming Ruby.

You should subscribe to my feed and follow me on twitter!

Submitting your first patch to Rubinius

Posted in Programming on October 11th, 2011 by Aviv Ben-Yosef – 1 Comment

I always love helping interesting open source projects, and Rubinius is one of those great projects that are very cool to play with. In case you don’t know it, Rubinius is a Ruby implementation written (almost) entirely in Ruby. Just playing with such a code base is quite interesting and whenever a peek around in the code I learn new stuff about Ruby.

At the moment, the people at Rubinius are working hard on making it compatible with ruby 1.9, and so there are a lot of easy changes that are waiting for you to do and start contributing. I’d like to show you a quick walk-through of how to find such simple tasks and get started.

Setup

Clone the project from the GitHub repo. Once that’s done, to make sure that everything works properly do this:

./configure
rake spec

The specs should be all passing on your machine. It will take a few minutes the first time, but afterwards whenever you make small changes it will be faster.

Finding interesting work

Of course you can submit whatever patch you find interesting, but in my opinion a quick way to get started is to find incompatibilities with 1.9. Fortunately for you, it’s pretty easy to find those.

Rubinius, along with the other Ruby implementations, uses mspec in order to have written specs of the language written in Ruby and is checked against that. These specs are similar to RSpec. Among other options, some specs are simply marked as having to pass only on Ruby 1.9 and of these, those that are currently failing are our hunt.

I came up with this command in order to find and execute such 1.9 specs that were last reported by Rubinius developers to be failing:

bin/mspec tag --list fails -tx19 :ci_files

This command will list the RubySpecs that are tagged as failing on Rubinius in 1.9 mode.

You should see plenty (at the time of this writing, over 500) of failing specs. Just pick something that seems easy enough to get started with.

Once you spot a spec that looks interesting you can run it specifically and see the code. For example, if you see an interesting spec for String#squeeze, you can run it with:

bin/mspec -tx19 spec/ruby/core/string/squeeze_spec.rb

Doing some work

For example, let’s look at one of the really simple specs I decided to get passing, you can see the commit here. I wanted to make a simple change to the String#ord method, but only on 1.9 version. The way to do that on Rubinius is that many of the files, say string.rb now have also “string18.rb” and “string19.rb” that contain the code that differs. In my case, I just made a simple change to the version used on 1.9 by editing the ord method on the string19.rb file (in case the 19 and 18 files don’t exist yet, you can simply create them like shown here).

After you’ve made your changes, be sure to run the specs again and see that everything works. Before submitting it, you should make sure to run all specs thoroughly using the command rake spec. If all is well, just do the regular GitHub pull-request dance and off you go!

Further than that, you can include in your pull request another commit that removes the failing tags from the specs you’ve just fixed. Find the appropriate file and just remove it, as you can see in this commit.

For some more in depth review of how to start contributing to Rubinius, see this excellent post on the official blog.

You should subscribe to my feed and follow me on twitter!

When being idiomatic wears you out

Posted in Programming on August 27th, 2011 by Aviv Ben-Yosef – 13 Comments

I believe that when learning a new programming language, it’s really important to learn its idioms and use them. I’ve written procedural C-like code in Java, and bloated Java-like code in Python, but only once you start using a language “like it was meant to” can you really say you’ve started mastering it. Had I not read Effective Java I don’t think I could have ever written a sensible line in this language.

I practically cringe whenever I see someone creating a new list in Java and then adding to it a single element when he just could have used Collections.singletonList(element). I’m that kind of a fanatic.

But, lately I’m getting worn out of being verbose. Yes, you can use the trick above to save a line of code and a lot of typing, but damn it – I just want to say [element]!

Less than a month into BillGuard we realized we don’t want to do all of our coding in Java and started calling Python code from Java (not in the JVM though, since Jython just doesn’t seem solid enough). Running away from Java’s notoriously long idioms, we preferred adding the overhead of having multiple programming languages in one project (which I think justified itself plenty, but it is an overhead).

This solution helped us when doing big stuff we didn’t want to do in Java, stuff that we’d represent in a unique class. But the smaller stuff just kept nagging us. We kept finding ourselves writing 10-15 lines of code to do something we thought trivial and then putting a 1-2 lines of comments before it saying what we actually meant in Python. These eventually lead to a lot of extracted methods which are generally good, but rarely would I extract such logic in Python/Ruby – where it would be a single concise line of code.

Lately, we started toying with just saying “screw the idioms” and doing what feels right. If that means having a JavaSucksUtils class with methods such as zip() and defaultdict_int() so be it. I think that with time this will lead to using a wholly different language in the JVM mostly, but in the mean time this seems to be a nice transition.

I mean, common:

// Why write this..
public static <T, V> Map<T, List<V>> defaultdict_list() {
    return new MapMaker().makeComputingMap(new Function<T, List<V>>() {
        @Override public List<V> apply(T unusedCrap) {
            return Lists.newArrayList();
        }
    });
}

# When you just want this (Python)
defaultdict(list)

# Or this (Ruby)
Hash.new {|h,k| h[k] = []}
view raw gistfile1.txt This Gist brought to you by GitHub.

Now we’ll have to wait and see where this gets us.

You should subscribe to my feed and follow me on twitter!

Guest Post: Lookup Tables with Ruby-on-Rails

Posted in Programming on August 9th, 2011 by Aviv Ben-Yosef – Be the first to comment

This is a guest-post by Nimrod Priell (@nimrodpriell) about the kind of time-saving tricks that I’m amazed are so easy to pull off in Rails

If you want to have an ActiveRecord macro to define memory-cached, dynamically growing, normalized lookup tables for entity ‘type’-like objects, read along. Or in plain English – if you want to have a table containing, say, ProductTypes which can grow with new types simply when you refer to them, and not keep the Product table containing a thousand repeating ‘type=”book”‘ entries – and gain some insight into ruby metaprogramming techniques – sit down and try to follow through.

A normalized DB means that you want to keep types as separate tables, with foreign keys pointing from your main entity to its type. For instance, instead of:

ID car_name car_type
1 Chevrolet Aveo Compact
2 Ford Fiesta Compact
3 BMW Z-5 Sports

You want to have two tables:

ID car_name car_type_id
1 Chevrolet Aveo 1
2 Ford Fiesta 1
3 BMW Z-5 2

And

car_type_id car_type_name
1 Compact
2 Sports

The pros/cons of a normalized DB can be discussed elsewhere. I’d just point out a denormalized solution is most useful in settings like column oriented DBMSes. For the rest of us folks using standard databases, we usually want to use lookups.

The usual way to do this with ruby on rails is:

  • Generate a CarType model using rails generate model CarType name:string
  • Link between CarType and Car tables using belongs_to and has_many

Then to work with this you can transparently read the car type:

car = Car.first
car.car_type.name # returns "Compact"

Ruby does an awesome job of caching the results for you, so that you’ll probably not hit the DB every time you get the same car type from different car objects.

You can even make this shorter, by defining a delegate to car_type_name from CarType:

# car_type_name.rb
delegate :name, :to => :car, :prefix => true

And now you can access this as

# car_type.rb
car.car_type_name

However, it’s less pleasant to insert with this technique:

car.car_type.car_type_name = "Sports"
car.car_type.save!
#Now let's see what happened to the OTHER compact car
Car.all.second.car_type_name #Oops, returns "Sports"

Right, what are we doing? We should’ve used

car.update_attributes(car_type: CarType.find_or_create_by_name(name: "Sports"))

Okay. Probably want to shove that into its own method rather than have this repeated in the code several times. But you also need a helper method for creating cars that way…

Furthermore, ruby is good about caching, but it caches by the exact query used, and the cache expires after the controller action ends. You can configure more advanced caches, perhaps.

The thing is all this can get tedious if you use a normalized structure where you have 15 entities and each has at least one ‘type-like’ field. That’s a whole lot of dangling Type objects. What you really want is an interface like this:

car = Car.first
car.car_type #returns "Compact"
car.car_type = "Sports" #No effect on Car.all.second, just automatically use the second constant
car.car_type = "Sedan" #Magically create a new type

Oh, and it’ll be nice if all of this is cached and you can define car types as constants (or symbols). You obviously still want to be able to run:

CarType.where(:id > 3) #Just an example of supposed "arbitrary" SQL involving a real live CarType class

But you wanna minimize generating these numerous type classes. If you’re like me, you don’t even want to see them lying around in app/model. Who cares about them?
I’ve looked thoroughly for a nice rails solution to this, but after failing to find one, I created my own rails metaprogramming hook.
The result of this hook is that you get the exact syntax described above, with only two lines of code (no extra classes or anything):

In your ActiveRecord object simply add

# car.rb
require 'active_record/lookup'
class Car < ActiveRecord::Base
#...
include ActiveRecord::Lookup
lookup :car_type, :as => :type
#…
end

That’s it. the generated CarType class (which you won’t see as a car_type.rb file, obviously, as it is generated in real-time), contains some nice methods to look into the cache as well: So you can call

CarType.id_for "Sports" #Returns 2
CarType.name_for 1 #Returns "Compact"

and you can still hack at the underlying ID for an object, if you need to:

car = Car.first
car.car_type = "Sports"
car.car_type_id #Returns 2
car.car_type_id = 1
car.car_type #Returns "Compact"
car.find_car_by_type_and_color("Compact", :blue) #Works, the underlying search is done by the ID

The full source code and gem can be found in https://github.com/Nimster/RailsLookup . The gem is named rails_lookup so you can just `gem install rails_lookup` to get the functionality required.

Note you do need to create tables for the new Type classes. The table format is very simple:

create_table :car_types do |t|
t.string :name
end
add_column :cars, :type, :integer

In this post, however, I would like to elucidate how this is achieved, hopefully teaching some ruby meta-programming and rails considerations on the way.

So how do we achieve that? Well, we start with creating our own Lookup module which can be included into active record classes:

module Lookup

  module ClassMethods
    #Any new "macros" go here
    def lookup(lookup_name)
    end
  end

  def self.included(host_class)
    host_class.extend(ClassMethods)
  end
end
view raw gistfile1.rb This Gist brought to you by GitHub.

This is the basic setup for inserting a new “macro” like belongs_to (which is actually a simple class method). When the Lookup module is included in a class, the ruby interpreter will call the hook method “self.included” with the class this was included into. We ask to also extend this class, thereby adding any class methods defined in ClassMethods into it.

We can now call “lookup :car_type, :as => :type” in our Car class, only that it doesn’t do anything. Let’s make it do something. We need to achieve the following things:

  1. Create the CarType ActiveRecord
  2. Link the CarType and Car ActiveRecords (with the standard has_many, belongs_to link)
  3. Make the Car#car_type=, Car#car_type methods behave in the way we described above.
  4. (Optional) code-fill the caches when the class loads from the data in the DB

We will now present the code for each – when you read through, remember this all runs in the host class context (e.g. Car) so that self is the Car class, and any actions we take are equivalent to having explicitly written them in the Car class itself.

    def lookup(as_name)
      mycls = self #Class I'm defined in
 
      #We now define the CarType class, as if we were in a file car_type.rb
      cls = Class.new(ActiveRecord::Base) do #Define a new class, extending AR::Base
        #CarType should have the has_many :cars link
        has_many mycls.name.tableize.to_sym

        #These are optional. You can define any additional constraints you like.
        validates_uniqueness_of :name
        validates :name, :presence => true

        #Methods for using the cache. Providing a second argument saves data into the cache.
        def self.id_for(name, id = nil)
          #We cannot access the class variable for CarType as simply '@@rcaches' because it will
          #look for @@rcaches in the scope of the module we're in.
          class_variable_get(:@@rcaches)[name] ||= id
        end

        #This helper method is the "find_or_create" of the class that also
        #updates the cache and the DB.
        def self.gen_id_for(val)
          id = id_for val
          if id.nil?
            #Define this new possible value
            new_db_obj = find_or_create_by_name val
            id_for val, new_db_obj.id
            name_for new_db_obj.id, val
            id = new_db_obj.id
          end
          id
        end

        #Query the cache for the value that goes with a certain DB ID
        def self.name_for(id, name = nil)
          class_variable_get(:@@caches)[id] ||= name
        end
      end

      #Finally, Bind the created class to a name
      lookup_cls_name = lookup_name.to_s.camelize
      Object.const_set lookup_cls_name, cls #Define it as a global class
view raw gistfile1.rb This Gist brought to you by GitHub.

The important parts to note here are:

  • How we define a new class and then bind it to the constant “CarType” so that after a class containing the lookup (like Car) is referred to (just calling Car.to_s is enough), the CarType is not accessible as if it were inside of a car_type.rb file in our app/models directory.
  • How we use Rails’ built-in Inflections module which it mixes in to string, to move from so-called “table_notation” to CamelNotation and vice versa.
  • How we use class_variable_get and class_variable_set to access the class variables of the newly created CarType class – because confusingly enough @@var will refer to the class we’re in now and not the one being defined inside the block, when the code is executed. We discuss initialization of these two variables later on, during part (4).
Side note: This is not the complete class definition – I shortened it a bit to remove details which are handled in the gem version, like supporting Rails’ where() methods, support anonymous classes that have lookups and supporting multiple classes using the same lookup. If you’re interested in these, I urge you to check out the gem.

Note also that we have already included the has_many link inside of CarType. In the same way, we will include the belongs_to in the other direction. We do this and also define the special accessors for getting and setting the CarType as a String:

   def lookup(as_name)
     #...

     #Now, define the foreign key from Car to CarType.
     belongs_to lookup_name.to_s.to_sym, :foreign_key => "#{as_name}".to_sym
     validates "#{as_name.to_s}_id".to_sym, :presence => true

      #Now we define the "delegates" that will allow us to just set call car.car_type = "Sports"
      #Define a setter for car_type
      define_method("#{as_name.to_s}_id=") do |id|
        #We would have used instance_variable_get. However rails maintains a hash of attributes
        #that we must use to play nicely along with rails. Here we write the ID of the value
        #instead of the value itself inside the field.
        write_attribute "#{as_name.to_s}".to_sym, id
      end

      # Setter via String
      define_method("#{as_name.to_s}=") do |val|
        id = cls.gen_id_for val
        write_attribute "#{as_name.to_s}".to_sym, id
      end

      # Getter for the ID
      define_method("#{as_name.to_s}_id") do
        read_attribute "#{as_name.to_s}".to_sym
      end

      #Define the getter
      define_method("#{as_name.to_s}") do
        id = read_attribute "#{as_name.to_s}".to_sym
        if not id.nil?
          value = cls.name_for id
          if value.nil?
            # This is reached in case many processes use the DB and some other process
            # inserted a new value that we were not aware of, but who's ID was inserted
            # into this object.
            lookup_obj = cls.find_by_id id
            if not lookup_obj.nil?
              cls.name_for id, lookup_obj.name
              cls.id_for lookup_obj.name, id
            end
          end
        end
        value
      end

    #...
  end

view raw gistfile1.rb This Gist brought to you by GitHub.

The important thing to note here is how we employ ActiveRecord’s read_attribute and write_attribute. The data in your ActiveRecord is maintained in a hash called attributes where the names of fields (in the DB) are saved along with their values. A classic setter method like `car.car_type = “Compact”` would set an attribute entry in the hash with :car_type => “Compact”, which will later cause SELECT or INSERT statements to try and access the in existing column car_type. Our approach is to intercept every time the ‘type’ attribute is being written (with a String), and replace that String with a numerical ID (meanwhile creating the corresponding CarType entry if necessary).

Finally, prefill the caches from the DB when this class loads. This is optional but as the list of types is likely to be rather small, a real-time expanding cache is just wasting some user time and could be better done ahead.

    def lookup(as_name)
      #...

      all_vals = cls.all
      cls.class_variable_set(:@@rcaches, all_vals.inject({}) do |r, obj|
          r[obj.name] = obj.id
          r
        end)
      cls.class_variable_set(:@@caches, all_vals.inject([]) do |r, obj|
          r[obj.id] = obj.name
          r
      end)
    end
view raw gistfile1.rb This Gist brought to you by GitHub.

That’s it. If you don’t like the caching this becomes even easier – remove all of the references to @@rcaches and @@caches and you simply saved yourself the trouble of manually maintaining CarType objects.

The only remaining thing is to define your migrations for creating the actual database tables. After all, that’s something you only want to do once and not every time this class loads, so this isn’t the place for it. However, it’s easy enough to create your own scaffolds so that a command like

rails generate migration create_car_type_lookup_for_car

will automatically create the migration. This is the required migration

class CreateCarTypeLookupForCar < ActiveRecord::Migration
  def self.up
    create_table :car_types do |t|
      t.string :name
      t.timestamps #Btw you can remove these, I don't much like them in type tables anyway
    end

    remove_column :cars, :type #Let's assume you have one of those now…
    add_column :cars, :type, :integer #Maybe put not_null constraints here.
  end

  def self.down
    drop_table :car_types
    remove_column :cars, :type
    add_column :cars, :type, :string
  end
end
view raw gistfile1.rb This Gist brought to you by GitHub.

I’ll let you work out the details for actually migrating the data yourself – this post has already ran long enough. I urge you to read more in the gem’s source code here. There are some tricks I’ve omitted to make rails be able to support calls like Car.find_by_car_type_and_color “Compact”, :blue (when the actual SQL query should be asking about car_type_id = 1), and some more options for setting the lookup itself, handling Car.where(type: “Compact”) or multiple classes using a single lookup.

I hope this helped you and saved a lot of time and frustration. I’d like to thank Aviv for hosting me here. If you don’t already, read the rest of his blog, you’re sure to learn something useful! Follow me on twitter: @nimrodpriell