繁体   English   中英

新数据未持久到Postgres上的Rails数组列

[英]New data not persisting to Rails array column on Postgres

我有一个带有text类型的friends列的用户模型。 运行此迁移是为了将数组功能与postgres结合使用:

add_column    :users, :friends, :text, array: true

用户模型具有以下方法:

def add_friend(target)
  #target would be a value like "1234"
  self.friends = [] if self.friends == nil
  update_attributes friends: self.friends.push(target)
end

通过以下规范,直到我在调用#add_friend之后添加user.reload #add_friend

it "adds a friend to the list of friends" do
  user = create(:user, friends: ["123","456"])
  stranger = create(:user, uid: "789")
  user.add_friend(stranger.uid)
  user.reload #turns the spec red
  user.friends.should include("789")
  user.friends.should include("123")
end

这也在开发中发生。 模型实例已更新,并且在数组中具有新的uid,但是一旦重新加载或以其他操作重新加载用户,它就会恢复为调用add_friend方法之前的add_friend

使用Rails 4.0.0.rc2和pg 0.15.1

这可能是什么?

我怀疑ActiveRecord不会注意到您的friends数组已更改,因为,当您执行以下操作时,基础数组引用不会更改:

self.friends.push(target)

这将改变数组的内容 ,但数组本身仍将是同一数组。 我知道这个问题出现在Rails3中的postgres_ext gem并给出了这个问题

字符串属性用<<更改时,未标记为脏

我希望Rails4的行为相同。

解决方案是创建一个新数组,而不是尝试就地修改该数组:

update_attributes friends: self.friends + [ target ]

有多种方法可在将元素添加到现有数组时创建新数组,无论您喜欢哪种方法。

看来问题可能出在您使用push修改了数组的位置。

我找不到更主要的自动取款机,但是这篇文章说:

与模型上的数组(或其他可变值)交互时要注意的一件事。 ActiveRecord当前不跟踪“破坏性”或就地更改。 这些包括数组pushpopadvance DateTime对象。 如果要使用“破坏性”更新,则必须调用<attribute>_will_change! 让ActiveRecord知道您更改了该值。

如果要使用Postgresql数组类型,则必须遵守其格式。 Postgresql文档输入的格式是

'{10000, 10000, 10000, 10000}'

不是friends.to_s返回的内容。 在红宝石中:

[1,2,3].to_s => "[1,2,3]"

也就是说,用括号代替大括号。 您必须自己进行转换。

但是,我宁愿依赖ActiveRecord进行序列化(请参阅序列化 )。 数据库不需要知道该值实际上是一个数组,这就是您的域模型泄漏到数据库中。 让Rails做事并封装这些信息。 它已经知道如何对值进行序列化/反序列化。

注意:此响应仅适用于Rails 3,而不适用于Rails4。我将留在这里,以防将来对某人有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM