32423hjh32423
32423hjh32423

Reputation: 3088

How do I validate certain fields with rails devise on registration only

I have a set of custom fields attached to a devise model called Entrant.

I have two forms, one for registration form (three fields) and one which sits in the account area (12 fields). Most of the custom fields area required but only within the form the sits in the account area.

How do I achieve this?

I am using rails 4.2 and ruby 2.1

Upvotes: 3

Views: 5506

Answers (7)

Cedric Loy
Cedric Loy

Reputation: 61

I also have this concern when using devise on customer with forms on separate pages updating different set of customer fields

I believe most of the solution works but I was looking for the simplest, easiest and foolproof way to implement the solution

Thus came this.

validates :phone, :country, :postal_code, :street_address, presence: true, allow_nil: true

The allow_nil: true instruct the model to validate the fields ONLY if it exists on the submitted form. If you want more protection, you can use extra para like :on => :update

Upvotes: 0

MZaragoza
MZaragoza

Reputation: 10111

When I have to do something like this I like to think of it as it validates if something in in the field but you can also take a nil value

Entrant.validates_presence_of(:foo, :allow_nil => true) 

Upvotes: 0

user1011792
user1011792

Reputation:

validates :name, presence: true, if: :condition_holds?

def condition_holds?
 # some code here that evaluates to a boolean
end

Upvotes: 2

jon snow
jon snow

Reputation: 3072

Maybe this way help you.

Add attribute in devise model : say attr_accessor :validate_certain. In your controller action, devise model instance say @user have to update like this @user.validate_certain = true. and change your appropriate validation conditions in devise model

validates :name, presence: true, if: :validate_certain_changed?

def validate_certain_changed?
  validate_certain.present?
end

Upvotes: 1

DVG
DVG

Reputation: 17480

There are several ways! You could do conditional validations, for instance

class Entrant < ActiveRecord::Base
  validate :foo, if: :account_area?

  def account_area?
    !new_record? # Assumes that Entrant that has already been saved 
                 # is in the account area
  end
end

However, it sounds like your needs are advanced enough that you should consider making a Form Object

A form object is an object that accepts parameters, performs validations on that data, then saves a model instance.

class AccountForm
  include ActiveModel::Model
  include Virtus # Provides AR like attribute functionality and mass assignment

  def initialize(entrant)
    @entrant = entrant
  end

  attribute :foo, String
  validates :foo, presence: true # This is only used on the account page, so no need to mess with conditional logic

  def save
    if valid?
      persist!
      true
    else
      false
    end
  end

  def persist!
    @entrant.update_attributes(foo: self.foo)
  end
end

This is just a great example of how non-rails-specific object oriented programming can make your life easier and your app more maintainable. Make a class like above, stick it in app/forms and restart your server. Then in your controller, you'll just pass it the model

class EntrantController < ApplicationController
  def update
    @form = Form.new(Entrant.find(params[:id]))
    @form.attributes = params[:entrant]
    if @form.save
      redirect_to some_path
    else
      render "edit"
    end
  end 
end

Upvotes: 3

tduchamp
tduchamp

Reputation: 31

By default devise only asks for a combination of email/password, you can add other fields by adding a sanitizer (see there -> Devise how to add a addtional field to the create User form?). If you want to add other fileds to validate, you should create a secondary Entrant controller and add a specific callback to your model. Typically:

after_update :validate_entrant_form, if: :property_changed?

I hope this will help you.

Upvotes: 2

Andrey Deineko
Andrey Deineko

Reputation: 52357

You can simply specify validations on actions, that is:

validates :name, presence: true, on: :create # which won't validate presence of name on update action

If you ask where to put your custom fields, then generate devise's views and update corresponding ones with these fields.

Upvotes: 7

Related Questions