Как сохранить вновь созданные связанные модели с помощью Sequel?

Предполагая, что у меня есть что-то вроде этого:

# Schema:
DB.create_table :transactions do
    primary_key :id
    foreign_key :card_id, :cards
    Integer     :amount
end
DB.create_table :cards do
    primary_key :id
    foreign_key :transaction_id, :transactions
    Intger      :number
end

# Models:
class Transaction < Sequel::Model
    one_to_one :card
end
class Card < Sequel::Model
    one_to_one :transaction
end

Как мне заставить эту работу работать так, чтобы она сохраняла как trans, card, так и их соответствующие ассоциации?

trans = Transaction.new(:amount => 100)
card = Card.new(:number => 4000500060007000)
trans.card = card
trans.save

В нынешнем виде это не работает, потому что card не сохраняется первым, а Sequel выдает ошибку «нет первичного ключа». Если я сначала сохраню card, он не получит идентификатор transaction.

В основном, я пытаюсь избежать этого:

# Save without associations first, but this will assign primary keys
trans.save
card.save

# Now, manually create associations
trans.card = card
card.trans = trans

# Re-save again, this time with associations
trans.save
card.save

person Arman H    schedule 09.05.2013    source источник


Ответы (1)


Вы можете попробовать изменить тип ассоциации на что-то вроде:

# Schema:
DB.create_table :transactions do
    primary_key :id
    Integer     :amount
end
DB.create_table :cards do
    primary_key :id
    foreign_key :transaction_id, :transactions
    Integer      :number
end

# Models:
class Transaction < Sequel::Model
    one_to_many :card
end
class Card < Sequel::Model
    one_to_one :transaction
end

Теперь вы создаете как:

trans = Transaction.new(:amount => 100)
trans.save
trans.add_card(:number => 4000500060007000)

Это позволит использовать все те же варианты, а также позволит (но, конечно, не потребует) разделить транзакцию между несколькими картами.

person Patrick Hurley    schedule 04.07.2013
comment
Спасибо, но я ищу решение, которое не меняет ассоциации объектов с 1:1 на 1:many. - person Arman H; 05.07.2013
comment
Почему бы просто не объединить таблицу? Если соотношение равно 1:1 и 1:1, то нет причин не создавать таблицу с обоими наборами столбцов — она будет представлять одни и те же данные. - person Patrick Hurley; 06.07.2013
comment
Этот пример тривиален, и я использовал его для иллюстрации проблемы. Реальные модели намного сложнее. - person Arman H; 07.07.2013
comment
Я так и предполагал, но в любом случае полностью рефлексивная связь 1:1 аналогична использованию одной таблицы. - person Patrick Hurley; 07.07.2013
comment
Хотя этот ответ не решил мою проблему, я присудил награду за усилия и предоставление полезной информации. - person Arman H; 10.07.2013
comment
@ArmanH, я думаю, что установка внешних ключей для обеих таблиц считается ошибкой - нет хорошего способа написать код так, как вы хотите, потому что эта схема ошибочна. Он допускает возможность несогласованности данных и является излишним — вполне достаточно одного внешнего ключа. Решение Патрика правильное. - person Ben Lee; 10.07.2013
comment
См. stackoverflow.com/questions/9420916/ -- как принятый ответ объясняет, что отношения 1-к-1 и отношения 1-ко-многим имеют одну и ту же структуру схемы, они просто по-разному используются в коде. - person Ben Lee; 10.07.2013
comment
Сами документы Sequel находятся по адресу sequel.rubyforge.org/rdoc/files/doc/. say Если вы хотите установить отношение 1-1 между двумя моделями, вы должны использовать many_to_one в одной модели и one_to_one в другой модели, а также ассоциацию one_to_one можно рассматривать как подмножество ассоциации one_to_many , но в связанной таблице может быть только 0 или 1 запись. - person Ben Lee; 10.07.2013
comment
@BenLee, спасибо за вклад. Пример 1:1 из документации Sequel у меня не работает. Если я укажу только one_to_one в модели Transaction и ничего в Card, то в обеих моделях отсутствуют методы add_card или add_trans, и я не смогу сделать что-то вроде card.transactions. - person Arman H; 10.07.2013