Unable to save empty array in database during serialization

In Ruby on Rails, a model with a serialized array will not be updated to .save() if the array is empty, where it previously had data.

I use:

  • Ruby 2.2.1
  • Rails 4.2.1
  • sqlite3 1.3.10

    I created a new model with a field defined as text:

    rails g model Username: string example: text

In the User.rb file, I added:

 serialize :example, Array 

I created a new instance of the User class:

 test = User.new <User id: nil, name: nil, example: [], created_at: nil, updated_at: nil> 

Then I save the user so that it is saved correctly:

 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 

And he added some data to make him feel happy and purposeful:

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

And save it:

 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 

And make sure everything is kept beautiful:

 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"> 

I deleted one item, confirmed its removal and saved it, making sure the SQL output shows UPDATE:

 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 

I deleted the last piece of data from the array, checked the empty array and saved it. Note the lack of an UPDATE action and return 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 

Multiple saves get the same result. The new User object still has this last piece of data:

 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"> 

The workaround is to remove the "Array" from the serialization string in the model, initializing the field as zero. But this means that the first time I add data to a new instance, I must manually set the field to an empty array ( test.example = [] ) to call .push() on it. Everything works fine in this setup, and the new empty array successfully saves the database.

I saw a closed issue on Rails Github indicating that serialized columns should always be saved, but I have no idea if this is appropriate:

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

I could not distinguish anything from the serialized source code that could illuminate me:

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

Why does adding an β€œArray” at the end of the serialization string cause empty arrays to not be stored in the database?

+6
source share
1 answer

SQLite does not support the Array column type. I think what happens when you try to save a user with an empty array for the example attribute, which is interpreted as a change in the example column. What happens if you try this after creating a test user with sample data?

 test.example = nil test.save 

Alternatively, what happens to this?

 test.example = [nil] test.save 

It seems like the solution would be to use an ActiveRecord callback such as before_save to check the attribute of the user model example to determine if the array is empty. If so, set the nil or [nil] attribute (depending on what works), and then the data should be stored accordingly.

+1
source

Source: https://habr.com/ru/post/988035/


All Articles