序列化时无法将空数组保存到数据库

时间:2015-05-27 17:23:16

标签: ruby-on-rails arrays ruby serialization

在Ruby on Rails中,如果数组为空,那么带有序列化数组字段的模型将不会在test = User.new <User id: nil, name: nil, example: [], created_at: nil, updated_at: nil> 上更新,以前它有数据。

我正在使用:

  • Ruby 2.2.1
  • Rails 4.2.1
  • sqlite3 1.3.10

    我创建了一个新字段,字段设置为text:

    rails g model用户名:string example:text

在User.rb文件中,我添加了:

test.save()
(0.1ms)  begin transaction
SQL (0.4ms)  INSERT INTO "users" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", "2015-05-27 16:17:31.902342"], ["updated_at", "2015-05-27 16:17:31.902342"]]
(0.7ms)  commit transaction
=> true

我实例化了User类的新实例:

test.example.push(1)
test.example.push(2)

然后我保存用户以确保正确保存:

test.save()
(0.1ms)  begin transaction
SQL (0.3ms)  UPDATE "users" SET "example" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["example", "---\n- 1\n- 2\n"], ["updated_at", "2015-05-27 16:17:50.331777"], ["id", 1]]
(0.8ms)  commit transaction
=> true

并添加了一些数据,以使它感到快乐和有目的:

test
<User id: 1, name: nil, example: [1, 2], created_at: "2015-05-27 16:17:31", updated_at: "2015-05-27 16:17:50">

并保存起来:

test.example.delete(1)
 => 1
test
<User id: 1, name: nil, example: [2], created_at: "2015-05-27      16:17:31", updated_at: "2015-05-27 16:17:50">
test.save()
(0.1ms)  begin transaction
SQL (0.9ms)  UPDATE "users" SET "example" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["example", "---\n- 2\n"], ["updated_at", "2015-05-27 16:18:30.148553"], ["id", 1]]
(8.9ms)  commit transaction
=> true

确保一切都得到了很好的保存:

test.example.delete(2)
=> 2
test
<User id: 1, name: nil, example: [], created_at: "2015-05-27 16:17:31", updated_at: "2015-05-27 16:18:30">
test.save()
(0.1ms)  begin transaction
(0.1ms)  commit transaction
=> true

我删除了一个项目,验证它已被删除并保存,确保SQL输出显示更新:

test = User.find(1)
User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
<User id: 1, name: nil, example: [2], created_at: "2015-05-27 16:17:31", updated_at: "2015-05-27 16:18:30">

我从数组中删除了最后一段数据,验证了空数组并保存了它。请注意缺少UPDATE操作并返回true:

test.example = []

多次保存可获得相同的结果。新的User对象仍然包含最后一段数据:

.push()

解决方法是从模型中的序列化行中删除“数组”,将字段初始化为nil。但这意味着我第一次将数据添加到新实例时,我必须手动将字段设置为空数组({{1}}),以便在其上调用{{1}}。在这个设置中一切正常,新清空的数组可以很好地保存到数据库中。

我在Rails Github上看到一个已关闭的问题,表明应该始终保存序列化列,但不知道这是否相关:

https://github.com/rails/rails/issues/8328

我无法辨别出能够照亮我的序列化源代码中的任何内容:

http://apidock.com/rails/ActiveModel/Serializers/Xml/Serializer/serialize

为什么在序列化行的末尾添加“Array”会导致空数组无法保存到数据库中?

1 个答案:

答案 0 :(得分:1)

SQLite不支持Array列类型。我认为发生的事情是当您尝试使用示例属性的空数组保存User时,它被解释为对示例列没有任何更改。如果您在使用示例数据创建测试用户后尝试此操作会发生什么?

test.example = nil
test.save

或者,这会发生什么?

test.example = [nil]
test.save

似乎解决方案是使用ActiveRecord callback(例如before_save)检查用户模型的示例属性以确定它是否为空数组。如果是这样,请将属性设置为nil[nil](无论哪个有效),然后数据应相应保留。