Rails: как эффективно использовать self.inherited - PullRequest
3 голосов
/ 17 июля 2009

У меня есть модель AbstractRecord, из которой происходят некоторые из конкретных моделей (которые имеют свои собственные таблицы). Ниже приводится наследство.

AbstractRecord < ActiveRecord::Base
Blog < AbstractRecord
Post < AbstractRecord
....
....

Чтобы Rails мог искать подходящие таблицы при наличии наследования, в документах API говорится, что нужно определить метод класса abstract_class? это возвращает true, так что рельсы не будут искать свою таблицу. В моем случае, чтобы рельсы искали таблицу блогов (а не таблицу abstract_records, как это обычно бывает в STI) я определил метод abstract_class? в AbstractRecord, который возвращает истину. Все запросы, кажется, работают нормально. Но я вижу, что всякий раз, когда я создаю экземпляр Blog, rails показывает его как Blog (abstract) в консоли, поскольку его родительский класс возвращает true. Чтобы избежать этого, я мог бы снова определить abstract_class? который возвращает false в классе Blog.

Но я думал вместо определения abstract_class? во всех дочерних моделях, если бы я мог как-то использовать self.inherited и определить этот метод в самом AbstractClass. Я попытался использовать несколько подходов (следующие) ни один из них не работает.

class AbstractRecord < ActiveRecord::Base
 def self.abstract_class?
    true
 end

 def self.inherited(subclass)
  super
  subclass.instance_eval do
   define_method(:abstract_class?) { false }
  end
 end  
end

class AbstractRecord < ActiveRecord::Base
 def self.abstract_class?
    true
 end

 def self.inherited(subclass)
  super
  subclass.class_eval do
   define_method(:abstract_class?) { false }
  end
 end  
end

class AbstractRecord < ActiveRecord::Base
 def self.abstract_class?
    true
 end

 def self.inherited(subclass)
  super
  subclass.instance_eval do
   def abstract_class?
    false
   end
  end
 end  
end

class AbstractRecord < ActiveRecord::Base
 def self.abstract_class?
    true
 end

 def self.inherited(subclass)
  super
  subclass.class_eval do
   def abstract_class?
    false
   end
  end
 end  
end

Любой совет о том, что я делаю неправильно, приветствуется?

Ответы [ 2 ]

2 голосов
/ 14 августа 2010

Попробуйте это:


def self.inherited(subclass)
  super
  def subclass.abstract_class?
    false
  end
end

Или:


def self.inherited(subclass)
  super
  subclass.class_eval do
    def self.abstract_class? 
  # You lost the 'self' part, so you had just defined an instant method for the subclass
      false
    end
  end
 end

1 голос
/ 26 октября 2009
class Account < Foo::Bar::Base
end

module Foo
  module Bar
    class Base < ::ActiveRecord::Base
      def self.abstract_class?
        true
      end
    end
  end
end

Это прекрасно работает для меня. В результате получается имя таблицы «account», как и должно быть.

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