Rails extending ActiveRecord::Base

后端 未结 9 1646
眼角桃花
眼角桃花 2020-11-22 12:38

I\'ve done some reading about how to extend ActiveRecord:Base class so my models would have some special methods. What is the easy way to extend it (step by step tutorial)?<

9条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-22 13:06

    With Rails 4, the concept of using concerns to modularize and DRY up your models has been in highlights.

    Concerns basically allow you to group similar code of a model or across multiple models in a single module and then use this module in the models. Here is a example:

    Consider a Article model, a Event model and a Comment Model. A article or A event has many comments. A comment belongs to either article or event.

    Traditionally, the models may look like this:

    Comment Model:

    class Comment < ActiveRecord::Base
      belongs_to :commentable, polymorphic: true
    end
    

    Article Model:

    class Article < ActiveRecord::Base
      has_many :comments, as: :commentable 
    
      def find_first_comment
        comments.first(created_at DESC)
      end
    
      def self.least_commented
       #return the article with least number of comments
      end
    end
    

    Event Model

    class Event < ActiveRecord::Base
      has_many :comments, as: :commentable 
    
      def find_first_comment
        comments.first(created_at DESC)
      end
    
      def self.least_commented
       #returns the event with least number of comments
      end
    end
    

    As we can notice, there is a significant piece of code common to both Event and Article Model. Using concerns we can extract this common code in a separate module Commentable.

    For this create a commentable.rb file in app/model/concerns.

    module Commentable
        extend ActiveSupport::Concern
    
        included do 
            has_many :comments, as: :commentable 
        end
    
        # for the given article/event returns the first comment
        def find_first_comment
            comments.first(created_at DESC)
        end
    
        module ClassMethods     
            def least_commented
               #returns the article/event which has the least number of comments
            end
        end 
    end
    

    And Now your models look like this :

    Comment Model:

        class Comment < ActiveRecord::Base
          belongs_to :commentable, polymorphic: true
        end
    

    Article Model:

    class Article < ActiveRecord::Base
        include Commentable
    end
    

    Event Model

    class Event < ActiveRecord::Base    
        include Commentable
    end
    

    One point I will like to highlight while using Concerns is that Concerns should be used for 'domain based' grouping rather than 'technical' grouping. For example, a domain grouping is like 'Commentable', 'Taggable' etc. A technical based grouping will be like 'FinderMethods', 'ValidationMethods'.

    Here is a link to a post that I found very useful for understanding concerns in Models.

    Hope the writeup helps :)

提交回复
热议问题