views:

256

answers:

4

I have no idea what went wrong but I can't get belongs_to work with :class_name option. Could somebody enlighten me. Thanks a lot!

Here is a snip from my code.

class CreateUsers < ActiveRecord::Migration
    def self.up
        create_table :users do |t|
            t.text :name
        end
    end

    def self.down
        drop_table :users
    end
end

#####################################################

class CreateBooks < ActiveRecord::Migration
    def self.up
        create_table :books do |t|
            t.text :title
            t.integer :author_id, :null => false
        end
    end

    def self.down
        drop_table :books
    end
end

#####################################################

class User < ActiveRecord::Base
    has_many: books
end

#####################################################

class Book < ActiveRecord::Base
    belongs_to :author, :class_name => 'User', :validate => true
end

#####################################################

class BooksController < ApplicationController
    def create
        user = User.new({:name => 'John Woo'})
        user.save
        @failed_book = Book.new({:title => 'Failed!', :author => @user})
        @failed_book.save # missing author_id
        @success_book = Book.new({:title => 'Nice day', :author_id => @user.id})
        @success_book.save # no error!
    end
end

environment:

ruby 1.9.1-p387 Rails 2.3.5

A: 

Try removing t.integer :author_id, :null => false from your CreateBooks Migration. belongs_to will create the association automatically.

kingjeffrey
I'm not sure this is correct. Whatever rails magic is used, there must be a foreign key in the db and it must be specified in the migration.
Evgeny Shadchnev
+1  A: 

It should be

belongs_to :user, :foreign_key => 'author_id'

if your foreign key is author id. Since you actually have User class, your Book must belong_to :user.

Evgeny Shadchnev
+2  A: 
class User < ActiveRecord::Base
  has_many :books, :foreign_key => 'author_id'
end

class Book < ActiveRecord::Base
  belongs_to :author, :class_name => 'User', :foreign_key => 'author_id', :validate => true
end

The best thing to do is to change your migration and change author_id to user_id. Then you can remove the :foreign_key option.

Tony Fontenot
I care about having good foreign keys. I wouldn't apply the suggestion about renaming the column, as it's clearer what's going on when the columns have the right name.
François Beausoleil
Either way works. Whatever makes sense for you and your team is the right thing to do. :)
Tony Fontenot
A: 

Thanks for all your helps. I am very appreciated!

@Tony Fontenot, @Evgeny Shadchnev: As for the suggestion of using :user instead, it is in fact more than a reference to the User class, there is another field created_by which is another User instance who put the entry into the application like the following code:

belongs_to :author, :class_name => 'User', :validate => true
belongs_to :creator, :class_name => 'User', :validate => true

In fact, I have tried to add a :foreign_key option as well but it didn't help. My Code was:

belongs_to :author, :class_name => 'User', :foreign_key => 'author_id', :validate => true
belongs_to :creator, :class_name => 'User', :foreign_key => 'author_id', :validate => true

Have I missed something?

@kingjeffrey: I did try to remove the NOT NULL in the database and in the asscoiation of the User model. Unfortunately, it resulted null for author_id and creator_id fields. :(

crackpot