在rails中使用attr_accessor尝试跳过验证

时间:2016-11-16 09:21:48

标签: ruby-on-rails ruby ruby-on-rails-5

我正在尝试跳过密码验证,因为facebook没有返回登录密码。

我收到错误;

“验证失败:密码不能为空”“user.save!

应用程序跟踪;

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'

这是因为from_omniauth是一个类方法,包装在用户变量中,然后我试图跳过密码验证,因为,实例变量,当尚未创建实例时。即first_or_create do |user|尚未在实例之前创建或注册用户?

如果是这样,我想知道如何重构我的代码才能使其工作?

会话控制器

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

3 个答案:

答案 0 :(得分:1)

您可以将skip_password参数传递给实例函数:

 def self.from_omniauth(auth, skip_password)
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.skip_password_validation = skip_password

  user.save!
end

然后像这样称呼它:

user = User.from_omniauth(env["omniauth.auth"], true)

答案 1 :(得分:0)

添加用户模型

public async void Write(params string[] text)
    {
        try
        {
            await FileLock.WaitAsync();
            using (StreamWriter sw = new StreamWriter(this.Source, true)) // <- IOException
            {
                for (int i = 0; i < text.Length; i++)
                {
                    await sw.WriteAsync(text[i]);
                }
            }
        }
        finally
        {
            FileLock.Release();
        }
    }

答案 2 :(得分:0)

有了这个,问题是has_secure_password,默认情况下显示3个验证方法api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html。您可以添加has_secure_password validations: false,并可以在validates方法中手动添加验证。正确的代码应该是,

会话控制器

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

    ...   

模型

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

 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.skip_password_validation = true

   user.save!
 end
...

编辑我再次回到这个问题,因为您需要在模型对象的模型中使用skip方法,然后才能保存,因为rails首先评估模型方法。所以你可以像@Vladan Markovic写的那样做,或者只是在调用save之前将user.skip_password_validation = true放在模型中的from_omniauth方法中,我已经编辑过它。