0

I am using devise for user registrations, meaning, that by default new user is registered through registrations_controller. So by clicking button "Register" user is redirected to a new_user_registration path.

My registration form however has two steps. In first step (new_user_registration) I am asking for a name and password. In the second step (users_controller), when user is saved, I am asking for address. This I am doing with wizard gem:

    def create
    @user = User.new(params[:user])
    if @user.save
      session[:user_id] = @user.id
      redirect_to user_steps_path
    else
      render :new
    end
  end

So, those a kind of partioal validations, but I cannnot validate depending in the step, as the first part of my form is handeled through registrations controller. The second part is however in the users_controller. It's getting complicated here and I would like to know, if I can validatede depending on the controller. Like:

validates :first_name, presence: true, if: -> { new_user_registration_path }
validates :last_name, presence: true, if: -> { new_user_registration_path }
validates :street, presence: true, if: -> { new_user_path }

I know, like this, it makes no sence, but maybe it helps to understand my thinking behind. Also, maybe I can work with smth. like:

validates :first_name, presence: true, if: -> { @user.save }
validates :last_name, presence: true, if: -> { @user.save }
validates :street, presence: true, if: -> { @user.update}

So basically, when creating a new user, I would validate if name and password is present. And when then adding address (it's an update action for user), I will check if address is present. Does anyone has experince with forms like this?

Another thought, maybe, I can skip registrations controller, redirecting directly to the user and creating two steps for partial validations? But as I am working with devise, I don't know, if I can just go throught users controller, skipping new_user_registration path. I did it, how it was advised on the wicked tutorial, but still ended up in the registrations controller:

 def create
      super
  end
 def update
      super
  end

Thanks!

Katharina Schreiber
  • 1,187
  • 2
  • 11
  • 38

2 Answers2

1

The best solution to this type of problem is to use form objects. See this example and the gem Reform.

With form objects, each HTML form is processed via a form object. In your example you could have a "User Registration" form, and a "User update" form. The key point is that the validation is done by the form and not the model. That way the validation is relevant to the current form input, and you avoid the issues of classing validation rules.

ReggieB
  • 8,100
  • 3
  • 38
  • 46
  • Thanks. Does this actually mean, I need the "Address Model", which is basically my second step in the form? – Katharina Schreiber Jan 21 '20 at 12:39
  • It depends. If a user can have more than one address, then yes you need an address model. If a user only ever has one address, you can get away with having address attributes in the user model. Also it makes sense to have a separate address object if there is a lot of address specific code. – ReggieB Jan 21 '20 at 14:23
  • I found a much easier solution, maybe interesting for you: see below – Katharina Schreiber Jan 21 '20 at 15:32
0

It's as easy as that:

validates :first_name, presence: true, :on => :create
validates :last_name, presence: true, :on => :create
validates :street, presence: true, :on => :update
validates :house_number, presence: true, :on => :update
validates :city, presence: true, :on => :update
validates :zip_code, presence: true, :on => :update

Clearly "Sign-Up" creates a User. And the wizard_steps just update the user. So for this simple example this works perfectly and raises validation errors according to the controller action.

Katharina Schreiber
  • 1,187
  • 2
  • 11
  • 38
  • This isn't a great solution. It ties the model to the input sequence, and means validation of some attributes is skipped on subsequent actions (for example if the user wants to update their first_name at a later point). Form objects is a much more flexible and scalable solution. – ReggieB Jan 21 '20 at 15:40