Search code examples
ruby-on-railsrubyvariablescontrol-flow

Simplifying Ruby control flow when defining variables


I'm defining three variables on a Rails app's page:

  if current_user
    if Vote.where(:user_id => current_user.id, :post_id => post.id, :direction => 0).count > 0
      active = ' upactive'
    elsif Vote.where(:user_id => current_user.id, :post_id => post.id, :direction => 1).count > 0
      active = ' downactive'
    end
  end

  unless Vote.group(:post_id).where(:post_id => @posts.map(&:id), :direction => 0).count[post.id] == nil
    upvotes = Vote.group(:post_id).where(:post_id => @posts.map(&:id), :direction => 0).count[post.id]
  else
    upvotes = 0
  end

  unless Vote.group(:post_id).where(:post_id => @posts.map(&:id), :direction => 1).count[post.id] == nil
    downvotes = Vote.group(:post_id).where(:post_id => @posts.map(&:id), :direction => 1).count[post.id]
  else
    downvotes = 0
  end

I notice there is quite a bit of repeated code in the if and unless statements. How can I write three variable declarations that equal the ones above, making sure the variable is always 0 instead of nil.


Solution

  • You can make use of the conditional assignment operator here to help reduce code. For example:

    if current_user
      if Vote.where(:user_id => current_user.id, :post_id => post.id, :direction => 0).count > 0
        active = ' upactive'
      elsif Vote.where(:user_id => current_user.id, :post_id => post.id, :direction => 1).count > 0
        active = ' downactive'
      end
    end
    
    upvotes = Vote.group(:post_id).where(:post_id => @posts.map(&:id), :direction => 0).count[post.id] || 0
    downvotes = Vote.group(:post_id).where(:post_id => @posts.map(&:id), :direction => 1).count[post.id] || 0
    

    The conditional assignment operator essentially says if the first portion evaluates to nil, use the right side as the default value.