Essence, Ceremony, and Deja-Vu

Posted by Rick DeNatale Thu, 21 Aug 2008 18:13:00 GMT

Stu Halloway just pointed out an interesting article on a Scala blog.

Stu asks us to consider whether making a Scala object an application by extending a trait, as described by the Scala article, affects the question of essence vs. ceremony. It certainly does cut down on boilerplate code.

Although this appears to be part of the standard Scala library, it is documented in such a way as to discourage its use, for the same reasons given in the article.

What strikes me is that the reasons seem to be tied up in language implementation and in particular the ways of the JVM. Perhaps this is an example of how the JVM, at least as it is today might be a good, but not the best platform for dynamic language implementation.

Putting on my old curmudgeon’s hat, this strongly reminds me of the early days of PL/I. The earliest PL/I compilers were notoriously bad at generating efficient code for subroutine linkage. PL/I was designed for the IBM/360, which used a subroutine calling mechanism entailing chaining invocation frames in a doubly linked list rather than on a stack. The brute force way to do a call was to perform a system getmain (OS/360 for malloc) at the beginning of a subroutine, and a freemain(free) upon return. This was fairly expensive.

As a result of this, early PL/I programmers were admonished not to use subroutines/functions, or at least to use them sparingly.

This is not bad language design, it is bad implementation.

And perhaps it is just one example, or maybe there are two here, one in Scala and one in PL/I, of how well meaning decisions based on the characteristics of the implementation at hand, particularly when compounded can give us magnificent complexities, that we really don’t need.

Posted in  | Tags ,  | no comments | no trackbacks

O Canada!

Posted by Rick DeNatale Tue, 01 Jul 2008 11:13:00 GMT

I’ve got quite a few Canadian friends, only partly due to my being an OTI alumnus. So it seems appropriate, albeit completely off-topic, to wish them all a happy FĂȘte du Canada, and a Canada Day Joyeux!

I’m a little surprised that neither the American nor the Canadian google sites seem to have acknowledged today’s date at least as of this writing.

no comments | no trackbacks

Lord Love a Duck!

Posted by Rick DeNatale Sat, 21 Jun 2008 12:08:00 GMT

From one of the many non-Ruby blogs I follow comes this collection of strange duck-types.

A bit off the beaten track for this blog, but, “if it quacks…!”

Posted in  | no comments | no trackbacks

Speaking Tomorrow at Raleigh Ruby Brigade

Posted by Rick DeNatale Mon, 16 Jun 2008 19:16:00 GMT

I’ll be giving a talk on “The Fall and Rise of Dynamic Languages” tomorrow at 7:00 p.m., at Red Hat HQ to the Raleigh Ruby Brigade.

Originally this was going to be a slightly revamped talk I gave some months ago to the local Agile group, with a slight change of emphasis from the history of agile methods to focus more on Ruby and other dynamic languages. It’s morphed into a completely different talk.

I plan to take a journey from the 1970s to today, and compare and contrast static and dynamic languages, and examine the recent resurgence in interest in dynamic languages and virtual machines. Along the way, I’ll have a few things to say about whether or not the recent news from RailsConf about MagLev is hype or reality.

If you’re in the area, please come by. Luckily the salmonella scare will probably keep the supply of (rotten) tomatoes to a minimum, so I should be fairly safe.

Posted in  | Tags , , ,  | no comments | no trackbacks

How Did You Get Started in Programming

Posted by Rick DeNatale Sun, 08 Jun 2008 03:14:00 GMT

Joe O’Brien wrote an article about How he got started in programming.According to Joe, this is a meme started by Michael Eaton, and Sarah Dutkiewicz. It seemed like fun, so here’s my story, in the same form used by Michael and Sarah.

How old were you when you started programming?

I would have been 18 or 19. It was my freshman year in college (1970/71), but I can’t recall whether it was first or second semester, and my birthday is in December.

How did you get started in programming?

