2015-06-05 174 views
0

我有這樣的場景:最佳方式

class Category < ActiveRecord::Base 

    has_many  :children, :class_name => "Category", :foreign_key => "parent_id" 
    belongs_to :parent,  :class_name => "Category", :foreign_key => "parent_id" 

    def self.for_select 
    ?? DO SOMETHING ?? 
    end 

end 

而我只需要生成一個select_tag這樣的選擇:

Category 1 
    - Subcategory 1 
    - Subcategory 2 
    - Subcategory 3 
Category 2 
    - Subcategory 4 
    - Subcategory 5 

我怎樣才能做到這一點沒有強調用循環查詢的數據庫?

其實,我有這樣的事情,但它正在執行太多的疑問:

def self.for_select 
    ret = [] 
    Category.where(parent_id: nil).each do |m| 
    ret << [m.name, m.id] 
    m.children.each { |c| ret << ["- #{c.name}", c.id] } 
    end 
    return ret 
end 
+2

您可以加載孩子,以限制數據庫調用次數。 'Category.where(parent_id:nil).includes(:children)' – Santhosh

+0

@Santhosh是對的。我會將它作爲「範圍」添加... –

回答

1

目前尚不清楚你要出現在選擇的選項是什麼。在這裏,我假定「類別」是所有沒有父母的類別,而子類別是這些類別的直接子類別。

在您的類別類

#class methods section 
class << self 

    def select_options 
    top_level_categories = Category.where(:parent_id => nil).includes(:children) 
    top_level_categories.collect{|category| [[category.name, category.id]] + category.children.collect{|category| [" - #{category.name}, category.id]}} 
    end 

應返回

[["Category 1", 321], [" - Subcategory 1", 123], [" - Subcategory 2", 456]...etc] 

那麼,在您看來,做

select_tag "foo", options_for_select(Category.select_options)  
+0

第1類和第2類不是組,然後,在您說你想要的選項中?我認爲你的要求不清楚。 –

+0

@MattiaMalonni你有沒有試過我建議的?它將工作,即使我在我的代碼庫中使用它... –

+0

o我c。我正在重寫我的答案,因爲這很混亂。也意識到你不能只在開始時獲得Category.all –

0

試着這麼做:

class Category 
    # ... 

    scope :main_categories, -> { where(parent_id: nil) } 

    def self.for_select 
    main_categories.includes(:children).each_with_object([]) do |cat, ret| 
     ret << [cat.name, cat.id] 
     ret << cat.children.map { |sub| ["- #{sub.name}", sub.id] } 
    end 
    end 
end 

希望有幫助!