在 Ruby 中对树状结构(tree)进行 map 操作 博客分类: Ruby rubytreemap
程序员文章站
2024-02-12 14:22:40
...
class BookChapter < ActiveRecord::Base belongs_to :parent, :class_name => 'BookChapter', :foreign_key => 'parent_id' has_many :children, :class_name => 'BookChapter', :foreign_key => 'parent_id', :order => 'play_order' def map(parent_mapping=nil, &block) result = block.call self, parent_mapping children.each do |chapter| chapter.map result, &block end result end end
usage:
class EpubChapter attr_accessor :title def initialize @children = [] end def add_child(child) @children << child end end book_chapter = BookChapter.first book_chapter.map do |chapter, parent| # 这里处理父子关系,例如: child = EpubChapter.new child.title = chapter.title parent.add_child child if parent child end
这是改进过之后的版本了,之前一个版本使用简单些,但是有接口上的双向依赖,就不贴出来了。
然后呢,还可以把这个方法抽出来,放到 module 中,这样就可以到处使用了:
module MappableTree def map(parent_mapping=nil, &block) result = block.call self, parent_mapping children.each do |child| child.map result, &block end result end end class Nokogiri::XML::Node include MappableTree end
还有点味道,这个 map 方法要求实现类必须有一个 children 方法,而且这个 children 方法的返回值还必须有一个 each 方法,稍微封装一下,变成:
module MappableTree def map(parent_mapping=nil, &block) result = block.call self, parent_mapping each_child do |child| child.map result, &block end result end end class Nokogiri::XML::Node include MappableTree def each_child &block children.each &block end end
这样耦合就不那么紧了。