0

I have a FormObject for registration which creates a user and a lot of models for him inside create method.

def create
  ActiveRecord::Base.transaction do
    @user = User.create(@params[:user])
    process_bonuses_for_user
    process_actions_for_user
    # et.c., giant amount of methods
  end

  @user.persisted? # to return the true of false to controller
end

I met the strange behaviour of my FormObject. Even it ran successfull (create a lot of models) or unsuccessful (not saving them), the id of User model is autoincrementing. So, every trying to save something using my FormObject increment the value of next id for User. This is normal situation when User created successfully, but not normal when user makes a mistake on registration form.

How can I disable this unpredictable behaviour?

P.S. I know that everything is work when I write @user = User.new(@params[:user]) at the start of create method and @user.save at the end, but there are a lot of associations, and I don't want to write a lot of autosave or inverse_of in my models.

P.P.S. I'm postgresql-9.4 user

Alex Antonov
  • 14,134
  • 7
  • 65
  • 142

2 Answers2

0

Your transaction is not working because you're using create. You need to use the bang version (create!) to raise an exception on failure which triggers the rollback. Do note that you'll need to rescue the InvalidRecord exception yourself.

fylooi
  • 3,840
  • 14
  • 24
0

In my opinion, it could be something like this:

  def create
    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
         process_bonuses_for_user
         process_actions_for_user
         # et.c., giant amount of methods
         ...
         format.html { redirect_to ... }
      end
    end
  • Wrong. What will be if user is valid, but `process_actions_for_user` method failed? – Alex Antonov Jun 25 '15 at 10:42
  • So, if `process_actions_for_user` related to `User Model`, it should be placed into verification area. If it related to other models, user should be ceated before it. Yes? Other case -- You could use before_action: and after_action: filters... – Сергій Назаревич Jun 25 '15 at 11:45