如何使用Rails在db中添加复合主键?

时间:2016-11-04 12:57:31

标签: ruby-on-rails ruby postgresql rubygems composite-primary-key

我在Postgresql 9.5中使用Rails 5.0

我需要在我的模型中添加复合主键' User_achievement' (如你所猜想的那样链接'用户'成就'模型)。

所以我尝试使用" composite_primary_keys"宝石。我遵循了所有的指示,然而,结果并不像我预期的那样。似乎它并没有在&user.dachievement'中创建pkey。表根据 psql 工具的信息:

test1_development=> \d user_achievements

Table "public.user_achievements"
Column | Type | Modifiers 

----------------+---------+-----------

user_id | integer | 
achievement_id | integer | 
uach_date | date | 

Indexes:

"index_user_achievements_on_achievement_id" btree (achievement_id)

"index_user_achievements_on_user_id" btree (user_id)

Foreign-key constraints:

"fk_rails_4efde02858" FOREIGN KEY (user_id) REFERENCES users(id)

"fk_rails_c44f5b3b25" FOREIGN KEY (achievement_id) REFERENCES achievements(id)

此处的模型和迁移'代码:

class CreateUsers < ActiveRecord::Migration[5.0]
 def change
  create_table :users do |t|
  t.string :name
  end
 end
end

class CreateAchievements < ActiveRecord::Migration[5.0]
 def change
  create_table :achievements do |t|
  t.string :ach_name
  t.text :ach_desc
  end
 end
end

class CreateUserAchievements < ActiveRecord::Migration[5.0]
  def change
   create_table :user_achievements, id: false do |t|
   t.belongs_to :user, :foreign_key => [:id]
   t.belongs_to :achievement, :foreign_key => [:id]
   t.date :uach_date
   end
  end
 end


class Achievement < ApplicationRecord
  has_many :user_achievements
end

class User < ApplicationRecord
  has_many :user_achievements
end

class UserAchievement < ApplicationRecord
  self.primary_keys = :user_id, :achievement_id
  belongs_to :user, :foreign_key => [:id]
  belongs_to :achievement, :foreign_key => [:id]
end

那么gem应该改变db表吗?或者它只会影响导轨&#39;环境? 是否有唯一的方法来改变db - 在迁移中添加执行行?

1 个答案:

答案 0 :(得分:3)

由于没有人发布任何有用的内容,我将分享我现在所拥有的内容。

Gem'composite_primary_key'(CPK)不会更改数据库中的任何内容,因此如果您仍然需要它 - 您应该手动执行此操作(将命令添加到迁移中)。

CPK唯一做的就是通过“理解”复合主键来扩展Rails,因为它最初没有并显示错误。

无论如何,我发现在Rails应用程序中使用复合主键是非常苛刻和有问题的,因为它使得使用其他宝石非常神经(每个新的宝石安装,你记住某些地方可能出错)以及更改你的将来用cpks代码。此外,它使您的代码更难理解其他不熟悉此功能的人。所以你应该总是指定你使用过CPK。

一个非常好的选择是添加一个带有'unique'选项的索引,这在技术上意味着完全相同,但不需要额外的头痛。

所以只有在你真的需要的时候才使用它,并且没有其他不太复杂的解决方案!