Suppressing “NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index” when running rake test with postgres db

Recently I switched to Postgres for my Rails database needs. Everything is good, but when running tests I get pages of NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index ... spewing into my output.

I asked around and got some help from @robtreat2. A quick search lead me to the Postgres docs on the matter.

client_min_messages (string)
Controls which message levels are sent to the client. Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, LOG, NOTICE, WARNING, ERROR, FATAL, and PANIC. Each level includes all the levels that follow it. The later the level, the fewer messages are sent. The default is NOTICE. Note that LOG has a different rank here than in log_min_messages.

That’s great for straight Postgres, but I don’t want to have some connection.exec jimmied into my test environment. Fortunately the Rails docs were also in that same search result:

:min_messages – An optional client min messages that is used in a SET client_min_messages TO <min_messages> call on the connection.

Using my newfound knowledge I was able to solve the issue by adding this to my database.yml file:

test:
  ...
  min_messages: WARNING

Giving up on has_many_polymorphs bug after an hour

I remember reading about has_many_polymorphs a couple of years ago, then again last year. Each time around when I wanted some sort of polymorphic has_many :through. Each time I figured, “Eh, it’s just another couple of tables” or “I can just map them in a method in the model, there’s not that much data”. But this time I finally gave it a try.

First I got this error when using the gem with Rails 3: has_many_polymorphs/support_methods.rb:69:in `warn': wrong number of arguments (1 for 3) (ArgumentError). So I looked at the github network graph and found a branch that seemed to fix that.

That worked, but next I got this: Could not find a valid class for :collections_items (tried CollectionsItem). If it's namespaced, be sure to specify it as :"module/collections_items" instead. (ActiveRecord::Associations::PolymorphicError) What are they trying to do, pluralize post positive adjectives? My model is named CollectionItem, which seems sensible to me.

This time I try adding a :through option to set it straight.

  has_many :collection_items
  has_many_polymorphs :items, :through => :collection_items, :from => [:sprites, :collections]

Now I get the following amazing error message:

has_many_polymorphs/class_methods.rb:441:in `create_has_many_through_associations_for_children_to_parent': You can't have a self-referential polymorphic has_many :through without renaming the non-polymorphic foreign key in the join model. (ActiveRecord::Associations::PolymorphicError)

This probably makes sense to everyone except me, but I’ve got to work with the skills I’m given.

What I’d really like is for polymorphic has_many :through to ‘just work’(TM).

Something kind of EXACTLY LIKE this:

class CollectionItem < ActiveRecord::Base
  belongs_to :collection
  belongs_to :item, :polymorphic => true
end
 
class Collection < ActiveRecord::Base
  belongs_to :user
  has_many :collection_items
  has_many :items, :through => :collection_items
end

Why is that so hard? No one will ever know…

So I did what I always do:

class Collection < ActiveRecord::Base
  belongs_to :user
  has_many :collection_items
 
  def items
    collection_items.map(&:item)
  end
end

After all, there’s not that much data anyway…

Random Scope

Here’s a little module that will make adding things like Cards.random(4) a breeze!

# This module takes care of adding a random scope to records
 
module RandomScope
  def self.included(model)
    model.class_eval do
      if connection.adapter_name == "MySQL"
        named_scope :random, lambda { |amount|
          if(amount)
            {:order => "RAND()", :limit => amount}
          else
            {:order => "RAND()"}
          end
        }
      else
        named_scope :random, lambda { |amount|
          if(amount)
            {:order => "RANDOM()", :limit => amount}
          else
            {:order => "RANDOM()"}
          end
        }
      end
    end
  end
end

Pluralizing Post-positive Adjectives in Rails

You know those adjectives that come after nouns? Well, sometimes you may want to pluralize them correctly in your Rails App. I might have been able to get by with “work_in_processes”, but “bill_of_materialsses” just wasn’t going to cut it.

Here’s the technique I used:

# Add new inflection rules using the following format:
ActiveSupport::Inflector.inflections do |inflect|
  inflect.irregular 'BillOfMaterials', 'BillsOfMaterials'
  inflect.irregular 'bill_of_materials', 'bills_of_materials'
 
  inflect.irregular 'WorkInProcess', 'WorksInProcess'
  inflect.irregular 'work_in_process', 'works_in_process'
end

If you have any improvements or suggestions please comment!

Now off to Burger King to order two Whoppers Jr.

Can’t dup NilClass… maybe try `unloadable`

If you’re using a model or controller from an engine in Rails 2.3.2 you may encounter some crazy errors from time to time. Errors like: A copy of ApplicationController has been removed from the module tree but is still active! Or sometimes the even weirder one: can't dup NilClass

In one situation where you get A copy of ApplicationController has been removed from the module tree but is still active! it could be because you’re using a plugin or engine that provides controllers and inherits from ApplicationController. Some of the classes inherited or included in your engine controllers may fail to get unloaded and cause trouble after the first request to your system. Add unloadable inside your controller classes in your engine.

The can't dup NilClass error really tricked me though. It seemed to be saying something about duping nil class but not really. It was a lie! Well, almost. See, I had a model in my engine like this:

class Account < ActiveRecord::Base
  include Authentication::ByCookieToken
  include Authentication::AccountBuddy
 
  has_many :logins, :dependent => :destroy
 
  attr_accessible :nickname, :email

