def follows(follower, followed)
follow = Follows.where("follower = ? AND followed = ?", follower, followed)
if follow
true
else
false
end
end
这是我的观看代码:
<% if current_user.id == @user.id%>
<p>This is you!</p>
<% else %>
<% if follows(current_user.id, @user.id)%>
<p>You already follow <%= @user.username %>
<% else %>
<p><%= link_to "Follow!", follow_path(@user.id) %></p>
<% end %>
<% end %>
我想检查用户是否跟随另一个用户,所以写了这个。它需要两个用户ID,并查询数据库, 应该 在找到匹配时返回true,否则返回false。但它总是回归真实。这是为什么?
答案 0 :(得分:7)
让我们先从一些风格和设计问题开始,然后以实际答案结束:
模型按惯例是单数的。否则只会让你工作更多。在这种情况下,我建议将Following
作为合适的名称,例如“用户有很多关注”。
外键应以_id
结尾。否则只会让你工作更多。所以follower_id
和followed_id
。
旨在用于其真/假性质的方法(“query methods”)应以?结尾,因此follows?
代替follows
,
你的if语句是多余的,一旦条件做对了就可以安全删除。在ruby中,在条件语境中,我们更关心事物评估是否为真/假,而不是它们是字面true
还是false
。这意味着nil
或false
以外的任何内容都将是“真实的”。
事实上,您的方法完全取决于User
个对象已知的信息,这表明最好将其挂在这些对象之外,例如current_user.follows? other_user
。
您正在使用关联重复已经提供给您的行为。
最后,考虑到所有这些因素,答案是:
class User < ActiveRecord::Base
has_many :followings, :class_name => 'Following', :foreign_key => 'followed_id'
has_many :followers, :through => 'followings'
def follows?(other)
other.followed_by? self
end
def followed_by?(other)
followers.include? other
end
end
NB :此处followed_by?
方法的使用是double dispatch的使用,可以防止一个用户直接了解该问题的(次要)Law of Demeter violation另一个用户的关注者的状态。相反,第一个用户对象向第二个用户对象询问一个直接问题(“你跟着我吗?”)并将结果基于答案。 (它本身也可能是一种有用的方法。)
答案 1 :(得分:3)
它总是返回true的原因是,即使没有找到记录,where()返回一个空数组。空数组是“true”。在其他新闻中,结构:
if (condition)
true
else
false
end
可以替换为:
condition
答案 2 :(得分:1)
follow实际上是ActiveRecord :: Relation的一个实例,而不是查询的结果集。要找出查询是否返回任何行,请使用follow.count。例如
if follow.count > 0
true
else
false
end
答案 3 :(得分:1)
您可以使用present?
。你的代码应该是
if follow.present?
true
else
false
end
答案 4 :(得分:0)
@rein Heinrichs的回答很棒。他为你提供了最好的Rails方法来解决它。但我想解释为什么你写的不起作用,以及你应该如何解决这个问题。
Follows.where(...)
返回一个数组,自己验证这个的简单方法是在rails控制台中运行该行(在控制台中键入rails c
)。
数组(即使是空数组)不是nil
,并且总是会计算为true
。
因此,要根据无论是否找到任何关注者的事实返回布尔值,只需检查where
结果中的项目数量(使用size > 0
或present?
)
因此,您的follows
函数可能已被重写为:
def follows(follower, followed)
Follows.where("follower = ? AND followed = ?", follower, followed).present?
end
这实际上也很可读。希望这会有所帮助。