grooble
grooble

Reputation: 657

rails how to reference current object in Model

This is a continuation of another question, but as it's different, I though I had better repost it as a new question:

Old Question


I'm adding quiz functionality to the twitter app from the Hartl tutorial and have these Models:

User is nearly the same as the tutorial:

class User < ActiveRecord::Base

  has_many :followed_users, through: :relationships, source: :followed

  has_many :takens, dependent: :destroy
  has_many :questions, through: :takens
end

Taken is a table of Question ids to User ids:

class Taken < ActiveRecord::Base
  belongs_to :user
  belongs_to :question

end

nothing interesting in Question:

class Question < ActiveRecord::Base
  attr_accessible :category, :correct, :option1, :option2, :option3, :qn
end

I want to be able to show followed_users and followers in order of the number of tests they have taken. In the console this can be had through:

User.find_by_id(1).question_ids.count

Then I can do something like:

User.find_by_id(1).followers.first.question_ids.count

in the console to get the count for a single follower.

I feel like I'm almost there.

How do I sort the followers and followed_users through their 'takens' count? (I was also looking at cache_count, which at first seemed promising, but might not be what I need...)


End Old Question

This is the answer from the other question: rails order through count on other table

and I went with a method like this in User.rb:

def users_sort_by_taken
User.find_by_sql("SELECT users.*
                  SELECT users.*
                  FROM users INNER JOIN takens
                  ON users.id = takens.user_id
                  GROUP BY users.id
                  ORDER BY count(takens.user_id) DESC")
end

which gets called in the users_controller.rb like so:

def following
    require 'will_paginate/array'
    @title = "Following"
    @user = User.find(params[:id])
    #@users = @user.followed_users.paginate(page: params[:page])
    @users = @user.users_sort_by_taken.paginate(page: params[:page])
    render 'show_follow'
end

(For reference, the commented out line is from the Hartl tutorial) all well and good, but now the current user is contained in the list of following (because of the above SQL). I need a way to eliminate the current user from the users_sort_by_taken.

I thought this might work:

WHERE (#{@current_user.id})

in the method,but I get this error:

Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id

I suppose I could pass it as an argument... but don't I already have the user as @user in the following line?

@users = @user.users_sort_by_taken.paginate(page: params[:page])

Why can't I reference the current user from a method in the User.rb model?

Or another way, can I pass the current_user (or @user or user) to the SQL to exclude the current_user from the SQL results?

Any help appreciated.

Upvotes: 3

Views: 17227

Answers (2)

Frederick Cheung
Frederick Cheung

Reputation: 84114

Every object has its own set of instance variables - the fact that @user or @current_user is set in one object means nothing to another object.

The receiver of a method (in this case your user) is always available as self, so self.id gets you the user's id

The self is actually implicit - most of the time you won't need it and just writing id would result in the same thing (as long as you're in an instance method of that user)

Upvotes: 9

Mischa
Mischa

Reputation: 43298

To reference @user's id in the model, you can simply use:

self.id

Upvotes: 6

Related Questions