Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts

Wednesday, April 28, 2010

Adding Rails Counter Cache - Two Stage Release

I recently added a counter cache to an existing has_many/belongs_to association. I am using a hosted Rails application (heroku)

I went through all the steps:

1) create a migration adding a table_name_count column to the counting table, and initializing table_name_count to the the proper value

2) add :counter_cache => true to my :belongs_to association

3) make use of .size instead of .count for counting the associations

4) write proper unit tests to verify the counter is updated

It all worked - until deployment. The migration did not fail, but my counter fields remained 0.

Odd, it all worked locally. Must be an issue with my host - NOT.

Here is the skinny:

Specifying :counter_cache => true makes the counter field read only. Updating it does not cause an error, the model can still be saved, and modified? returns true. However, the field does not get saved - it is a transient change.

It wasn't a problem locally, because I had done these in the proper order. With git as my interface to heroku, all these steps were effectively compressed into one.

To fix this, I had to deploy this change in two stages:

A) Migration, initializing the value
B) Model and other code updates.

And it worked.

Friday, October 30, 2009

Installing Nokogiri gem on debian

sudo aptitude install libxml2-dev
sudo aptitude install libxsl1-dev
sudo gem install nokogiri

This fixes the "could not find libxml2" error

Wednesday, January 21, 2009

The Sweet Spot

Everything I Know, I Learned From Rails, Part II - The Sweet Spot Between Frameworks and APIs

This is the second article in a series to try to convince more developers to learn Ruby on Rails, even if they are not involved in web programming. See also part I and part III.

Rails is described as a Model-View-Controller (MVC) web application framework. It also contains a number of Application Programming Interfaces, or APIs.

What's the difference? Frameworks impose a structure on our program in order to make development easy in a complex paradigm. Frameworks say "implement interface X and overide the doSomething() method". An example of a framework would be the Microsoft Foundation Classes (MFC) for Windows development. Frameworks are great, except when the user needs to do something outside of the framework's capabilities.

An example of this which I encountered in my career was (not sure if it still this way) introducing an MFC split view with separate documents in each view pane. Was not possible as a view references one document. (Author's note: pls don't slam me on this point - at the time, had no other way to show two documents in my view).

APIs, on the other hand, are considerably lower level, offering more flexibility than frameworks, at a cost of complexity moving from the producer to the consumer. An API many of us are familiar with is the Java Swing API. You can do pretty much anything you want, but good luck figuring out how to correctly incorporate the JTree into your application.

I've often said APIs give you what you want, while Frameworks tell you what you want. There is a parallel in the software application space too. Applications can be written as a tool to aid the wisdom of the smart user, or can be the expert system which tells the user what's what.

As developers, we always get squeezed between the limitations imposed by a framework, and the difficulty of using an API in a efficient and robust manner which is maintainable across the future releases of the library. In fear, we wrap the API in a facade which we can adapt to new releases or fix improper usage of it. In essence, we turn APIs into into Frameworks ourselves.

Rails has found, in my opinion, a way to get the best of both worlds. Rails starts as a minimalist framework, doing basic request routing. It also has a series of APIs for building out your functionality.

Rather than impose a structural framework, Rails provides more of a functional framework. Using the metaprogramming of Ruby, rails generates missing methods at runtime, including defining model classes based on a table's structure, and generating find_by methods as they are called. The framework writes itself as it is running. That way, it stays lean and does as little for you as possible, and limits you as little as possible.

In addition to runtime code generation, Rails also comes with a series of static code generators to give you a leg up on fulfilling your part of the framework. Developers need to write model, view and controller classes, and there are generators which output each, plus the necessary tests for each.

While we may not all be able to put metaprogramming into our frameworks in the same manner Rails does, there still are lessons to be learned here. Not all of the restrictions we impose via frameworks are necessary. We can still help users by providing APIs alongside our frameworks, generating code (and tests with it) that use these APIs, but not providing the whole solution to your users, ever.

Tuesday, January 20, 2009

The Cost Of Choice

Everything I Know, I Learned From Rails, Part I - The Cost of Choice

This is the first article in a series to try to convince more developers to learn Ruby on Rails, even if they are not involved in web programming. See also part II.

Rails constantly preaches the idea of Convention over Configuration, or con/con. By way of con/con, Rails makes decisions for you. Some of these include directory names and layout, database table and column names, and others.

To quiet the naysayers, there is the claim that you can customize these defaults to your liking. But before this happens, somebody asks the question "Why?" and it doesn't happen. Nobody really knows if you can customize these or not :) As a result, a great many of the Rails applications use the default conventions.

Choice is expensive. Extremely expensive. Is there anything more costly than being able to make choices? Think about it. Here are a few time costs
  • Setting our various PATH variables, accommodating the directory structure of a new library we've included in our project
  • Figuring out where this project builds to
  • Looking at stored procedures to determine mapping to relational tables
  • Determining which directory/registry to put our configuration files in
  • Learning how to configure/configuring/reconfiguring/rolling out configuration/synchronizing configuration
  • Added complexity in our code due to options in our software
  • Added complexity in our tools due to the above
And the list goes on. But, this is only the direct costs of choice. There is also a second, even more expensive indirect cost. The indirect cost is not what we have to do because of choice, but what we don't do because of choice.
  • Reusing code is difficult, we'll just write ourselves
  • Testing code is difficult, we'll just hope it works
  • Automating anything is difficult, we'll do it by hand
  • That tool would take a minute to write and an hour to make work, I'll pass
When we move from a configurable environment to a con/con environment, things change noticeably. Configuration is automatic. Things are easy to find. Names are easy to remember. Code gets reused. Test are simple. Automation happens. Tools are easy to write. We make fewer decisions about things which don't impact our final product, and more which do. The Schmitzer becomes happy.

Monday, January 5, 2009

Ten Predictions for 2009

Rails Hosting Specialists Take Market Share...
finding they can cut costs more due to convention over configuration.

Bill Evjen Writes a Book About Something Other Than .NET...
signaling the beginning of the end of C#.

Zune Works All Year Long...
but thinks Feb 30 is a valid date.

Open Source Investment Increases...
as companies move to cut costs by leveraging community development.

Static Languages Get Dynamic Envy...
try to add closure, open classes, and metaprogramming but fall way short.

Ruby is Forked...
so many times, we won't be able to count. Thanks, Dave.

Technical Patent Mess Gets Even Worse...
as the 1 bit gets patented, hosing us all.

Ruby GUIs Become Real...
but not with FxRuby or Shoes, but Monkeybars on JRuby.

Steve Jobs Shows Up at MacWorld...
but Gizmodo claims he is a fake.

Yet Another MVC Framework Emerges...
but Rails still wins.