has_many returns an array instead of ActiveRecord class
Asked Answered
F

1

6

I am following OmniAuth railscasts and trying to implement the same with authlogic + facebook instead of devise + twitter as shown in the railscast.

Maybe my understanding of has_many still isn't good but in the railscasts ryan has the following code in AuthenticationsController

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

In my implementation current_user.authentications returns an array [] how can I call find_or_create_by_provider_and_uid on an array?

Is my implementation wrong? Isn't has_many suppose to return an array?

Error I get is that I am calling find_or_create_by_provider_and_uid on a nil object.

current_user.authentications is nil well because the user does not have any authentications yet.

Furring answered 2/6, 2011 at 18:52 Comment(5)
Are you sure you are using Rails 3, or are you using an earlier version of Rails?Chon
positive about it being rails 3. had this problem last night, thought I'll ask here before I tackle with it again at home. Perhaps there is something wrong in my source. but shouldn't has_many bring back an array?Furring
It appears to me that what you have coded should work. Have you verified that you aren't overriding the authentications relation with a function of your own (for example in the User class or in a related module)? Without seeing more code this is really all I can think of.Chon
I understand. I'll go home and take a closer look. if not, will try to clone ryans github repo for this episode.Furring
Did you ever figure this out? All of my hm:t relationships inexplicably started returning Arrays instead of ActiveRecord::Relations today. I've tried multiple versions of rails 3, and many different hm:t relationships on many different models. All of them return Arrays. Very inconvenient!Librium
H
5

The array is actually an AssociationProxy instance, which delegates all method calls to the internal object, which is an array in the case of a has_many association (also see this question). This means you should be able to call magic methods like find_or_create_by_provider_and_uid, as well as scopes etc. on it just fine.

I found this question because I stumbled over a similar problem: for some reason I couldn't call ActiveRecord::Relation#klass to find out the model class:

post.comments.klass # => NoMethodError

But by calling relation first you can get a normal ActiveRecord::Relation instance:

post.comments.relation.klass # => Comment
Halsey answered 20/1, 2012 at 0:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.