Rails保存序列化对象失败?

时间:2012-06-29 04:08:05

标签: ruby-on-rails ruby activerecord serialization yaml

请参阅以下输出:

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

为什么会发生这种情况,我该如何避免呢?

模型上没有((之前|之后)+(保存|创建|提交))。我正在使用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 :: load(YAML :: dump(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 :: load

的返回相同

2 个答案:

答案 0 :(得分: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

查看ActiveRecord::Base#persisted?的Rails源代码:

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

对于ActiveRecord::Base#new_record?

def new_record?
  @new_record
end

将对象转储到Yaml时,不会保存@new_record实例变量,因此当您从Yaml加载对象时,它是nil。因此,ActiveRecord认为它已经被持久存储到数据库中,并且不会尝试保存它。

答案 1 :(得分:2)

布兰登的回答是非常相关的,从YAML反序列化的对象认为它已经被持久化了。假设@loaded_obj是您从YAML(要保存的对象)加载的对象,请尝试@loaded_obj.dup.save