Let me go back just a little bit. When I was in high school, I was very interested in music. I’d played in various rock and blues bands since junior high. My high school in Connecticut was part of a program which taught electronic music. This was a time when synthesizers were just coming to the fore. Walter (now Wendy) Carlos’ album “Switched on Bach” had come out in 1968 when I was a high-school sophomore.

So I started at the University of Connecticut in the fall of 1970 and enrolled in the Electrical Engineering School, with the sole intention of becoming the next Robert Moog. All I really wanted to learn was how to design voltage-controlled oscilators and amplifiers.

One of the courses which all freshman engineers at UConn had to take was a 100 level CE course which consisted of one-half semester of “Engineering Graphics” i.e drafting on a board with a T-Square, Triangles and French-curves, and one-half semester of Fortran I programming on an IBM 1620.

That course got me hooked on programming, and my musical career ended in a hurry.

What was your first language?

As I mentioned it was Fortran I, but I quickly became one of those guys who wanted to dabble with every programming language I could get my hands on.

What was the first real program you wrote?

It’s been so long that I can’t really remember. One of the things I remember from school was writing a compiler as a class project. I also remember a computer architecture (hardware) course, taught by grad student with a recent math MS, who I baffled by designing a computer for the term project which had a very simple hardware design, because it was micro-programmed so the main part of the design was actually firmware. The poor guy didn’t really know what to make of it.

What languages have you used since you started programming?

