【问题标题】:Why can't I add an object to the relationship?为什么我不能将对象添加到关系中?
【发布时间】:2013-03-21 20:59:02
【问题描述】:

只是学习rails...

我有以下型号:

class TimeSlot < ActiveRecord::Base
  has_and_belongs_to_many :users
end

class User < ActiveRecord::
   has_and_belongs_to_many :time_slots
end

我也有模特加入两者:

class TimeSlotsUsers < ActiveRecord::Base
  attr_accessible :time_slot_id, :user_id
end

在控制台中,我创建了一个用户对象,并且我想将它与一个 TimeSlot 相关联。我有一个变量 ts 是一个 TimeSlot 对象,u 是一个用户对象。两者都已存在于数据库中。当我执行ts.users &lt;&lt; u 时,我收到一条错误消息:“ActiveRecord::StatementInvalid: SQLite3::ConstraintException: time_slots_users.created_at may not be NULL: INSERT INTO "time_slots_users" ("time_slot_id", "user_id") VALUES (1, 1 )。

为什么 created_at 会为空?不是在创建 TimeSlotsUsers 中的记录时自动创建的吗?我是否需要改用 has-many through 关系?

【问题讨论】:

    标签: ruby-on-rails-3.2 has-and-belongs-to-many


    【解决方案1】:

    如果您希望将 user_id 和 timeslot_id 以外的任何信息作为关系的一部分,则连接模型是一个很好的模式。例如,如果您有groupsusers 并且您有多对多关系,但有时用户是组的admin,您可以将is_admin 属性放在连接模型上。

    为了保持你的连接模型,一个更好的 Rails 模式如下...

    class TimeSlot < ActiveRecord::Base
      has_many :time_slot_users
      has_many :users, through: :time_slot_users
    end
    
    class User < ActiveRecord::Base
      has_many :time_slot_users
      has_many :time_slots, through: :time_slot_users
    end
    
    class TimeSlotsUsers < ActiveRecord::Base
      belongs_to :users
      belongs_to :time_slots
    end
    

    我不同意其他主张在连接表上没有主键的答案之一。
    例如,当您想使用 REST API 删除或编辑该关系时,拥有该关系的唯一 ID 很重要。是否有updated_atcreated_at 取决于它们是否是您的问题域中的有用数据。它可能是有用的信息,例如,知道用户何时被添加到组中(或者可能没有)。

    在 (user_id, time_slot_id) 上的连接表上拥有唯一索引以确保数据完整性非常重要。 Rails 模型可以在 99.999% 的情况下可靠地验证唯一性,但不是 100% 的时间。

    【讨论】:

    • 使用 has_and_belongs_to_many 时,Rails 不会设置 updated_atcreated_at 列。实现该功能的唯一方法是破解 Rails 或向数据库添加触发器。您不妨删除它们,或者至少不要将它们设为必需。无法真正确定此处是否需要 has_many :through,但从连接模型看来,time_slots_users 真的只是一个连接表,没有任何额外的属性。在这种情况下,一个简单的has_and_belongs_to_many 可能就足够了,我的回答解决了这个问题。我同意你的其他 cmets。
    • 啊!我没有意识到 updated_atcreated_at 没有设置。那讲得通。在设计方面,现在该表是一个简单的连接表。
    【解决方案2】:

    habtm 关系should not have created_at and updated_at columns 的连接表。您也不需要连接模型。

    如果你想对连接表做一些事情和/或向它添加属性,你应该更改为has_many :through

    【讨论】:

    • 你说我不需要join模型是什么意思?连接表不是必须的吗?
    • @JeffreyGuenther:表格是必要的,但模型不是。
    • 知道了。表必须存在于数据库中,但不需要定义 Ruby/Rails 对象。
    • @JeffreyGuenther:完全正确。只需删除 app/models/time_slots_users.rb 并删除这两个时间戳列,就可以了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多