2012-06-29 86 views
3

看到下面的輸出:Rails保存序列化對象失敗?

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 

爲什麼出現這種情況,我該如何避免呢?

模型上沒有((before | after)+(save | create | commit))。我正在使用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) 

編輯:在回答 「你爲什麼想到YAML ::負載(YAML ::轉儲(Player.randomize_for_market))保存到做任何事情!?」

因爲它序列化一個對象並恢復它? 例如:

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> 

注意p的回報是一樣的,從YAML ::負荷的回報

+0

您爲什麼期望'YAML :: load(YAML :: dump(Player.randomize_for_market))。save!'做任何事情? –

+0

因爲它應該序列化並恢復對象?請檢查我的編輯並回答你的問題 – fotanus

+0

但是爲什麼'save!'對沒有真正改變的對象做任何事情?您的'.save!'調用基於返回值,沒有異常,SQL'BEGIN'和'COMMIT'成功執行。但如果沒有什麼改變,那麼爲什麼你會希望'save'是一個非空操作? –

回答

7

這可能有助於回答你的問題:

: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 

展望了Rails源代碼爲ActiveRecord::Base#persisted?

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

而對於ActiveRecord::Base#new_record?

def new_record? 
    @new_record 
end 

當您轉儲對象YAML的@new_record實例變量不會被保存,因此,當您加載從YAML對象是nil。所以ActiveRecord認爲它已經被保存到數據庫中,並且不會嘗試保存它。

+1

是的,YAML只包含表格中的數據,告訴ActiveRecord需要完成的數據的重要事情在通過YAML的往返過程中無法生存。 +1用於追蹤更多缺少的部分。 –

2

Brandan的答案非常相關,從YAML反序列化的對象認爲它已經被持續存在。假設@loaded_obj是您從YAML加載的對象(您想要保存的對象),請嘗試@loaded_obj.dup.save

+1

在Rails 4中,'loaded_obj.persisted?= false',這是正確的,但顯然代碼沒有「意識到」任何值已更改,因此它不保存任何值。使用** dup()**解決了這個問題。 – gitb