重构 怎么用 Ruby 的方式 (Block) 来实现这个递归

gfreezy_ · 2012年12月15日 · 最后由 gfreezy_ 回复于 2012年12月16日 · 4680 次阅读

def get_all_friends(uid, client) friends = client.friendships.friends(uid: uid) total = friends.total_number get_friends(total, 0, uid, client) end

def get_friends(total, cursor, uid, client) left = total count = [200, left].min

friends = client.friendships.friends(uid: uid, count: count, cursor: cursor) left -= count next_cursor = friends.next_cursor

return friends if (left == 0 || next_cursor == 0)

more_firends = get_friends(left, next_cursor, uid, client) more_firends.users << friends.users return more_firends end

get_all_friends(uid, observer.client).users.map do |info| user = User.find_or_create_by_uid_and_name(uid: info.id, name: info.name) follow(user) user end

这段代码实现的是从微博获取所有关注(默认 API 只能根据 cursor 来一页一页的获取)。但是接触 Ruby 不久,不会用 Ruby 的方式( block, do...end )来实现。

然后因为一次获取其他也是靠 cursor 和 count 来定位的东西这种情况很普遍,可以通过将client.friendships.friends(uid: uid, count: count, cursor: cursor)这个提取出来,以函数的方式传进去(函数式的想法)的方法来抽象。

不知道 Ruby 的方式是怎么样来处理的?Ruby block的思想转不过来。

能问下 为何 get_friends 要用递归而不是循环嘛?

#1 楼 @iBachue 直觉上就想到了递归,没想到循环。好像用 loop 然后中间判断循环退出也比较简单。花时间看了下 Ruby 的 block Proc ,重构了下,现在更加的通用。

现在只需要如下这样使用就可以了:

response = fetch_all do |count, cursor| observer.client.friendships.friends(uid: uid, count: count, cursor: cursor) end

代码:

def fetch_all(&fetch_proc) res = fetch_proc.call(10, 0) total = res.total_number return res if total <= 10 fetch(total, 0, &fetch_proc) end

def fetch(total, cursor, &fetch_proc) left = total count = [200, left].min

res = fetch_proc.call(count, cursor) left -= count next_cursor = res.next_cursor

return res if (left == 0 || next_cursor == 0)

more_res = fetch(left, next_cursor, &fetch_proc) more_res.users << res.users more_res end

需要 登录 后方可回复, 如果你还没有账号请 注册新账号