这不是一个简单的错误。这是相当多的事情是错误的。
如果您想要一个用户可以拥有多个事件的关系,并且一个事件可以属于多个用户,您需要创建一个连接表。因为在用户表或事件表上存储外键会创建一对多的关系,这可能不是您想要的。
class User < ApplicationRecord
has_many :user_events
has_many :events, through: :user_events
end
class Event < ApplicationRecord
has_many :user_events
has_many :users, through: :user_events
end
# this is a join model.
class UserEvent < ApplicationRecord
belongs_to :user
belongs_to :event
end
has_many :through association 通常用于设置多对多
与另一个模型的连接。这种关联表明
声明模型可以与另一个的零个或多个实例匹配
通过第三种模型进行建模。
http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
您可以通过运行生成UserEvent 模型和创建连接表的迁移:
rails g model user_event user:belongs_to event:belongs_to
这将创建一个带有user_id 和event_id 外键列的user_events 表。您还应该回滚创建用户表的迁移并修复它:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :name
t.string :email
t.string :password_digest # !!!
t.integer :code
t.timestamps
end
end
end
注意添加了password_digest 列 - 这是has_secure_password 所必需的。如果您已经在生产数据库上运行此迁移或提交并推送它,您应该创建单独的迁移来修复错误:
class AddPasswordDigestToUsers < ActiveRecord::Migration[5.0]
def change
add_column(:users, :password_digest, :string)
end
end
class RemoveEventFromUsers < ActiveRecord::Migration[5.0]
def change
remove_column(:users, :event)
end
end
要创建与用户关联的事件,您可以执行以下操作:
event = user.events.new(name: "Dummy") # does not persist the record
event = user.events.create(name: "Dummy")
您可以使用铲子运算符从任一端分配记录:
user.events << event
event.users << user
这对我来说合适吗?
我的应用程序的主要目标是让用户有聚会和
那些派对有歌曲。
只有一个用户的聚会听起来很蹩脚。但是,如果您想为用户创建特殊关系,您可以创建单独的关联:
class User < ApplicationRecord
has_many :user_events
has_many :events, through: :user_events
has_many :owned_events, class_name: 'Event', foreign_key: 'owner_id'
end
class Event < ApplicationRecord
has_many :user_events
has_many :users, through: :user_events
belongs_to :owner, class_name: 'User'
end
class AddOwnerIdToEvents < ActiveRecord::Migration[5.0]
def change
add_column(:events, :owner_id, :integer)
add_foreign_key(:events, :users, column: :owner_id)
end
end
解决此问题的另一种方法是在UserEvent 连接模型中添加一个列,该列指定关联是什么。但这远远超出了您的技能水平。