自循环中的 Active Record 模型查询在 rails 中执行不同
Active Record model query in self loop executes differently in rails
我正在使用 facebook-omniauth
gem 构建 Facebook Oauth。我写了这个方法来根据授权数据创建用户。
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 []>
如何修改此查询使其正常执行。
问题是您在 first_or_create
块中调用该方法。
first_or_create
字面意思就是first || create(*args, &block)
。现在,当使用块调用 create
时,该块内的所有查询都通过名为 scoping
的方法限定在当前范围内
Docs State: "Scope all queries to the current scope.
...
Please check unscoped if you want to remove all previous scopes (including the default_scope) during the execution of a block.
例如:
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
我正在使用 facebook-omniauth
gem 构建 Facebook Oauth。我写了这个方法来根据授权数据创建用户。
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 []>
如何修改此查询使其正常执行。
问题是您在 first_or_create
块中调用该方法。
first_or_create
字面意思就是first || create(*args, &block)
。现在,当使用块调用 create
时,该块内的所有查询都通过名为 scoping
Docs State: "Scope all queries to the current scope. ... Please check unscoped if you want to remove all previous scopes (including the default_scope) during the execution of a block.
例如:
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