ruby-on-railsdevisewicked-gem

Rails partial validations depending on conrtoller


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!


Solution

  • 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.