Perfection, Not Progress

I wasted an entire day yesterday on :counter_cache => true. (Why was it wasted? Because I didn't need a counter cache yesterday, but knew that I would need it in a few weeks or months...progress versus perfection rears its ugly head again.)

Anyhow the problem ultimately had nothing to do with counter caching, but the error message didn't help too much, and there wasn't much in Google about the error message, so I spent a lot of time looking for the problem in the wrong place. Hopefully this post will help others in the future if you're getting this error message:

NoMethodError in Document content templateController#create
undefined method `increment_counter' for Class:Class

Yesterday I was creating entities called DocumentTemplate and DocumentContentTemplate:
class DocumentTemplate < ActiveRecord::Base
has_many :DocumentContentTemplates
end

class DocumentContentTemplate < ActiveRecord::Base
belongs_to :DocumentTemplate
end

Then, I ran a quick script/generate scaffold on both of these, and modified the _form.rhmtl for DocumentContentTemplate in order to add the association to DocumentTemplate. Everything is working fine.

Next, I decide that I'm going to need a counter cache on the DocumentTemplate, so I modify the DocumentContentTemplate model and added the document_content_templates_count column to the document_templates table via migration:
class DocumentContentTemplate < ActiveRecord::Base
belongs_to :DocumentTemplate, :counter_cache => true
end

Now, when I create a new DocumentContentTemplate the method DocumentContentTemplate#create should automatically increment the document_content_templates_count column in the document_templates table. But, when I submit the form that calls the create method I get this error:
NoMethodError in Document content templateController#create 
undefined method `increment_counter' for Class:Class

I spent hours debugging and investigating all the things related to counter cache, but it turns out that wasn't the problem. Go way back to the has_many and belongs_to declarations:
has_many :DocumentContentTemplates
belongs_to :DocumentTemplate

which, if you look carefully, should really be:
has_many :document_content_templates
belongs_to :document_template

So, if you're seeing that error, that's how to fix it. But, this raises two issues that I want to bring up:

1. My understanding is that the camel-case of a class name is supposed to be used when referring to the class, not an instance of it. For example, camelcase is used in a class definition or when the class is being used:
class DocumentTemplate < ActiveRecord::Base

DocumentTemplate.find(:all)

With that in mind, aren't the has_* and belongs_to methods referring to classes? Why don't they use the camelcase?

2. Regardless of the answer to #1, why does Rails handle this error gracefully? Why does has_*|belongs_to :ClassName not throw an error when it should be has_*|belongs :class_name?

No comments: