2012-12-30 14 views
0

我有一個Skill模型,它有許多先決條件(或prereqs在我的模型中),我需要創建一個N層深度的地圖這是技能的先決條件,因爲我需要將這些信息傳遞給JavaScript(在我的控制器中使用gon寶石),以獲得一些瘋狂的HTML5/KineticJS動作,該動作顯示了該技能與其他人之間關係的鳥瞰圖。試圖構建一個嵌套數組的數組來映射N個關聯深入Rails模型

現在,下面的代碼非常適合深入地描繪5個層次。

delegate :url_helpers, to: 'Rails.application.routes' 

def prereqs_map 
    prereqs_array = [ self.title.to_s, url_helpers.skill_path(self), Array.new(prereqs) ] 
    prereqs_array[2] = prereqs_array[2].map do |prereq1| 
    prereq1 = [ prereq1.title.to_s, url_helpers.skill_path(prereq1), Array.new(prereq1.prereqs).map do |prereq2| 
     prereq2 = [ prereq2.title.to_s, url_helpers.skill_path(prereq2), Array.new(prereq2.prereqs).map do |prereq3| 
     prereq3 = [ prereq3.title.to_s, url_helpers.skill_path(prereq3), Array.new(prereq3.prereqs).map do |prereq4| 
      prereq4 = [ prereq4.title.to_s, url_helpers.skill_path(prereq4), Array.new(prereq4.prereqs).map do |prereq5| 
      prereq5 = [ prereq5.title.to_s, url_helpers.skill_path(prereq5), [] ] 
      end ] # prereq depth 5 
     end ] # prereq depth 4 
     end ] # prereq depth 3 
    end ] # prereq depth 2 
    end # prereq depth 1 

    return prereqs_array 
end 

的問題,正如你所看到的,是它的嵌套地圖超級凌亂,而且也沒有辦法,我可以找出傳遞一個depth參數,並有方法映射出任何深度I通過。

我認爲必須有一個更好的方法來做到這一點。有什麼想法嗎?

+0

似乎是遞歸一個完美的候選人,但它真的很難理解它是如何工作 – apneadiving

+0

你確認'prereq1.prereqs'是一個整數? – apneadiving

+0

@apneadiving它似乎是一個遞歸的完美候選人,但我無法弄清楚如何使用遞歸。 prereq1.prereqs不是一個整數。這是一系列其他技能,已作爲先決條件添加到此技能中。 –

回答

2

試試這個:

class Skill 
    # has many prereqs? 

    def prereqs_map(depth = 5) 
    mapping = Proc.new do |node, depth, current_level| 
     [node.title.to_s, url_helpers.skill_path(node), node.prereqs.map {|prereq| mapping.call(prereq, depth, current_level+1)}] if current_level <= depth 
    end 
    mapping.call(self, depth, 0) 
    end 

end 

>> skill.prereqs_map(5) 
+0

對不起,現在更新深度 –

+0

優雅,它完美的作品。謝謝你教我新東西! –

1

通過在模型中添加一個實例方法「to_tree」,您可以重新編譯它。以下隨機設置了一個依賴關係樹,然後以您所需的格式爲您提供一組數組。

class Skill 

    attr_accessor :prereqs 
    attr_accessor :title 

    def randomly_create_tree depth=0 
    self.title = ["Coding", "Winning", "Smiling", "Eating"][rand(4)] 
    if depth < 3 
     self.prereqs = [] 
     (0..rand(3)).each do 
     skill = Skill.new 
     skill.randomly_create_tree(depth + 1) 
     self.prereqs << skill 
     end 
    else 
     self.prereqs = [] 
    end 
    self 
    end 

    def to_tree 
    prereqs.collect do |prereq| 
     [self.title, prereq.to_tree] 
    end 
    end 

然後:在

s = Skill.new 
s.randomly_create_tree 
s.to_tree 

結果:

[["Coding", [["Winning", [["Winning", []], ["Winning", []]]]]]] 

當每個串的是隨機生成的標題。您可能還想添加您的url_helpers.skill_path,但我不確定它會做什麼。

+0

這樣的東西可能已經奏效了,但是我發現創建一個隨機樹的例子有點令人困惑,因爲大部分的東西並不是我想要做的;先決關係已經存在於關聯中,我只想將它們映射到數組中。下面瓦列裏的回答正是我所期待的。 –