扩展Active Record以减少冗余

时间:2011-02-22 22:06:01

标签: ruby-on-rails ruby refactoring

假设我在Rails应用程序中有两个类:

class Subject < ActiveRecord::Base  
  def children?
    Subject.where(:parent_id => self.id).length > 0
  end

 def children
   Subject.where(:parent_id => self.id)
 end 
end


class Region < ActiveRecord::Base  
  def children?
    Region.where(:parent_id => self.id).length > 0
  end

 def children
   Region.where(:parent_id => self.id)
 end 
end

减少冗余类方法的最佳方法是什么?我会用两种新方法扩展ActiveRecord吗?如果是这样,我怎么能写这两个新方法可用于这两个类?

谢谢, 麦克

4 个答案:

答案 0 :(得分:2)

实际上你在处理的是has_many关联。

DRY原则非常好,但不适用于这种情况。你想从模型中提取非常简单和原生的东西,而它会使主要图片复杂化。

所以你可以重构一下

class Subject < ActiveRecord::Base
  has_many :children, :class_name => "Subject", :foreign_key => :parent_id

  def children?
    children.present?
  end
end

答案 1 :(得分:1)

查看acts_as_tree以查看其功能或使用它,因为您似乎正在尝试执行相同的任务。

答案 2 :(得分:1)

如果您正在处理小对象,快速解决方法是在应用程序帮助文件中创建2个通用方法:

def children?(myObject)
  myObject.where(:parent_id => myObject.id).length > 0
end
def children(myObject)
  myObject.where(:parent_id => myObject.id)
end 

编辑: 对于任何更加资源密集的东西,你可以在ActiveRecord :: Base中定义一个方法,因为它们都从它继承。

def children?
  self.where(:parent_id => self.id).length > 0
end
def children
  self.where(:parent_id => self.id)
end

答案 3 :(得分:1)

我同意@ abdollar关于使用acts_as_tree的建议。或者你可以在同一个表上创建一个关联(这就是acts_as_tree的作用)。

如果你想使用你给出的那些方法作为例子来自己动手,你可以在lib中创建一个模块,你可以在模型中创建并包含它......

# lib/children.rb
module Children
  def children
    self.class.where(:parent_id => self.id)
  end

  def children?
    children.present?
  end
end

# app/models/subject.rb (or any other model)
require 'children'
class Subject < ActiveRecord::Base
  include Children
end

如果您使用的是rails 2,则不需要执行require 'children',因为lib是自动加载的。如果您正在使用rails 3,您可以将其放入初始化程序或清理它。