我有三个型号。用户,页面和网络。
我正在编写Page#visible_to?(user)
方法,并且想知道是否有比我目前更快/更有效/更好的方法。如果任何用户网络也链接到页面,则该方法应返回true。
目前的实施:
def visible_to?(user)
return true if networks.empty
user_network_ids = user.networks.pluck(:id)
!networks.detect { |network| user_network_ids.include?(network.id) }.nil?
end
其他选项包括使用&
运算符确定交集,或将此方法放在User上。想法?
答案 0 :(得分:2)
def visible_to?(user)
return true if networks.empty?
(user.networks & networks).size > 0
end
答案 1 :(得分:1)
您应该考虑使用Enumerable#any?
您可以简化
!networks.detect { |network| user_network_ids.include?(network.id) }.nil?
到
newtworks.any? { |network| user_network_ids.include? network.id }
虽然在这种情况下,(仅在我的深奥意见中)使用集合交叉点进行所有繁重的工作会更好:
def visible_to?(user)
networks.empty? || (networks.map(&:id) & user.networks.pluck(:id)).any?
end
如果存在重叠或网络为空,则返回true。
答案 2 :(得分:0)
只使用数据库,你可以这样做:
Page.joins(networks: :user).where(pages: {id: page_id}, users: {id: user_id}).any?
它生成此查询:
SELECT COUNT(*) FROM "pages"
INNER JOIN "networks" ON "networks"."page_id" = "pages"."id"
INNER JOIN "users" ON "users"."id" = "networks"."user_id"
WHERE "pages"."id" = <<page_id>> AND "users"."id" = <<user_id>>
最快的取决于您的具体情况以及数据的分发方式。例如,如果已经选择了用户的网络和页面的网络,因为您在其他地方也需要它们,并且没有很多要比较的元素,那么执行(user.networks & page.networks).any?
可能会更快。只是试验一下,找出最适合你的方法。