开发者

find_or_create_by multiple attributes not finding records when called in context of belongs_to object (AR bug in 2.3.11?)

I am adding omniauth to a rails 2.3.11 application with devise. I'm basically following Ryan Bate's railscast (with appropriate modifications for rails 2.3). But I'm seeing something very odd in testing this part of the code:

class AuthenticationsController < ApplicationController
  ...

  def create
    auth = request.env["omniauth.auth"]
    current_user.authentications.find_or_create_by_provider_and_uid(auth['provider'], auth['uid'])
    flash[:notice] = "Authentication successful."
    redirect_to authentications_url
  end

  ...
end

The find_or_create always creates. In the log, I see this select:

SELECT * FROM `authentications` WHERE (`authentications`.`provider` IN ('facebook','XXXXXXX') AND `authentications`.`uid` IS NULL) AND ((`authentications`.`user_id` = 10)) LIMIT 1

That is not the right select for that method. auth['provider'] and auth['uid'] are populated correctly (and it creates the new record just fine).

More perplexing: If I go into the console and do Authentication.find_or_create_by_provider_and_uid('facebook', 'XXXXX'), it works fine (it finds the existing record). But if I get a user and do user.authentications.find_or_create_by_provider_and_uid('facebook', 'XXXXX'), it creates a new record and I see the same problematic query statement in the log.

I know I can work around this (and Ryan Bates changes this code later anyway), but this is very troubling. Am I missing something or does this look like a bug in ActiveRecord?

This is not specific to OmniAuth or Devise. Before submitting this, I tried it with two other classes (rather simple classes). Same result [ Klass.find_or_create_by_a_and_b('A','B') works but parent.klasses.find_or_create_by_a_and_b('A','B') generates a select that wants b to be null and a in ('A开发者_StackOverflow社区','B')].

Now I'm definitely thinking this is a bug 2.3.11. Before I submit a bug, does anybody see anything I'm missing? Has anyone seen this problem?


I just updated an app from Rails 2.3.10 to 2.3.11 and I ran into this bug, too.

In our code, we have:

      rate_plan = lodging.rate_plans.find_or_create_by_primary_code_and_secondary_code(rate_plan_code, inv_type_code)

which worked fine under 2.3.10. Under 2.3.11, rate_plan winds up being a new record, even though find_by_primary_code_and_secondary_code(rate_plan_code, inv_type_code) will find an existing record. Not only is rate_plan a new record in 2.3.11, but it's not saved because our uniqueness validation isn't met.

Ugh. I'll go back to 2.3.10 for now.


What are the values of auth['provider'] and auth['uid']? Maybe I am wrong, but it looks to me that auth['provider'] is ['facebook','XXXXXXX'] and auth['uid'] is nil.


It definetely must be, like Tudor Constantin says, a problem with the auth['provider'] value, as it seems to be an array. Have you tried to make a puts call over this variable? What is the result?

Also I hope that you know that this:

Authentication.find_or_create_by_provider_and_uid('facebook', 'XXXXX')

is not the same as this:

user.authentications.find_or_create_by_provider_and_uid('facebook', 'XXXXX')

In the first case you're searching through all Authentication instances / rows, while in the second one you're reducing the search scope so it only looks for Authentication instances / rows that belong to that concrete instance of User.


Check

auth['uid']

I guess it is coming blank for you. That is why

`authentications`.`uid` IS NULL) AND ((`authentications`.`user_id` = 10))

is conflicting

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