And I had a module in my app (not in the engine) like this (sort of a reverse-micro-plugin):

module Authentication
  module AccountBuddy
    def self.included(account)
      account.class_eval do
        has_many :characters
      end
    end
  end
end

And when I tried to access account.characters it was all “can’t dup NilClass”. But what it really meant to say was: “I’m returning nil instead of an array containing the characters belonging to this account because I became confused during the loading and unloading of all your crazy ass models. -Love, Rails”

So adding a little unloadable also fixes that.

class Account < ActiveRecord::Base
  unloadable # <= That's the ticket!
  include Authentication::ByCookieToken
  include Authentication::AccountBuddy # reverse-micro-plugin 
 
  has_many :logins, :dependent => :destroy
 
  attr_accessible :nickname, :email

What a load off.

A better way

Courtesy of Paul (from the comments)

unloadable is now deprecated, I think. As far as I am aware, the “right” way to do this is one of the following:

First, you could put something like this in your plugin’s init.rb file:

# This plugin should be reloaded in development mode.
if RAILS_ENV == 'development'
  ActiveSupport::Dependencies.load_once_paths.reject!{|x| x =~ /^#{Regexp.escape(File.dirname(__FILE__))}/}
end

Second, you could put something like this in your application’s environment.rb file:

config.reload_plugins = true if RAILS_ENV == ‘development’

If the above did not solve your problem:

Courtesy of Evan Owen (from the comments)

Another possible cause of this problem is that ActiveRecord also defines self.included. In order to ensure that ActiveRecord gets the call and can finish loading the model, a call to super needs to be added to the end of self.included like so:

def self.included(account)
  account.class_eval do
    has_many :characters
  end
 
  super # fixes the "can’t dup nil" issue
end

This did not work in my specific case, but may be the correct solution if you are suffering from a similar but different problem.

Adding a Non-null Column with no Default Value in a Rails Migration

This is something that I’ve often needed to do: add a new column to the DB that has a non-null constraint, but also doesn’t have a default value. There are a some options:

  • Forget the DB constraint and use `validates_presence_of` in the model
  • Add a default value for the new column with non-null and then remove the default
  • Add the column without a default value, then alter it to be non-null

The first method of simply using `validates_presence_of` won’t cut it for me because that doesn’t actually make guarantees on the data stored in the DB from interfaces outside the of application.

Adding the new non-null column with a default value and then altering it to remove the default would probably be the best choice if you just need a standard value for all your historic data.

The third method is how I did it, and I like it best for any data that can be computed to a reasonable value to start out.Here’s the source for my migration:

class AddLoginMetricsToAccounts &lt; ActiveRecord::Migration
  def self.up
    add_column :accounts, :last_login, :datetime
    add_column :accounts, :total_logins, :integer, :null => false, :default => 1
 
    Account.reset_column_information
 
    Account.all.each do |account|
      account.last_login = account.created_at
      account.save!
    end
 
    change_column :accounts, :last_login, :datetime, :null => false
  end
 
  def self.down
    remove_column :accounts, :total_logins
    remove_column :accounts, :last_login
  end
end

I’m adding a last_login column that I want to be non-null, but because it has no default value most DBs won’t allow the new column to be added (it violates data integrity). So the thing is to add the column without a a non-null constraint, populate it with acceptable values, and then to change the column to include the constraint.

Hope this comes in handy!

The magic of haml and sass

As this project has progressed we’ve began using haml and sass to mark up our pages. When I first heard and read about these gems they had me concerned that it was an unnecessary change to the relatively simple languages of html and css. “Why the hell would I want to use percent signs instead of angle brackets?” and “What’s so hard about closing your tags?” were just some of the wtf moments I had initially, not to mention the forced indentation and strict whitespace requirements. “I can format my code however the fuck I please!!” However I did see some immediate benefit with sass, especially in the addition of constants and ease of nesting tags. Even so it didn’t feel like the pros would outweigh the cons, and that having to “learn” a new syntax would be more frustrating than the benefits being gained.

Now that I’ve been using it for all of our pages I’ve realized that it does simplify a lot of the gnarlier aspects of html and css and most of my worries were bullshit. Learning a new syntax took pretty much no time at all, and not needing to remember to close my tags has become very handy. The “forced” whitespace I was so concerned with turned out to be a non-issue because I format my regular code the way they want anyway, which is the cleanest way to read it to begin with. The nesting features of sass were immediately beneficial, even for relatively simple/common nests like ‘div#id p img’. Additionally, I didn’t think much time would be saved from these technologies, even after I began using them the first few times. But the more I’ve exploited them the more I realize that I spend less time typing out code and more time accomplishing tasks. In the end a lot of the complaints I’ve had about html/css for years (and those that I’ve forgotten about, too) have been addressed by haml and sass and ultimately make things easier.

Of course all of this is possible because of Rails, and seeing as how I’m fairly new to Rails, much of the kudos belongs to it as well. Using it on the backend delivers on it’s promises of cutting down wasted time and energy doing menial set up tasks and maintenance. I can make changes in one place and see them reflected all over the app, which is all I can ever ask for from a framework.

So now that I’ve professed my love of haml, sass, and rails, what’s the progress of the app? Well we have some colors on there and forms that aren’t hideous. There’s also a chat feature that’s functional and is rapidly expanding. Basically you can’t DO much of anything yet besides create an account and login, but it kind of looks like a website and acts like one too!