我们在两个模型之间有一个简单的has_and_belongs_to_many关系。我们想在该模型中添加一些参数,因此我们需要将其更改为has_many:通过某种模型。
据我所知,我们需要添加一个id列(以及我们想要的任何列)。但是,我不清楚100%如何做到这一点。如果我们添加一个整数列:id,那么rails会知道那是'id'主键吗?
我们正在使用最新的3.x.
答案 0 :(得分:12)
假设rails创建的has_and_belong_to数据库表是users_physicians
您需要做的就是生成一个像这样的模型
<强> rails g model patients_physician --skip-migration
强>
然后您可以使用迁移命令添加所需的任何列,例如“
”rails g migration add_new_column_to_patients_physician new_column
并且您的数据仍然完好无损,您可以根据自己生成的模型进行查询。
别忘了添加
belongs_to :model_1
belongs_to :model_2
新增加的模型患者_医师
然后你就可以访问了 在你需要的模型中。
has_many patients_physician
has_many :model_2, through: :patients_physician
答案 1 :(得分:9)
答案 2 :(得分:6)
这里有一篇文章说明使用sql修补habtm表并添加一个id(作为一个pkey):Rails modeling: converting HABTM to has_many :through。我遇到了这种方法的问题,可能存在特定于数据库的问题。我最终破坏了join(habtm)表并创建了一个新的连接模型。那很有效。
一些警告:在此之前,我建议在git中创建一个分支并归档数据库,以便在它横向移动时轻松恢复。
以下是这些步骤:
编辑两个已连接的模型以使用has_many到
class Physician < ActiveRecord::Base
# has_and_belongs_to_many :patients
has_many :appointments
has_many :patients, :through => :appointments
end
为患者做同样的事。
创建新的连接模型:
rails g model Appointment physician_id:integer patient_id:integer has_insurance:boolean
编辑上面生成的新迁移文件...请注意,由于我们正在处理数据,因此迁移方法的“更改”不起作用。见下文。
在数据库中创建新的连接模型,并通过记录将所有旧的habtm关联映射到新的has_many:
def self.up
create_table :appointments do |t|
t.integer :physician_id
t.integer :patient_id
t.boolean :has_insurance
t.timestamps
end
Physician.find_each {|doc|
doc.patients.each do |pat|
Appointment.create!(:physician_id => doc.id, :patient_id => pat.id, :has_insurance => false )
end
}
# finally, dump the old hatbm associations
drop_table :patients_physicians
end
如果重建旧的habtm协会似乎太痛苦了,按照rails指南,只是中止。但请注意,使用此方法无法再回滚迁移。
def self.down
raise ActiveRecord::IrreversibleMigration
end
相反,要“关闭”,只需杀死git分支,然后重新加载备份数据库。然后,如有必要,您可以从那里恢复db:rollback。另一方面,如果has_many through记录不需要修改,另一种方法是删除:id列,并重命名db:
def self.down
remove_column :appointments, :id
rename_table :appointments, :patients_physicians
end
我没有测试后者(在我的情况下,我必须弄乱元数据)。这些想法来自这篇文章:http://7fff.com/2007/10/31/activerecord-migrating-habtm-to-model-table-suitable-for-has_many-through/。
答案 3 :(得分:5)
这是我用于转换团队和用户之间has_and_belongs_to_many关系的迁移:
class CreateTeamMembers < ActiveRecord::Migration
def up
# Create a new table with id and timestamps to replace the old one
create_table :team_members do |t|
t.belongs_to :team
t.belongs_to :user
t.timestamps
end
# Now populate it with a SQL one-liner!
execute "insert into team_members(team_id,user_id) select team_id,user_id from teams_users"
# drop the old table
drop_table :teams_users
end
def down
# This leaves the id and timestamps fields intact
rename_table :team_members, :teams_users
end
end