捞出一个数组的数据

在此前的一家公司测试题中,要实现一个功能,捞出所有用户所在团队 @team 的所有项目@project 发生的动态事件 @events,我当时写的代码是大概这样的:

def index
  @team = current_user.participated_teams.find(params[:team_id])
  @projects = @team.projects
  @events = @projects.collect{ |project| project.events }.flatten
end

学习完 Ruby on Rails 教程 之后,知道另一种效率更高的底层方法。

类似 Twitter 或者微博的 timeline ,实现的功能是这样的,显示所有 我关注的用户 所发出来的 微博

在数据库层面,首先要捞出 我关注的用户,这个很好办,比如说

@followers = current_user.followers

接下来,要捞出这些用户的所有 微博。对于每一个关注的用户都有很多微博,@follower.mircoposts 这个的方法是可以的,但是没有 @followers.mircoposts 这样的方法。因为 @followers 是一个数组。

教程中,是这样捞出所有 我关注的用户 所发出来的 微博 的。

def feed
  Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
end

为了提高效率,还可以使用子查询(subselect),在数据库层查找关注的用户 ID,具体实现方法是

def feed
  following_ids = "SELECT following_id FROM relationships WHERE  follower_id = :user_id"
  Micropost.where("user_id IN (#{following_ids}) OR user_id = :user_id", user_id: id)
end

同理,将我之前的代码重构一下,可以这么写

def index
  @team = current_user.participated_teams.find(params[:team_id])
  @projects = @team.projects
  project_ids = "SELECT project_id FROM projects WHERE team_id = #{@team.id}"
  @events =  Event.where("project_id IN (#{project_ids})")
end
· rails, SQL