Richlewis
Richlewis

Reputation: 15374

Validation across two forms

I have a signup process that has two signup forms, depending on whether you are an individual or company, both get posted to the same model (User with devise). I am setting up my validations within the model, but was wondering how I would go about setting validations for the input fields that differ on each form.

For example :company_no is only on the company sign up form, but if I add a validation for this field the individual signup form will fail and throw an error on the :company_no field

I have set these links up to take the user to the correct form

<p><%= link_to 'Sign Up as Individual', new_user_registration_path %></p>
<p><%= link_to 'Sign Up as Vets/Rescue Centre', new_user_registration_path(organization: true) %></p>

View

<% if params[:organization] %>
 <%= render 'shared/company_signup_form' %>
<% else %>
 <%= render 'shared/individual_signup_form' %>
<% end %>

An example of a simple validation I am trying to use

class User < ActiveRecord::Base
  validates :company_no, presence: true
end

Upvotes: 1

Views: 156

Answers (2)

Mandeep
Mandeep

Reputation: 9173

What you can do is make use of rails conditional validation and do something like this:

class User< ActiveRecord::Base
  validates :company_no, presence: true, if: :record_is_company?

  def record_is_company?
    # check for some field which distinguish between a user and company
  end
end

Update:

As @Dave pointed out if there are multiple validations to check then either you can make non-persisted model or instead of using rails validation methods you can make two custom validation methods and then utilize validation errors to add error, so your user model will be something like this:

class User< ActiveRecord::Base
  validate :company_account, if: :record_is_company?
  validate :user_account, if: :record_is_user?

  def company_account
    # validate company form fields and add error
  end

  def user_account
    # validate user form fields and add error
  end

  def record_is_company?
    # check for some field which distinguish between a user and company
  end

  def record_is_user?
    # check for some field which distinguish between a user and company
  end
end

Update: I instead of checking for database fields for condition. It'll be better if we use a virtual attribute and set it in form(as you suggested in you comment)

attr_accessor :company_form
validates :company_name, presence: true, if: :record_is_company? 

def record_is_company?
  true if company_form 
end    

Upvotes: 1

Dave Newton
Dave Newton

Reputation: 160191

There are multiple solutions.

One trivial one is to use conditional validation, but this gets messy.

IMO the cleanest is to use non-persisted models, one for each form, and create the user model from them.

This isolates the persisted (domain) model from the form representation. Since Rails advocates putting validations on the model, without an easy way to separate contexts, creating form models is sometimes quite a bit less hassle and maintenance than trying to conditionalize everything. This is especially true when it's more than one or two conditions.

Upvotes: 2

Related Questions