Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails save serialized object fails?

See the following output:

1.9.3p194 :001 > player = Player.randomize_for_market
 => #<Player id: nil, name: "Gale Bridges", age: 19, energy: 100, attack: 6, defense: 4, stamina: 5, goal_keeping: 3, power: 4, accuracy: 5, speed: 5, short_pass: 5, ball_controll: 4, long_pass: 6, regain_ball: 5, contract_id: nil, created_at: nil, updated_at: nil> 
1.9.3p194 :002 > player.save!
   (0.2ms)  BEGIN
   SQL (20.5ms)  INSERT INTO "players" ("accuracy", "age", "attack", "ball_controll", "contract_id", "created_at", "defense", "energy", "goal_keeping", "long_pass", "name", "power", "regain_ball", "short_pass", "speed", "stamina", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) RETURNING "id"  [["accuracy", 5], ["age", 19], ["attack", 6], ["ball_controll", 4], ["contract_id", nil], ["created_at", Fri, 29 Jun 2012 04:02:34 UTC +00:00], ["defense", 4], ["energy", 100], ["goal_keeping", 3], ["long_pass", 6], ["name", "Gale Bridges"], ["power", 4], ["regain_ball", 5], ["short_pass", 5], ["speed", 5], ["stamina", 5], ["updated_at", Fri, 29 Jun 2012 04:02:34 UTC +00:00]]
   (16.6ms)  COMMIT
 => true 
1.9.3p194 :003 > YAML::load(YAML::dump(Player.randomize_for_market)).save!
   (0.2ms)  BEGIN
   (0.2ms)  COMMIT
 => true

Why this happens and how can I avoid it?

There is no ((before|after)+(save|create|commit)) on the model. I'm using rails 3.2.

                                   Table "public.players"
   Column     |            Type             |                      Modifiers                       
--------------+-----------------------------+------------------------------------------------------
id            | integer                     | not null default nextval('players_id_seq'::regclass)
name          | character varying(255)      | not null
age           | integer                     | not null
energy        | integer                     | not null
attack        | integer                     | not null
defense       | integer                     | not null
stamina       | integer                     | not null
goal_keeping  | integer                     | not null
power         | integer                     | not null
accuracy      | integer                     | not null
speed         | integer                     | not null
short_pass    | integer                     | not null
ball_controll | integer                     | not null
long_pass     | integer                     | not null
regain_ball   | integer                     | not null
contract_id   | integer                     | 
created_at    | timestamp without time zone | not null
updated_at    | timestamp without time zone | not null

Indexes:
   "players_pkey" PRIMARY KEY, btree (id)

Edit: Answering "Why do you expect YAML::load(YAML::dump(Player.randomize_for_market)).save! to do anything?"

Because it serializes a object and recovers it? example:

1.9.3p194 :006 > p = Player.randomize_for_market
 => #<Player id: nil, name: "Vincenzo Allen", age: 23, energy: 100, attack: 2, defense: 8, stamina: 6, goal_keeping: 3, power: 5, accuracy: 6, speed: 5, short_pass: 6, ball_controll: 5, long_pass: 6, regain_ball: 5, contract_id: nil, created_at: nil, updated_at: nil> 
1.9.3p194 :007 > p
 => #<Player id: nil, name: "Vincenzo Allen", age: 23, energy: 100, attack: 2, defense: 8, stamina: 6, goal_keeping: 3, power: 5, accuracy: 6, speed: 5, short_pass: 6, ball_controll: 5, long_pass: 6, regain_ball: 5, contract_id: nil, created_at: nil, updated_at: nil> 
1.9.3p194 :008 > YAML::load(YAML::dump(p))
 => #<Player id: nil, name: "Vincenzo Allen", age: 23, energy: 100, attack: 2, defense: 8, stamina: 6, goal_keeping: 3, power: 5, accuracy: 6, speed: 5, short_pass: 6, ball_controll: 5, long_pass: 6, regain_ball: 5, contract_id: nil, created_at: nil, updated_at: nil> 

Note that the return of p is the same of the return from YAML::load

like image 347
fotanus Avatar asked Dec 10 '25 13:12

fotanus


2 Answers

This may help to answer your question:

:001 > article = Article.new
#<Article:0x102d16b10> { ... }
:002 > article.persisted?
false
:003 > dumped = YAML::dump(article)
"--- !ruby/object:Article ... "
:004 > loaded = YAML::load(dumped)
#<Article:0x102cf5500> { ... }
:005 > loaded.persisted?
true

Looking into the Rails source code for ActiveRecord::Base#persisted?:

def persisted?
  !(new_record? || destroyed?)
end

And for ActiveRecord::Base#new_record?:

def new_record?
  @new_record
end

The @new_record instance variable is not saved when you dump the object to Yaml, and therefore it's nil when you load the object from Yaml. So ActiveRecord thinks it's already been persisted to the database and doesn't attempt to save it.

like image 150
Brandan Avatar answered Dec 13 '25 03:12

Brandan


Brandan's answer is very relevant, the object de-serialized from YAML thinks it's already been persisted. Assuming @loaded_obj is the object you loaded from YAML (the object you want to save), try @loaded_obj.dup.save

like image 41
rthbound Avatar answered Dec 13 '25 02:12

rthbound



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!