This is probably not a complete list but:

  • PL/I
  • Snobol
  • Lisp 1.5
  • Formac
  • 1620 Assembler Language
  • PDP 8/5 Assembler Language
  • IBM System/360/370 Assembler Language
  • APL
  • PL/S – an IBM internal mid-level language akin to C but with a PL/I like syntax, and a later variant PL/AS
  • Basic – on the APPLE ][
  • UCSD Pascal
  • C
  • Class-C, an object oriented C variant similar to Objective-C which I invented for use within IBM
  • Object Pascal (using MacApp)
  • C++ (as little as possible)
  • Smalltalk – my first real love
  • Java – mostly because I had no choice
  • Ruby – my current love
  • JavaScript – which I’ve decided is my language of the year for 2008.

If you knew then what you know now, would you have started programming?

Only because I can’t figure out how to become a real Rock Star.

If there is one thing you learned along the way that you would tell new developers, what would it be?

Try to get a broad a picture as possible of programming, try to use your knowledge of other languages enhance your learning of new ones instead of inhibiting yourself by misunderstanding how the languages differ from the ones you’ve already used,

What’s the most fun you’ve ever had … programming?

The most enjoyable aspects of programming are the social ones. I was doing pair programming before anyone had coined the term. I remember sessions where two or three guys were working on something, one working the keyboard, one the mouse, and maybe a third kibitzing. Beyond that it’s great to hang out with other programmers whether at local groups or at a conference like OOPSLA or RubyConf and talk about the craft of programming, maybe over a beer or two.

Posted in  | no comments | no trackbacks

Solving the Final Google Treasure Hunt Problem in Ruby

Posted by Rick DeNatale Sun, 08 Jun 2008 01:43:00 GMT

For the past four weeks, Google has been running the 2008 Google Treasure Hunt. Each Monday a new question was asked, requiring a ‘simple’ answer. Actually, each question was parameterized, and the parameters were ‘randomly’ generated for each participant.

For each of the four questions, I wrote a Ruby program to find the answer.

The final question was probably the hardest, and although it’s still ‘alive’, the spoilers have already started to appear on the internets. Peter Krumins has posted a solution using unix shell commands, so I figured I’d show my Ruby solution

The Problem

As Peter describes the problem is to find the smallest prime number which can be expressed as a sum of several different numbers of consecutive primes. Here’s the question as Google posed it to me:

Find the smallest number that can be expressed as

the sum of 3 consecutive prime numbers,

the sum of 5 consecutive prime numbers,

the sum of 275 consecutive prime numbers,

the sum of 1167 consecutive prime numbers,

and is itself a prime number.

For example, 41 is the smallest prime number that can be expressed as the sum of 3 consecutive primes (11 + 13 + 17 = 41) and the sum of 6 consecutive primes (2 + 3 + 5 + 7 + 11 + 13 = 41).

Note that I’ve got a different set of four numbers of consecutive primes than Peter’s

The Approach

I always try to do ‘the simplest thing that could possibly work.’ Like Peter I had no desire to write a prime number generator. A little googling found me the same source of prime numbers. I figured as a first guess that the answer would probably lie somewhere within the first million prime numbers, so I downloaded that list, and examined the list in Textmate.

As Peter notes, the file has two lines of header, and then several primes in sequence on each line. I just deleted the header lines in Textmate and then wrote a class which would read the file and return each prime number in sequence:

class PrimeReader
  def initialize(file)
    @file = file
    read_line
    yield self
  end

  def next
    read_line if @numbers.empty?
    @numbers.shift.to_i
  end

  def read_line
    @numbers = @file.readline.split(' ')
  end
end

This should be fairly explanatory. PrimeReader reads the file as necessary and hands out each prime number.

Now that I had a source of consecutive primes it was time to write the code to search for the answer. Here’s the outer loop:

processor = Processor.new

File.open("#{File.dirname(__FILE__)}/primes1.txt") do |f|
  PrimeReader.new(f) do | primes |
    until processor.test(primes.next)
    end
  end
end

The real work is done, in the unimaginatively named Processor. The loop reads lines from the PrimeReader until the processor finds the desired prime or end of file generates an exception.

And here’s the Processor class:

class Processor
  def initialize
    @counts = [3, 5, 275, 1167].reverse
    # @counts = [3,6]
    @sums = @counts.inject({}) { |hash, count| hash[count] = []; hash}
    @processed = []
  end

  def test(prime)
    puts "testing #{1+@processed.length}: #{prime} "
    qualifies(prime) || process(prime)
  end

  def qualifies(prime)
    @sums.each_value do | sums |
      return false unless sums.include?(prime)
    end
    report(prime)
    true
  end

  def process(prime)
    @processed << prime
    @counts.each do |count|
      calc_sum(count)
    end
    false
  end

  def calc_sum(count)
    if @processed.length >= count
      @sums[count] << @processed[-count,count].inject(0) { |sum, p| sum + p}
    end
  end

  def report(found)
    puts "Found #{found}"
    @counts.each do | count|
      report_sum(count, found)
    end
  end

  def report_sum(count, found)
    sums = @sums[count]
    sum_start = sums.index(found)
    puts "#{found} = #{@processed[sum_start, count].join(" + ")}"
  end
end

The approach I took was to compute the sums and save them in arrays which in turn are the values for each count used as a key in the hash @sums. I keep each prime in the array @processed which is used to calculate the sums.

I hard coded the parameters in the initialize method, note the commented out assignment to counts, by changing the commenting I could test the code against the example given and show that my code found 41 as the lowest prime expressible by both 3 and 6 consecutive primes.

The test method reports the number and value of each prime it examines, purely as a ‘progress indicator.’ The statment “qualifies(prime) || process(prime)” will return true if qualifies returns a truthy value, otherwise it will invoke process which always returns false.

The qualifies method returns true only if the array for each count contains the current prime, which is the essence of what we are seeking. Otherwise it returns false.

The process method first appends the new prime to @processed, then calculates the sum for each count using the calc_sum method. This method determines if we have enough primes in @processed to calculate the particular sum, and if so calculates the sum and appends it to the array for the count.

Once the answer has been found, the report method prints it and the sums which total to it. The sums are calculated in the report_sum method. This method takes a slice out of the @processed array, consisting of the count elements starting at the index where the answer is found in the particular sums array. A bit of reflection will reveal that this is precisely the primes which add to the answer.

In the case of my parameters, the answer, in case you are wondering is 5,181,901, which was confirmed by Google when I gave my answer. This is the 360,245th prime number by the way.

Performance

Although this might be a bit of a brute force approach, the performance was acceptable.

The biggest feature of Ruby which makes this approach feasible is the copy-on-write nature of Ruby arrays. In Ruby Array#slice (a.k.a. Array#[]) doesn’t copy the elements of the array, it just creates a new Array with an offset from the beginning of the original array and the length of the result. As long as neither Array is changed to affect one of the shared elements, nothing is copied, but when a shared element in the source or result array is changed, Ruby first does the copy to preserve the semantics.

My code does a lot of slicing of the @processed array, but other than appending to the end of the @processed array, the accesses to that array and the slices are read-only, so nothing needs to be copied.

Posted in  | 7 comments | no trackbacks

What Would You Miss If You Had To Stop Using Ruby and Go Back to Smalltalk?

Posted by Rick DeNatale Wed, 21 May 2008 20:58:00 GMT

Last night, James Robertson from Cincom, presented Smalltalk and Seaside to the Raleigh Ruby Brigade.

It was an interesting deja-vu experience, since in my younger days, part of my job with IBM was evangelizing Smalltalk, much as James does today. It was interesting to see what has and hasn’t changed. For the most part the things about Smalltalk which were blessings and curses (or many times both) haven’t changed. The IDE is still powerful. It gets much of it’s power from Smalltalk’s model of how source code and run-time implementation objects like compiled-methods, classes and metaclasses interact, but the consequence is that there aren’t really Smalltalk source files to use with popular editors like VIM or EMACS or Textmate. The question came up about whether the Smalltalk IDE supported the notion of giving the code to an external editor, and the answer was that the size of a typical Smalltalk method, which is the unit of editing, was so small (10 lines is a long Smalltalk method) as to make it ‘moot.’ I used to get the same kind of questions and give pretty much the same answers.

One area where Smalltalk really does excel is in it’s debugging and inspection tools. The same implementation object model which enables browser features, like finding all senders or implementers of a message using structural rather than textual searching, also allows live debugging, where you can not only inspect the run-time state at a breakpoint, or when an exception occurs, but actually make changes to the running code, and compile those changes, at which point the VM prunes the invocation stack down to the point of the change and allows you to restart from that point. Protestations from TDD/BDD adherents that you don’t need no steenking debugger if you follow TDD practice, the Smalltalk debugger was tool much favored by the very people, like Kent Beck, who invented TDD. Many Rubyists who were around for more than a year or two had an anti-debugger attitude, generated more, I suspect, by the lack of a decent Ruby debugger than any real hatred of debuggers.

Now that ruby-debug has been around for almost two years, the situation is much better. Ruby has a fairly competent debugger which allows stepping through code. It’s still hampered by Ruby’s rather simple run-time meta information, being forced to work on a line-by-line mode, rather than being able to step through individual expressions as can the Smalltalk debugger. And we’re still a long way from the live surgery capabilities I described. Perhaps as Ruby VM implementations mature we might see some of these advanced features emerge, perhaps this is something which the Rubinius implementers might also take as an inspiration from Smalltalk. This is one of the main things I miss from my Smalltalk days.

On the other hand, at this point in time, I’m really much happier working in Ruby than I think I would be were I somehow forced to work in Smalltalk again instead. Much as I love it, Smalltalk is now my second favorite language.

At one point last night, Brian Adkins asked me the question which is the title of this article. I think it’s a fair question, and I’m not sure I know exactly, but let me try to answer it.

What I’d miss from Ruby

I’ve said this before, but one of the things I like about Ruby is that it is more dynamic than Smalltalk in ways which I like, and cuts back on other aspects of Smalltalk which I don’t think are really that important.

One of the things I like about Ruby is the elimination of variable declarations. A good example of this was that during the Seaside demo last night, James showed how interfacing to the database requires attribute instance variables in model objects to be declared. Now the IDE provides tools for helping with this, you get prompted with a list of column names and can add them one by one just by clicking buttons. Contrast this with ActiveRecord where model objects just acquire instance variables dynamically at run-time. Now I know that some prefer more explicit mappings, but personally I feel that the dynamic mapping provides much more capability for much less ceremony.

The ways in which Ruby is more dynamic than Smalltalk seem to me to provide better facilities for building low-ceremony architectures and artifacts like Rails, Rake, etc. There are more dynamic languages than Ruby to be sure, such as Self, and from what I can sense JavaScript, but Ruby seems to strike a very nice balance.

Much has been made of the legacy of Smalltalk in pioneering metaprogramming, although some Lisp guys might quibble with that, and in truth, most Smalltalk metaprogramming was only used to support the IDE and never put to use by application programmers. Alan Kay used to say that he was disappointed that no one seemed to make new classes of Behavior (which is the superclass of both Class and Metaclass in Smalltalk). I know he said this to some of us at an IBM internal conference, which at least led to Dave Smith and Jerry Archbald developing a “behavior of behavior” tutorial which ran for several years at OOPSLA. But Rubyists have taken metaprogramming much further than I recall from my Smalltalk days.

On the other end of the scale, Smalltalk as James pointed out, as I used to, has a very simple syntax, a few reserved words (self, super, nil, true, and false), three types of messages (unary, binary, and keyword), two operators (:= for assignment, and ^ for return), and a few more things for defining block literals.

Now when I was doing James’ job, this got mixed reactions. Some people took to syntax like:

topLeft = Point x: 3+2*5 y: 15

While others found it just a little too strange, something which we Smalltalkers just couldn’t get.

Another thing which put off newcomers to Smalltalk was that, because of the simplicity of the language, and the lack of any form of operator precedence (remember the only operators are := and ^), that subexpression 3+2*5 evaluates to 25 and not 13.

Ruby trades off a little simplicity and does provide precedence between messages which seem like they should act as operators.

I’m not saying that Ruby is without quirks, just that different people react to different quirks in different ways. If you don’t like what you perceive to be the quirks of any programming language, you won’t be convinced, even by the most ardent supporter of those quirks.

One of the interesting effects of the Smalltalk syntax was that, as we observed back in Smalltalk’s heyday in the Enterprise (late ‘80s-early ‘90s), it seemed that a lot of COBOL programmers seemed to take to Smalltalk. We used to think that Smalltalk might actually become the 21st century COBOL, until the “Enterprise” got wooed away by EJBs and the like. The same things which made Smalltalk approachable by COBOL programmers made it seem weird to those who looked down on those COBOL programmers as “trade-school” programmers.

Another much-touted feature of Smalltalk, is that everything is done by message sending, even control flow. In Smalltalk a if/then/else control flow is achieved by sending an ifTrue:ifFalse: message to a boolean object as in:

 ^(x = 0) ifTrue:[a] ifFalse:[b]

Smalltalk evaluates this as if the the expression (x = 0) is evaluated by sending the message with the selector = and argument 0, to the object referenced by x. The result of that message, an object of course, is then sent the message with the selector ifTrue:ifFalse: and the arguments [a] and [b], which are two blocks. What happens is up to that object. Typically that object is either true (the sole instance of the class True) whose ifTrue:ifFalse: method evaluates the first argument, or false (the sole instance of the class False) whose ifTrue:ifFalse: method evaluates the second argument. Very neat and conceptually clean. It allows you to define your own control flow methods.

Ruby on the other hand compiles if statements and their kind as tests and branches, much as a C compiler would. We trade off a little flexibility for performance.

But, in my experience, that flexibility rarely got used in Smalltalk. Not only that but, in my day at least, the Smalltalk compilers would also compile ifTrue:ifFalse: to a test of the result of the ‘receiver’ and a branch. In fact I just tried defining a FakeBoolean class with an ifTrue: method and when I try to use it I see this:

must_be_boolean

That NonBooleanReceiver exception is like seeing the Wizard of Oz behind the curtain, this notion of no control flow, just messages is actually a bit of an illusion.

Again, while Ruby doesn’t even pretend to implement all control flow by messaging, it provides most of what the underlying Smalltalk mechanisms are really used for in the form of blocks used to implement iterators.

There are other aspects of Smalltalk which are both blessings and curses. The fact that Smalltalk has a persistent run-time image, containing all the development tools, which can be saved along with its state of execution, and restarted is quite powerful, alien to many programmers, and can drastically change your approach to deployment. Back when I was doing Smalltalk we always struggled with issues like the footprint of the image, how to strip out the development tools before deployment, and start-up time. Some of these problems might seem to be less severe with today’s hardware, but they are still issues.

I feel that I might be coming across a little too harshly on my old friend Smalltalk. It still provides a great programming environment, and serves as a source of inspiration which shouldn’t be overlooked, and I hope to see some of the powerful development tool features from Smalltalk appear with help from support in some of the emerging Ruby implementations. I’m glad to see that it seems to be making somewhat of a resurgence, along with dynamic languages in general. But for me right now, while I wouldn’t be unhappy if I had to go back to Smalltalk, but I feel happier with Ruby.

Posted in , ,  | Tags ,  | 5 comments | no trackbacks

On Ceremony and Training Wheels

Posted by Rick DeNatale Sun, 18 May 2008 14:15:00 GMT

The perennial topic of getting duck-typing in ruby has come up again. A ruby nuby wonders about the dangers of passing a “giraffe” object to a method expecting an “order.” Or asking an object to “draw”, expecting it to be a “brush” when it was really a “cowboy.”

These are reasonable questions, coming from someone who is used to a high-ceremony language which gives at least the illusion of protection from such “errors.” Note that method signatures in languages like Java can’t really protect from a draw method doing different things in different classes.

J. Cooper offered the following good advice:

Instead, look at it like this: how likely is a Giraffe able to do what an Order does? If the Giraffe doesn’t quack like an Order, than an exception is going to be thrown automatically anyway.

Just program in it, and see how often it ever actually bites you. Start with small things, work your way up.

The advice here is to tackle the problem of learning a language like Ruby with a certain amount of fearlessness. This reminds me of learning to ride a bike.

The traditional way of learning to ride a bicycle is to use training wheels, sometimes even progressively. Your dad might have installed the training wheels so that they touched the ground, turning the bike into a kind of tricycle with an extra, overly large back wheel between the normal ones. You think you’re riding a bike, but you’re really still on a trike.

The next stage, is for dad to raise the training wheels a bit so that you need to start learning to balance properly, but you can’t really tip too far. Now you’re riding something that kind of acts like a bicycle, but which “flops over” into tricycle mode.

If you never get past this stage, you never really learn to ride a bike. In an analogy with programming in Ruby, training wheels are chicken typing devices.

The truth is that bicycles and motorcycles operate quite differently than wheeled vehicles which keep three or more wheels on the ground, for one thing you steer by leaning, not with the handlebars or steering wheel. Learning to fly an airplane gives even stronger examples of having to learn that your instincts are wrong, and that you have to train yourself to “instinctively” know not only that you turn by banking rather than with the rudder, but that you control altitude primarily with the throttle, not the elevators, speed primarily with the elevators not the throttle, and so forth.

Now the use of training wheels, or flight simulators, might be considered a ceremony, although a necessary rite of passage for many learners. Given the high cost of mistakes in learning, it’s no doubt a good thing that student pilots get time in simulators and in dual control planes accompanied by a flight instructor before soloing. Although the way most young birds learn to fly is to be throw out of the nest to “sink” or “swim” so to speak.

In learning to program, it’s hard to see a difference between a simulator and reality, so it’s perfectly feasible to “fly the plane” from the start. The consequences of a mistake are no more dire than making a mistake in a flight simulator. It’s really just a matter of conquering fear, not to rely on chicken-typing, and the more mistakes you make and correct, the more quickly you come to grips with the differences in really using a dynamically typed language from earlier experiences.

Some can do this easier than others. For example, Alex, my 6-year old next-door neighbor recently jumped off his tricycle, and onto a bicycle (sans training wheels) and is now zooming around our cul-de-sac faster than ever before.

So if you’re struggling with how to program Ruby or a similar language because lacking ceremonial training wheels to “bridge the gap” from Java or a similar language. Might I suggest that you just jump in like Alex and give it a whirl.

Of course, it’s rarely easy to be as fearless as a 6-year old!

Posted in  | Tags , ,  | no comments | no trackbacks

Rails 2.1RC1 and the Enhanced Migrations Plugin

Posted by Rick DeNatale Thu, 15 May 2008 19:24:00 GMT

At work, we use the Revolution on Rails enhanced_migrations plugin.

Yesterday I started the work of moving the app to Rails 2.1RC1.

With version 2.1, Rails is moving to timestamp based migration names, instead of the traditional sequence numbering. This effectively does the same thing as the enhanced_migrations plugin, but the implementation is slightly different, more on this in a bit.

After installing or gitting Rails 2.1 into my vendor/rails directory, I ran the rake task to run all of our tests and specs.

Early on this task does a rake db:migrate, which attempted to run ALL of our migrations since Rails 2.1 looks in a different place to determine if a migration has been already run.

Implementation Differences

Until now Rails has tracked migrations using a single row, single column table in each database called schema_version. This table holds the number of the latest migration which has been run.

The enhanced_migrations plugin uses a w table, named migrations_info, with one row for each migration which has been applied to the database. The key used for this table is the migration number which the migration generator sets to Time.now.to_i. The only column besides the id is created_at. So the enhanced_migration plugin captures the time at which the migration was run against the database, which is different than the time it was generated.

Rails 2.1 uses a table called schema_migrations, which also has a row per applied migration, but this table has a string key whose value is the migration number, in Rails 2.1, the migration number is also a utc timestamp but is a string in the the form “yyyymmddhhmmss”

Blake Watters and I noticed that the timestamp forms can’t overlap since enhanced migrations uses a 10-digit timestamp and Rails 2.1 uses a 14-digit one. So we wrote a new migration 1_convert_migration_schema_to_rails21.rb

class ConvertMigrationSchemaToRails21 < ActiveRecord::Migration
  def self.up
    values = select_values('select id from migrations_info')
    values.each {|value| execute("replace into schema_migrations VALUES('#{id}')")}
  end

  def self.down
  end

We then ran rake db:migrate:up VERSION=1

This populated schema_migrations so that it now “knew” that all of our current migrations had already been run.

Not quite there

For many current users of enhanced_migrations, this might be enough. In our case it wasn’t. When I tried to run rake test again, it blew up in the prerequisite task db:test:clone_structure, complaining about bad sql syntax on an insert statement. The insert statement which was logged looked perfectly fine. It was the second of a series of statements inserting rows into our new friend, the schema_migrations table. The SQL in question looked like this:

INSERT INTO schema_migrations (version) VALUES ('0');
INSERT INTO schema_migrations (version) VALUES ('1');

Followed by a similar line for each of our 500 or so migrations.

The rake task for db:test:clone structure, basically breaks the file db/development_structure.sql into chunks delimited by empty lines, and ‘plays’ them against the test database using ActiveRecord::Base.connection.execute. After some head scratching over why this seemingly legal SQL was being rejected, it occurred to us that it was trying to execute all of these lines as one sql statement.

So the next step was to figure out how to get db/development_structure.sql into a form which would cause the task to execute each sql statement individually. This was a simple patch to rails, which once made, allowed rake db:test:prepare to run successfully, which in turn allowed me to actually move on to running the test suite and working out the problems caused by the changes to rails.

I opened up ticket #201 on the Rails lighthouse which contains the Rails patch.

Posted in  | Tags ,  | no comments | no trackbacks

Big Dave on Video

Posted by Rick DeNatale Wed, 30 Apr 2008 02:24:00 GMT

InfoQ recently published a video interview with Dave Thomas (of OTI fame).

In his inimitable style, Dave covers lots of interesting topics in software development, both today and with a historical perspective.

I agree with almost everything he says, and find the rest food for thought.

His comments about Java as a platform are quite germane to the article I published yesterday. If you’ve been exposed to Big Dave before, you’ll enjoy this, and if you haven’t it’s a good introduction.

Tags , , , ,  | 1 comment | no trackbacks

Older posts: 1 2 3 ... 11