`
taito
  • 浏览: 94501 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

将旧有的Acts_As_Tree转成Acts_As_Threaded

阅读更多
转换的重点其实只有一个,重点在于lft和rgt两个字段的初始化,否则其他字段的初始
化对会写程序的人应该难不倒才是,转换的相异点来自于新增四个字段:root_id(根ID)
、lft(左值)、rgt(右值)、depth(深)

改成这样好处多多,可以使用单一query取得"所有"子代(不限阶层),且所有子代count
详情请参阅Acts_As_Threaded

以下是转换实做的部份,用于"Cate"这个model
[[Migrate]]

class FixCate < ActiveRecord::Migration 
    def self.up 
        puts "fixing Cate" 
            Cate.reset_column_information 
            Cate.find(:all).each do |c| 
                if c.parent_id == nil 
                    c.parent_id = 0 
                    c.update 
                end 
            end 
        puts "fixed Cate" 
        change_column "cates" , "parent_id",    :integer,  :default => 0,  :null => false 
        add_column "cates" , "root_id",    :integer,   :default => 0,  :null => false 
        add_column "cates" , "lft",        :integer 
        add_column "cates" , "rgt",        :integer 
        add_column "cates" , "depth",      :integer,   :default => 0,  :null => false 
        puts "fixing Cate" 
            Cate.reset_column_information 
            Cate.find(:all).each do |c| 
                if c.parent_id == 0 
                    c.root_id = c.id 
                    c.update 
                end 
            end 
        puts "fixed Cate" 
    end 

    def self.down 
        change_column "cates" , "parent_id",       :integer 
        remove_column "cates" , "root_id" 
        remove_column "cates" , "lft" 
        remove_column "cates" , "rgt" 
        remove_column "cates" , "depth" 
        puts "fixing Cate" 
            Cate.reset_column_information 
            Cate.find(:all).each do |c| 
                if c.parent_id == 0 
                    c.parent_id = nil 
                    c.update 
                end 
            end 
        puts "fixed Cate" 
    end 
end 


[[cate.rb (Model)]]
class Cate < ActiveRecord::Base 
    acts_as_threaded 
    def parent 
        if self.parent_id == 0 
            return nil 
        else 
            return Cate.find(self.parent_id) 
        end 
    end 
    def children 
        #direct_children与all_children选一个使用 
        return self.direct_children 
    end 
end

[[cates_controller.rb (Controller)]] 
class CatesController < ApplicationController 
  def init 
      Cate.find(:all).each do |c| 
          c.before_create 
          c.after_create 
      end 
  end 
end


简单的来说,就是在migrate时做基本的转换与初始化,将parent_id = null转为parent_id = 0,然后将parent_id = 0的实体(root)的root_id改为自己(self.id),这样就完成基本的两个字段的初始化。

Model内新增两个method来复写掉继承的mothod,Acts_As_Threaded预设没有parent与children这两个method,且如果之前用Acts_As_Tree实做的话,通常root实体的parent的值通常为null,而修正后会变为0,所以需要另外复写。

因为migrate没有支持完整的Rails与AR与plugin,所以最后一步的初始化要留到全部建立好后,在Controller内执行才行,上面的Controller内写的init就是初始化的方式,执行一次即可。

如果详细看Acts_As_Threaded内的语法就会得知lft与rgt的migeate为何没加入":default => 0, :null => false"这段语法与为何要那样的初始化,不过还是希望有神人可以想出在migrate内一次做完全部的方法
1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics