Расширение Active Record для уменьшения избыточности - PullRequest
2 голосов
/ 23 февраля 2011

Предположим, у меня есть два класса в приложении 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 двумя новыми методами? Если так, как я могу написать эти два новых метода, которые будут доступны для обоих классов?

Спасибо, Mike

Ответы [ 4 ]

2 голосов
/ 23 февраля 2011

На самом деле вы имеете дело с has_many ассоциацией.

DRY принцип очень хорош, но не для этого случая.Вы хотите извлечь из модели очень простые и нативные вещи, в то время как это усложнит основную картинку.

Так что вы можете просто немного изменить рефакторинг

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

  def children?
    children.present?
  end
end
1 голос
/ 23 февраля 2011

если вы имеете дело с небольшими объектами, быстрое решение состоит в том, чтобы создать 2 универсальных метода в файле помощника приложения:

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

Edit: для чего-либо более ресурсоемкого вы можете определить метод в ActiveRecord :: Base, так как они оба наследуют его.

def children?
  self.where(:parent_id => self.id).length > 0
end
def children
  self.where(:parent_id => self.id)
end
1 голос
/ 23 февраля 2011

Я согласен с предложением @ abdollar об использовании acts_as_tree. Или вы можете просто создать ассоциацию для одной и той же таблицы (что именно делает поступок act_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, вы можете поместить это в инициализатор или что-нибудь, чтобы очистить его.

1 голос
/ 23 февраля 2011

Взгляните на acts_as_tree , чтобы увидеть, что он делает, или используйте его так, как будто вы пытаетесь выполнить те же задачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...