创建或更新ArchivedUser

时间:2017-05-17 15:31:42

标签: mysql ruby-on-rails

我正在尝试制作users的备用表,名为archived users。它通过获取当前用户属性的哈希值(self)并在self.id中合并为user_id来创建ArchivedUser。

恢复用户后,他们作为ArchivedUser的记录仍保留在ArchivedUser表中。如果用户第二次被删除,则应更新已更改的任何属性。

目前,它会抛出验证错误: Validation failed: User has already been taken,因为self.id表中已存在ArchivedUser

如果可能的话,处理更新现有对象的对象的更好方法是什么,或者如果不存在则创建新记录。我正在使用Rails 4并尝试find_or_create_by但它会抛出错误

Mysql2::Error: Unknown column 'device_details.device_app_version'

这是奇怪的,因为该列存在于两个表中并且不会被修改。

用户删除方法

  # creates ArchivedUser with the exact attributes of the User
  # object and merges self.id to fill user_id on ArchivedUser
  if ArchivedUser.create!(
    self.attributes.merge(user_id: self.id)
  )

谢谢你偷看!

1 个答案:

答案 0 :(得分:0)

如果您的archived_users表真正充当用户备份而不添加任何其他功能,我会放弃ArchiveUser模型,只需在{{archived上添加User布尔值1}}模型来判断用户是否已存档。

这样你就不必处理将一个对象移动到另一个表并挂钩到一个删除回调。

但是,如果您的ArchiveUser模型与User相比确实提供了一些不同的功能,则另一个选项是使用single table inheritence来区分用户类型。在这种情况下,您可以User管理所有用户,然后区分用户,例如ActiveUserArchivedUser

这需要更多设置,如果您还没有使用过STI,可能会有点混乱,但是当两个相似模型需要稍微不同时,它会很有用。

话虽如此,如果您想保留当前的设置,我相信我的代码会出现一些问题:

  1. 如果您要从现有对象创建对象,duplicate the object (dup)是一种很好的做法。这样id就不会自动设置并且可以自动递增。

  2. 如果您确实已从数据库中删除了User记录,则没有理由存储对其id的引用,因为它已消失。但是,如果您实际上没有删除记录,那么您绝对应该使用布尔属性来确定用户是处于活动状态还是存档。

  3. 我没有足够的背景知道为什么find_or_create_by不起作用,但如果是这样,那么我会尽量保持简单。不要使用所有属性,但只知道您知道的一致属性(如id)将返回正确的结果。

  4. if ArchivedUser.create! # ...有问题。如果无法创建记录,那么创建后的爆炸(即create!)将抛出错误,使if毫无意义。因此,如果您不想抛出错误并想要处理未创建记录的条件,请使用if。如果您确实想要抛出错误,请使用create!而不是if