Как я могу рефакторинг этой сложной транзакции в мою модель с моего контроллера? - PullRequest
1 голос
/ 10 ноября 2010

У меня сложный процесс сохранения (циклическая ссылка, которую необходимо разрешить путем проверки и сохранения и одной модели, проверки и сохранения другой, а затем обновления первой с помощью идентификатора второй), которая имеет откаты в зависимости от того, что-то не так случилось и т. д.

Мои модели связаны следующим образом:

  • Account s имеют один SiteContact.
  • Account s имеют много Customer s.
  • SiteContact s это тип Customer.
  • Customer с принадлежат Account

Из-за циклической ссылки (т. Е. Customer являются недействительными БЕЗ Account, но Account требуется SiteContact, который является типом Customer.) Я решил сохранить Учетную запись с пустым идентификатор для контакта с сайтом сначала , затем сохраните site_contact.

У меня есть код, подобный этому:

# remove the site contact from the account because its not valid yet.
site_contact = params[:account].delete(:site_contact_attributes)
account = Account.new(params[:account])

# some pseudo code
# start database transaction
# validate account
# if valid then
#   save account
#   site_contact.account_id = account.id
#   validate site_contact
#   if valid then
#     account.site_contact_id = site_contact.id
#     save account
#     break out!
#
#   else
#     rollback transaction
#   end
# else
#   rollback transaction
# end

if Account.exists?(account)
  # everything was good! flash[:notice] and redirect somewhere
else
  # something bad happened, go back to the page and display the errors.
end

Можно ли переопределить Account#save или какой-либо другой метод и перенести весь этот код в мой контроллер? Я смотрел на before_save и before_create, но я боюсь, что может быть какая-то непреднамеренная рекурсия, так как я должен сохранить account дважды.

Есть идеи?

Ответы [ 2 ]

2 голосов
/ 10 ноября 2010

В вашем контроллере:

site_contact = SiteContact.new(params[:account].delete(:site_contact_attributes))
account = Account.new(params[:account])

if account.save_nested(site_contact)
 # success
else
 # error
end

В вашей Account модели.

class Account < ActiveRecord::Base
  def save_nested(site_contact)
    Account.transaction do
      save!
      site_contact.account_id = self.id
      site_contact.save!
      self.site_contact_id = site_contact.id
      save!
      return true
    end
    return false
  end
end

save! вызовет исключение при сбое проверки. Это автоматически откатит транзакцию.

0 голосов
/ 10 ноября 2010

Как-то так?

Код контроллера

site_contact = params[:account].delete(:site_contact_attributes)
account = Account.new(params[:account])

if Account.validate_and_save(site_contact)
   # everything was good! flash[:notice] and redirect somewhere
else
   # something bad happened, go back to the page and display the errors.
end

Код модели

class Account < ActiveRecord::Base
  def validate_and_save(site_contact)
   # some pseudo code
   # start database transaction
   #  validate account
   #  if valid then
   #    save account
   #    site_contact.account_id = account.id
   #    validate site_contact
   #    if valid then
   #      account.site_contact_id = site_contact.id
   #      save account
   #      break out!
   #      return true
   #    else
   #      rollback transaction
   #      return false
   #    end
   #  else
   #    rollback transaction
   #    return false
   #  end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...