自我循环中的Active Record模型查询在Rails中的执行方式不同

时间:2019-04-18 15:10:46

标签: ruby-on-rails ruby rails-activerecord

我正在使用facebook-omniauth gem构建Facebook Oauth。我写了这种方法来根据auth数据创建用户。

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]
      user.username =  check_username(auth.info.email)
      user.remote_avatar_url = get_image_url(auth)
      user.skip_confirmation!
    end
  end

对于username代,我编写了此方法,其中检查了给定的用户名当前是否存在。

def self.check_username(value)
    username = value.split("@").first
    byebug 
    while(User.where(username: username).exists?)
      username += rand(100).to_s
    end
    username
  end

正在发生非常奇怪的错误,或者可能是我不知道有什么错误。在这里,当我尝试执行User.where(username: username)时,结果应该是 select * from users where username=username 它实际上正在执行

User.where(username: username)
  CACHE (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`provider` = 'google_oauth2' AND `users`.`uid` = '101977206788010441641' AND `users`.`username` = 'ashjambhulkar'

即使我尝试简单地获取所有记录,它也会给出

(byebug) User.all
  CACHE (0.0ms)  SELECT `users`.* FROM `users` WHERE `users`.`provider` = 'google_oauth2' AND `users`.`uid` = '101977206788010441641'  [["provider", "google_oauth2"], ["uid", "101977241641"]]
#<ActiveRecord::Relation []>

如何修改此查询,使其可以正常执行。

1 个答案:

答案 0 :(得分:2)

问题是您正在first_or_create块中调用该方法。

first_or_create的字面意思是first || create(*args, &block)。现在,当使用一个块调用create时,该块内的所有查询将通过称为scoping的方法

限定当前作用域。
  

文档状态:“将所有查询的范围都限制为当前范围。   ...   如果要在执行块期间删除所有先前的作用域(包括default_scope),请检查未作用域的范围。

以以下示例为例:

Comment.where(post_id: 1).scoping do
  Comment.first
end
=> SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = 1 ORDER BY "comments"."id" ASC LIMIT 1

您应该能够通过

解决此问题
def self.check_username(value)
  username = value.split("@").first
  while(User.unscoped.where(username: username).exists?)
    username += rand(100).to_s
  end
  username
end