gpt4 book ai didi

ruby - 将元素添加到 postgres 数组字段失败,同时替换整个数组有效

转载 作者:太空宇宙 更新时间:2023-11-03 17:23:09 25 4
gpt4 key购买 nike

我有一个包含一系列角色的用户模型。

来 self 的 schema.db:

create_table "users", force: true do |t|
t.string "roles", array: true

我的模型是这样的:

class User < ActiveRecord::Base
ROLES = %w(superadmin sysadmin secretary)

validate :allowed_roles
after_initialize :initialize_roles, if: :new_record?

private

def allowed_roles
roles.each do |role|
errors.add(:roles, :invalid) unless ROLES.include?(role)
end
end

def initialize_roles
write_attribute(:roles, []) if read_attribute(:roles).blank?
end

问题是当我尝试从控制台添加另一个角色时,例如 user.roles << "new_role"然后 user.save!说 true 并询问 user.roles 给了我想要的输出。但是当我询问 User.find(user_id).roles 时,我得到的是之前的状态,其中没有“new_role”。

例如。

user.roles
=> ["superadmin"]
user.roles << "secretary"
=> ["superadmin", "secretary"]
user.save!
=> true
user.roles
=> ["superadmin", "secretary"]
User.find(<user_id>).roles
=> ["superadmin"]

当替换整个数组时,它如我所愿:

user.roles
=> ["superadmin"]
user.roles = ["superadmin", "secretary"]
user.save!
=> true
user.roles
=> ["superadmin", "secretary"]
User.find(<user_id>).roles
=> ["superadmin", "secretary"]

我正在使用 rails 4 和 postgresql,角色用于 cancancan gem。

更改其他字段,如 ex 的 user.name 会像预期的那样工作。我在谷歌中进行了大量挖掘,但没有任何帮助。

最佳答案

Active Record 跟踪哪些列已更改,并且仅将这些保存到数据库中。这种变化跟踪通过 Hook 到 setter 方法来工作 - 未检测到就地改变对象。例如

user.roles << "superuser"

不会被检测为更改。

有两种解决方法。一种是永远不要就地更改任何 Active Record 对象属性。在你的情况下,这意味着稍微笨拙

user.roles += ["superuser"]

如果你不能/不会这样做,那么你必须告诉 Active Record 你做了什么,例如

user.roles.gsub!(...)
user.roles_will_change!

让 Active Record 知道角色属性已经改变并且需要更新。

如果 Active Record 能更好地处理这个问题会更好 - 当不支持数组列中的更改跟踪时(当时 mysql 受到了最大的关注)

另一种方法是将此类列标记为始终需要保存(很像序列化属性所发生的情况),但您需要为此对 activerecord 进行猴子修补。

关于ruby - 将元素添加到 postgres 数组字段失败,同时替换整个数组有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25142532/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com