Rails没有创建中间表? - 哈布姆的关系

时间:2011-06-21 00:05:43

标签: ruby-on-rails-3 activerecord model sqlite has-and-belongs-to-many

User模型与Period模型之间的表格不存在。他们有一个has_many_and_belongs_to关系。我还在学习Rails,所以请耐心等待。

这是User.rb模型文件的内容

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

这是Period.rb模型文件的内容

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

确切的错误消息是Could not find table 'periods_users'。当Period或User的实例尝试调用用户或句点(即new_user.periodsnew_period.users

时会发生这种情况

我正在使用SQLite 3作为开发数据库,​​并正确安装了SQLite 3。

我假设Rails会为habtm关系创建中间表。我是否必须自己制作,如果是,如何制作?

(请注意其他模特协会工作正常)

如果我没有提供足够的信息,请告诉我。

编辑:尝试方法B后,它抛出:

undefined method "klass" for nil:NilClass

尝试管理rails_admin中的UserPeriod模型时发生这种情况

所以,我删除了新模型,并尝试了方法A.它抛出了

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

尝试运行时

rake db:migrate

以下是迁移:

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

编辑#2

现在它有一个"create_has_and_belongs_to_many_reflection: Primary Key is not allowed in a has_and_belongs_to_many join table"

尝试运行“rails server”后发生这种情况,在此之前我成功运行了rake db:migrate

编辑#3:

我在不到一周前解决了这个问题,最终成了数据库架构的一个问题,所以我只是删除了数据库并重新迁移,它工作正常。

2 个答案:

答案 0 :(得分:5)

你必须自己创建它们,有两种方法可以做到这一点。

a)只需使用新表创建迁移。

b)创建一个用于HABTM关联的新模型(这样可以更容易地删除关联)。

方法A:

$ rails generate migration CreateTablePeriodsUsers

然后编辑新生成的迁移文件

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

运行rake db:migrate,您应该进行设置。

方法B:

$ rails generate model PeriodsToUser period_id:integer user_id:integer

编辑PeriodsToUsers模型

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

然后更改模型以使用:through选项。

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在他的网站https://github.com/ryanb/railscasts/blob/master/app/models/tagging.rb

上有一个很好的例子

答案 1 :(得分:0)

要使用 has_many 子句与选项创建has_many_belongs_to_many关系,请按照以下步骤操作:

  1. 创建表一(例如:用户)
  2. 创建表二(例如:角色)
  3. 创建以下迁移:
  4.   

    rails生成模型RolesToUsers用户:belongs_to role:belongs_to

    其中 RolesToUsers 可以是任何名称,而用户角色不是复数(实际的表名是用户< / em>和角色 - 复数形式。)

    因此,应该创建类似以下迁移的内容:

    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
    

    使用相应的模型:

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

    最后,您只需要在两个模型中使用选项添加 has_many 子句,如下所示:

    users.rb 文件中:

    has_many :roles_to_users
    has_many :roles, through: :roles_to_users
    

    roles.rb 文件中:

    has_many :roles_to_users
    has_many :users, through: :roles_to_users