0

I am handling a multistep form and this is why I need partial validations. Here is my model.

  class User < ApplicationRecord

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: %i[facebook]

    cattr_accessor :form_steps do
        %w(address) 
    end

    attr_accessor :current_step

    has_one :profile, dependent: :destroy
    after_create :create_profile
    accepts_nested_attributes_for :profile
    validates :first_name, presence: true
    validates :last_name, presence: true
    validates :street, presence: true, if: -> { current_step?(:address) }
    validates :house_number, presence: true, if: -> { current_step?(:address) }
    validates :city, presence: true, if: -> { current_step?(:address) }
    validates :zip_code, presence: true, if: -> { current_step?(:address) }


    def current_step?(step)
      current_step == step
    end


    def self.from_omniauth(auth)
        where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
            user.email = auth.info.email
            user.password = Devise.friendly_token[0, 20]
            name = auth.info.name
            user.first_name = name.split(" ")[0]
            user.last_name = name.split(" ")[1] 
        end
    end
end

Unfortunately this bit is not working, meaning the validations of the step :address do not function and it will let the user register without filling out the form on step :address.

validates :street, presence: true, if: -> { current_step?(:address) }
validates :house_number, presence: true, if: -> { current_step?(:address) }
validates :city, presence: true, if: -> { current_step?(:address) }
validates :zip_code, presence: true, if: -> { current_step?(:address) }

Why? What is wrong here?

Here is UserSteps_Controller

class UserStepsController < ApplicationController
    include Wicked::Wizard
    steps :address


    def show
      @user = current_user || User.from_omniauth(request.env["omniauth.auth"])
      render_wizard
    end


    def update
      @user = current_user || User.from_omniauth(request.env["omniauth.auth"])
      @user.update!(user_params)
      render_wizard @user
    end

    private

    def user_params
        params.require(:user).permit(:email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :street, :house_number, :city, :zip_code)
    end

    def redirect_to_finish_wizard(options = nil, params = nil)
        redirect_to new_user_profile_path(current_user)
    end

end

Thank you.

Katharina Schreiber
  • 1,187
  • 2
  • 11
  • 38
  • obviously (imho) `current_step == step` is returning false even when you pass `current_step = address`. You are passing address as symbol in step but your value passed in current_step is either not a symbol in first place or being converted to string after being sent. String address is not equal to symbol address i.e. `"address" == :address` => false. There is the issue. – ARK Jan 17 '20 at 19:50
  • As a solution, you can use: `current_step.to_sym == step` if the issue is what I mentioned. – ARK Jan 17 '20 at 19:53
  • This unfortunately returns an error: undefined local variable or method `current_step' for # Did you mean? current_step? Seems like the whole method is wrong. – Katharina Schreiber Jan 18 '20 at 08:45
  • I assume, the problem is, that I am using Devise. When I hit button "register" on my page, it goes to registrations controller. By hitting "Sign Up" I create user and redirect him/her to the first step of my form. The prblem is, however, that the first set of validations should run upon registration. Second set of validations runs when on step adress of user_steps. I guess this is really causing the problem, which leads to not validating properly. Well, I don't know, how to solve it, especially as a beginner. – Katharina Schreiber Jan 18 '20 at 09:46

0 Answers0