0

In my rails app I have a table Designs which are essentially the posts. Users can like these Designs (using the thumbs_up gem). This table is called Votes. On user's profile pages, I'm showing all of the Designs that they have liked (or voted for). In the user model, I have a method:

def favorites
  Design.joins(:votes).where('voter_id = ?', self.id).where('voteable_type = ?', 'Design').where('vote = ?', true)
end

Then in the user's controller to call these designs I have

def show
  @designs = @user.favorites
end

This shows all of the designs they have liked, but it's in order of when the Design was created, not when the Vote was created. The Vote table has a created_at column so I know I can sort these Designs based on when they liked them.

I tried this with no luck

def favorites
  results = Design.joins(:votes).where('voter_id = ?', self.id).where('voteable_type = ?', 'Design').where('vote = ?', true)
  results.sort! {|t1, t2| t2.vote.created_at <=> t1.vote.created_at}
end

How can I sort the Designs based on when that user liked them.

the Vote table has these columns

vote: boolean
voteable_id: integer
voteable_type: string
voter_id: integer
created_at: date
updated_at: date

thanks!

2 Answers 2

1
+50

The prior answer doesn't work because scopes work at the Class level, so when you use it on a instance of User, it assumes favorites is a instance method or association.

What I recommend you do is use the Vote model, and reference the belongs_to Design association on Vote:

def show
  @votes = @user.votes.includes(:design).order(created_at: :asc)
  @designs = @votes.collect {|v| v.design }
end

You could feel free to move that to the User model in place of your favorites method like so:

def favorites
  @favorites ||= self.votes.includes(:design).order(created_at: :asc).collect {|v| v.design }
end

UPDATE

Since you are using this thumbs_up gem, the following will work:

In Action

def show
  @designs = @user.votes.where(voteable_type: 'Design').order(created_at: :asc).collect {|v| v.voteable}
end

Or Method

def favorites
  @favorites ||= self.votes.where(voteable_type: 'Design').order(created_at: :asc).collect {|v| v.voteable}
end

https://github.com/bouchard/thumbs_up

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for the reply @omarvelous. With the second method you mentioned in my User model, with this call in the controller: @designs = @user.favorites, I am receiving the error Association named "design" was not found; perhaps you misspelled it?. The way this gem works is using a acts_as_voteable in the voteable model (if that's relevent information), because I'm unsure why the association wasn't found, besides to find the voteable model of the Vote it's stored in a string called voteable_type
I quickly read the plugin, you'll want to do the following, I updated in the answer above.
Wow thanks so much for taking all this time to help me out. I really appreciate it! I think you def got it right but Im getting this error involving type association. undefined method "by_type"...I recently read that the #type association was deprecated
Updated once more... Odd, it's still in the readme of the gem
Misread your question, you are using the github.com/bouchard/thumbs_up gem! lol ok. ENTIRELY up to you, but github.com/ryanto/acts_as_votable might be more up to date, also supports Rails 4.
|
1

I think you'll be able to use a scope for this - I'd use a scope on the user model to communicate with the votes model from your user instance:

#app/models/user.rb
Class User < ActiveRecord::Base
    has_many :votes, as :voteable
    has_many :designs, through: :votes

    scope :favorites, -> { joins(:votes).where('voter_id = ? AND votable_type = ? AND vote = ?', id, 'Design', true) }
    scope :latest, -> { order(created_at: :asc) }
    scope :latest_favorites, -> { favorites.order(created_at: :asc) }
end

This will allow you to call:

@user.favorites.latest
@user.latest_favorites

5 Comments

Weirdly, I'm getting an undefined method "favorites" which has been defined in the User model
How is your @user instance var defined?
@user = User.find_by_username(params[:id])
find_by_username is a dynamic method and it wont work if users table doesn't have a username column or User model haven't a username attribute. Check if it returns nil.
Dynamic finders have been deprecated in Rails 4. You should be using User.find_by(username: params[:username]). You seem to have an attribute mismatch here though (using an id to search by username). Have you tried User.find(params[:id])?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.