简化 Ruby 变量定义时的控制流程

3

我在Rails应用程序的页面上定义了三个变量:

  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

我注意到if和unless语句中有很多重复的代码。如何编写三个变量声明,使它们等于上面的变量声明,并确保变量始终为0而不是nil

1个回答

2
您可以在这里使用条件赋值运算符来帮助减少代码。例如:
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

条件赋值运算符的作用是如果第一个部分求值为nil,则使用右侧作为默认值。

+1 用于点赞和踩赞的重构。我也在做这个。由于减少了数据库访问次数,速度应该会更快。我还在想是否应该将 elseif 改为 else,因为如果两个 Vote 查询的 count == 0,就有可能导致 active 未定义,从而存在潜在的逻辑漏洞。 - the Tin Man
我大多数情况下不会改变active变量,因为上下文中我没有足够的信息,但我同意那里可能存在逻辑漏洞。例如,如果当前用户在一个帖子上只能投一票,那么可以通过使用类似于Vote.first(:user_id => current_user.id, :post_id => post.id) 的东西来简化该逻辑,然后在Ruby中评估方向。但由于我对应用程序了解不多,所以我让它保持原样。 :) - Marc Baumbach
呵呵,很高兴这不是我要维护的系统。 :-) - the Tin Man
我是指 Vote.where(:user_id => current_user.id, :post_id => post.id).first。那个应该可以正常工作。 - Marc Baumbach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接