Рендирането не успява да изобрази правилен шаблон в метода rescue_from ActiveRecord::Rollback

Създавам страницата за плащане за сайт за електронна търговия и имам доста дълга транзакция, която създава нов потребителски модел и нов модел на поръчка. Обвих създаването на тези модели в транзакция, така че ако проверката за единия се провали, другият не се мотае в базата данни. Ето съкратения код в моя OrdersController:

rescue_from ActiveRecord::Rollback, with: :render_new

def render_new
  render action: 'new'
end

ActiveRecord::Base.transaction do
  @user = User.new params[:user]
  unless @user.save
    raise ActiveRecord::Rollback
  end
  //More stuff
  ...
  @order = Order.new params[:order]
  ...
  unless @order.save
    raise ActiveRecord::Rollback
  end
end

Грешката, която виждам е следната:

Липсващи шаблони за поръчки/създаване, приложение/създаване с {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}

Объркан съм защо се опитва да рендира шаблоните orders/create и application/create вместо рендиране на orders/new.

Има ли по-добър начин да принудите транзакцията да се провали, така че да се извърши връщането назад?


person Jordan Brown    schedule 15.01.2013    source източник


Отговори (3)


Мисля, че намерението е малко по-ясно, когато транзакцията се опакова в блок за начало/спасяване.

def create
  begin 
    ActiveRecord::Base.transaction do
      @user = User.new params[:user]
      unless @user.save
        raise ActiveRecord::Rollback
      end
      //More stuff
      ...
      @order = Order.new params[:order]
      ...
      unless @order.save
        raise ActiveRecord::Rollback
      end
    end
  rescue ActiveRecord::Rollback
    render action: "new" and return
  end
end

Трябва да се върнете в метода create, в противен случай изпълнението му ще продължи до края на метода и ще възникне изобразяване по подразбиране на Rails (в този случай това означава опит за намиране на шаблон create.___)< /em>.

Ако не харесвате блока за начало/спасяване, можете просто да добавите and return към raise редовете

raise ActiveRecord::Rollback and return
person deefour    schedule 15.01.2013
comment
Благодаря за бързата реакция. За съжаление все още нямам успех. Въведох начален/спасителен блок около моята транзакция, както предложихте, но по някаква причина спасителният блок никога не се изпълнява. Дори преминах към по-общо изключение за спасителния блок, ActiveRecordError, и блокът все още не се изпълнява. Можете ли да се сетите за някакви причини защо това би се случило, особено когато изрично повдигам изключение ActiveRecordError? - person Jordan Brown; 15.01.2013

Горният отговор е правилен, но е необходима известна модификация за изобразяване на действие.

Направи го така:-

def create
    is_project_saved = false
    is_proposal_saved = false

    ActiveRecord::Base.transaction do
      is_project_saved = @project.save
      is_proposal_saved = @proposal.save
      if is_project_saved && is_proposal_saved
        # Do nothing
      else
        raise ActiveRecord::Rollback
      end
    end

    if is_project_saved && is_proposal_saved
      # You can add more nested conditions as per you need.
      flash[:notice] = "Proposal Created Successfully."
      redirect_to project_show_path(:job_id => @project.job_id)
    else
      render :new
    end
end

ActiveRecord::Rollback няма да бъде уловен от resque. Така че трябва да се направи извън транзакционния блок.

Можете също да използвате save_point, като използвате :requires_new => true във вложен ActiveRecord::Base.transaction.

person RohitPorwal    schedule 16.04.2014

Трябва да повдигнете ActiveRecord::Rollback и да управлявате изобразяването/пренасочването, както желаете. Както каза @WasimKhan, ActiveRecord::Rollback няма да бъде хванат от спасяване.

def create
  @user = User.new params[:user]
  ActiveRecord::Base.transaction do
    if @user.save
      @order = Order.new params[:order]
      if @order.save
        redirect_to :index
      else
        raise ActiveRecord::Rollback
      end
    else
      render :new
    end
  end
  render :new if @user.id.nil?
end
person monteirobrena    schedule 01.03.2016