Rails named_scope inheritance?

后端 未结 1 1524
臣服心动
臣服心动 2021-01-26 21:56

I\'m trying to generalize some of my models by providing a common base model to inherit from that contains some mutual named_scope declarations and a filter method that activate

相关标签:
1条回答
  • 2021-01-26 22:15

    That's a bit of a train-wreck because of the way ActiveRecord is trying to interpret what you're saying. Generally the first class derived from ActiveRecord::Base is used to define what the base table name is, and sub-classes of that are defined to use Single Table Inheritance (STI) by default. You're working around this by using set_table_name but, as is often the case, while it's possible to go against the grain in Rails, things often get messy.

    You should be able to do this a lot more cleanly using a mixin as suggested by Beerlington.

    module ByNameExtension
      def self.extended(base)
        # This method is called when a class extends with this module
    
        base.send(:scope, :by_name, lambda { |name|
          name.blank? ? nil : where("#{self.table_name}.name LIKE ?", "%#{name}%")
        })
      end
    
      def filter(params)
        params[:name].present? ? self.by_name(params[:name]) : [ ]
      end
    end
    
    class MyModel < ActiveRecord::Base
      # Load in class-level methods from module ByNameExtension
      extend ByNameExtension
    end
    

    You should be able to keep your extensions contained to that module. If you want to clean this up even further, write an initializer that defines a method like scoped_by_name for ActiveRecord::Base that triggers this behavior:

    class ActiveRecord::Base
      def scoped_by_name
        extend ByNameExtension
      end
    end
    

    Then you can tag all classes that require this:

    class MyModel < ActiveRecord::Base
      scoped_by_name
    end
    
    0 讨论(0)
提交回复
热议问题