Question

At the end of a blog post I would like to display a teaser link to another random post. Obviously this link should be NOT a teaser for the current post itself.

I figured already out how to choose a random post, but there is still the chance that the teaser link is a link to the current post. I couldn't figure out, how can I exclude this case.

Here is my controller:

def show
    @post = Post.find(params[:id])
    @staff_pickrandom = Post.where(staff_pick:true).order("RANDOM()").limit(1)
end

I am quite new to Rails and I am still struggling with basic stuff. Sorry, if this is an easy one. Thank you so much for helping out!!!

UPDATE: I am using Rails 3.2 and the "friendly_id" Gem.

Was it helpful?

Solution

Using order('RANDOM()').limit(1) is the right way to start since it is better to let the DB choose a random record, than fetching a large set of ids, and letting Ruby sample from an array. In order to avoid choosing the post you are currently on use where.not to exclude that post

 Post.where(staff_pick: true).where.not(id: @post.id).order('RANDOM()').limit(1)

or

 Post.where(staff_pick: true).where('id != ?', @post.id).order('RANDOM()').limit(1)

OTHER TIPS

It depends on how large you want the set to be. The easiest is:

@staff_pickrandom = Post.where(staff_pick:true).sample

That will pick a random object from the array returned by Post.where(staff_pick:true). If you find that is too many records then you can add more into the where clauses

def show
    @post = Post.find(params[:id]) # [1]
    ids = Post.ids # [1, 2, 3, 4, 5]
    ids.shuffle # [3, 5, 2, 1, 4]
    ids.delete(params[:id]) # [3, 5, 2, 4]
    @staff_pickrandom = Post.find(ids[0]) # [3]
end

there is many way to do that. It's better to create a helper.

Try:

@post = Post.where(staff_pick: true).where.not(id: params[:id]).shuffle.first

If where.not can't be done like in Rails 4, try:

Post.where(staff_pick: true).where("id != ?", params[:id]).shuffle.first

Edit: since you're using friendly_id gem, you shouldn't compare the slug (params[:id]) to a recorded id in database. First declare which post you're looking for like @post = Post.find(params[:id]) and remove params[:id] from the queries above and use @post.id instead.

I guess that should work!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top