2012-06-29 2 views
3

Смотрите следующий вывод:Rails save serialized object не удается?

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 

Почему это происходит и как я могу избежать этого?

Нет ((до | после) + (save | create | commit)) на модели. Я использую рельсы 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: Ответ на "Почему вы ожидаете 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> 

Обратите внимание, что возвращение р такое же возвращения из YAML :: нагрузки

+0

Почему вы ожидаете 'YAML :: load (YAML :: dump (Player.randomize_for_market)). Save!' Делать что-либо ? –

+0

Потому что предполагается сериализовать и восстановить объект? Пожалуйста, проверьте мое редактирование с ответом для вас – fotanus

+0

Но почему «сэкономить!» Что-нибудь сделать для объекта, который на самом деле не изменился? Ваш вызов '.save! 'Преуспевает на основе возвращаемого значения, отсутствия исключения и SQL' BEGIN' и 'COMMIT'; но если ничего не изменилось, то почему вы ожидаете, что 'save' будет чем-то иным, чем no-op? –

ответ

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 

переменная экземпляра @new_record не сохраняется, когда дамп объект YAML, и поэтому это nil при загрузке объекта из YAML. Поэтому ActiveRecord считает, что он уже сохраняется в базе данных и не пытается его сохранить.

+1

Да, YAML содержит только данные, которые идут в таблице, важные вещи, которые говорят ActiveRecord, что нужно делать с этими данными, не выдерживают кругосветное путешествие через YAML. +1 для отслеживания еще нескольких недостающих частей. –

2

Ответ Брандана очень уместен, объект, де-сериализованный из YAML, считает, что он уже сохраняется. Предполагая, что объект @loaded_obj - это объект, который вы загрузили из YAML (объект, который хотите сохранить), попробуйте @loaded_obj.dup.save

+1

В Rails 4, 'loaded_obj.persisted? = False', что является правильным, но, по-видимому, код не« понимает », что любые значения изменились, поэтому он не сохраняет никаких значений. Использование ** dup() ** решает проблему. – gitb

Смежные вопросы