4

The table between the User model and Period model does not exist. They have a has_many_and_belongs_to relationship. I'm learning Rails still, so please bear with me.

This is the contents of the User.rb model file

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me

  has_many :assignments, :order => "end"
  has_and_belongs_to_many :periods
end

This is the contents of the Period.rb model file

class Period < ActiveRecord::Base
  has_many :weights
  has_many :assignments
  has_and_belongs_to_many :users
end

The exact error message is Could not find table 'periods_users'. This occurs when an instance of Period or User tries to invoke users or periods (i.e new_user.periods or new_period.users)

I'm using SQLite 3 for the development database, and SQLite 3 is properly installed.

I presumed that Rails would create the intermediary tables for habtm relationships. Do I have to create them myself, and if so, how?

(Please note that the other models associations are working just fine)

If I'm not giving enough information please let me know.

edit: After trying Method B, it threw:

undefined method "klass" for nil:NilClass

This occurred while trying to manage the User and Period models in rails_admin

So, I deleted the new model, and tried Method A. It threw

undefined method "period_id" for <ActiveRecord::ConnectionAdapters::SQlite3Adapter:0x3df7760>

while trying to run

rake db:migrate

Here is the migration:

class CreateTablePeriodsUsers < ActiveRecord::Migration
  def self.up
    create_table 'periods_users' do |t|
      t.integer period_id
      t.integer user_id
    end
  end

  def self.down
    drop_table 'periods_users'
  end
end

edit #2

Now it's having a "create_has_and_belongs_to_many_reflection: Primary Key is not allowed in a has_and_belongs_to_many join table"

This occurred after trying to run "rails server", and before that I ran rake db:migrate successfully

edit #3:

I fixed this a little less than a week ago, it ended up being an issue with the database schema, so I just dropped the database and re-migrated and it worked fine.

Jarred Sumner
  • 1,793
  • 6
  • 33
  • 45

2 Answers2

5

You have to create them yourself yes, there's two ways you can do this.

a) Simply create a migration with a new table.

b) Create a new model to use for the HABTM association (this makes things like deleting an association easier).

Method A:

$ rails generate migration CreateTablePeriodsUsers

Then edit the newly generated migration file,

class CreateTablePeriodsUsers < ActiveRecord::Migration                                                                                                                                                                                                                                                                                                           
  def up
    create_table 'periods_users' do |t|
      t.integer :period_id
      t.integer :user_id
    end
  end

  def down
    drop_table 'periods_users'
  end
end

Run rake db:migrate and you should be setup.

Method B:

$ rails generate model PeriodsToUser period_id:integer user_id:integer

Edit the PeriodsToUsers model

class PeriodToUser < ActiveRecord::Base
  belongs_to :period
  belongs_to :user
end

Then change your models to use the :through option.

class Period < ActiveRecord::Base
  # ...
  has_many :users, :through => :period_to_user
end

class User < ActiveRecord::Base
  # ...
  has_many :periods, :through => :period_to_user
end

Ryan Bates has a nice example of this method on his website, https://github.com/ryanb/railscasts/blob/master/app/models/tagging.rb

basicxman
  • 2,095
  • 14
  • 21
  • 1
    That did it, but I'm having a really strange error now. I think it's something wrong with rails_admin but the error is "undefined method `klass' for nil:NilClass" It looks like a typo, as this is the latest version from git, but I didn't see any typos in the method that was referenced ("NoMethodError in RailsAdmin::MainController#list", specifically in list). This error only happens with Period and User, which would probably mean that it doesn't support :through associations, but I will look that up. – Jarred Sumner Jun 21 '11 at 01:03
  • @Indebi Er, is this error related to this question? Please code new source code etc – basicxman Jun 21 '11 at 01:07
  • Updated my answer, those two column names should be symbols. – basicxman Jun 21 '11 at 01:39
  • Thanks, that did it! Edit: Migration was successful, but it's having a new error, I updated the answer – Jarred Sumner Jun 21 '11 at 01:41
0

In order to created has_many_belongs_to_many relationship using has_many clause with through option follow the steps below:

  1. Create table one (for example: users)
  2. Create table two (for example: roles)
  3. Create the following migration:

rails generate model RolesToUsers user:belongs_to role:belongs_to

where RolesToUsers can be any name, and user and role are not in plural (the actual table names are users and roles - in plural).

So, the something like the following migration should be created:

class RolesToUsers < ActiveRecord::Migration
  def change
    create_table :roles_to_users do |t|
      t.belongs_to :user
      t.belongs_to :role

      t.timestamps
    end
    add_index :roles_to_users, :user_id
    add_index :roles_to_users, :role_id
  end
end

with the corresponding model:

class RolesToUsers < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
  # attr_accessible :title, :body
end

Finally, you only need to add the has_many clause with through option in the two models as follows:

In the users.rb file:

has_many :roles_to_users
has_many :roles, through: :roles_to_users

In the roles.rb file:

has_many :roles_to_users
has_many :users, through: :roles_to_users
gotqn
  • 42,737
  • 46
  • 157
  • 243