Lee Eather Lee Eather - 22 days ago 6
Ruby Question

Using attr_accessor in rails trying to skip validations

I am trying to skip password validation as facebook does not return a password for login.

I am getting a error;

"Validation failed: Password can't be blank" on line

user.save!


Application trace;

app/models/user.rb:36:in block in 'from_omniauth'
app/models/user.rb:29:in 'from_omniauth'
app/controllers/sessions_controller.rb:6:in 'create'


Is this because
from_omniauth
is a class method, wrapped inside the user variable and then I am trying to skip password validation, as, a instance variable, when the instance is not created yet. Ie
first_or_create do |user|
has not created or registered the user before the instance?

If so, I was wondering how I could refactor my code to make this work?

Sessions controller

class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
user.skip_password_validation = true
...


model.rb

class User < ApplicationRecord

has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true,
unless: :skip_password_validation

attr_accessor :skip_password_validation

def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.email = auth.info.email
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end

Answer

With this, the problem is has_secure_password, which has 3 validation methods by default shown here api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html. You add in has_secure_password validations: false, and can add in validations manually in the validates method. The proper code should be,

Sessions controller

class SessionsController < ApplicationController
  def create
   user = User.from_omniauth(env["omniauth.auth"])
    user.skip_password_validation = true
    ...   

Model

has_secure_password validations: false
validates :password, on: :create, presence: true, length: { minimum: 6 }, allow_nil: true,
unless: :skip_password_validation

attr_accessor :skip_password_validation

...