Rails: how to use self.inherited effectively

I have an AbstractRecord model from which some of the specific models come out (which have their own tables). The next is inheritance.

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

So that Rails can look for the right tables, if there is inheritance, do API documents say to define an abstract_class class method? which returns true so that the rails will not look for their table. In my case, so that the rails look for the blog table (instead of the abstract_records table, which usually takes place, as in the STI), did I define the abstract_class method? in AbstractRecord, which returns true. All requests seem to be working fine. But I see that whenever I create a blog, the rails show it as a blog (abstract) in the console, since its parent class returns true. To avoid this, could I define abstract_class again? which returns false in the Blog class.

But I was thinking instead of defining abstract_class? in all child models, if I could somehow use self.inherited and define this method in AbstractClass itself. I tried to use several approaches (further), none of them work.

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

Any advice on what I'm doing wrong is appreciated?

+3
source share
2 answers

Try the following:


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

Or:


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

+2
source
class Account < Foo::Bar::Base
end

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

This works great for me. This leads to the fact that the "accounts" of the table names, as it should be.

+1
source

Source: https://habr.com/ru/post/1712892/


All Articles