在Ruby on Rails中,如果数组为空,那么带有序列化数组字段的模型将不会在test = User.new
<User id: nil, name: nil, example: [], created_at: nil, updated_at: nil>
上更新,以前它有数据。
我正在使用:
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”会导致空数组无法保存到数据库中?
答案 0 :(得分:1)
SQLite不支持Array列类型。我认为发生的事情是当您尝试使用示例属性的空数组保存User时,它被解释为对示例列没有任何更改。如果您在使用示例数据创建测试用户后尝试此操作会发生什么?
test.example = nil
test.save
或者,这会发生什么?
test.example = [nil]
test.save
似乎解决方案是使用ActiveRecord callback(例如before_save
)检查用户模型的示例属性以确定它是否为空数组。如果是这样,请将属性设置为nil
或[nil]
(无论哪个有效),然后数据应相应保留。