ruby on rails सक्रिय रिकॉर्ड आधार में कुछ विधि जोड़ने का पसंदीदा तरीका क्या है?




ruby-on-rails include (3)

मैं एक मॉड्यूल बनाना चाहता हूँ जो सक्रिय वर्गों से सक्रिय होने वाले वर्गों को कुछ सामान्य विधियां प्रदान करता है।

निम्नलिखित हम इसे प्राप्त कर सकते हैं दो तरह से है।

1)

module Commentable

def self.extended(base)
    base.class_eval do
        include InstanceMethods
        extend ClassMethods
    end
end

module ClassMethods
    def test_commentable_classmethod
        puts 'test class method'
    end
end

module InstanceMethods
    def test_commentable_instance_method
        puts 'test instance method'
    end
end
end


ActiveRecord::Base.extend(Commentable)

2)

module Commentable

def self.included(base)
    base.extend(ClassMethods)
end

module ClassMethods
    def test_commentable_classmethod
        puts 'test class method'
    end
end

def test_commentable_instance_method
    puts 'test instance methods'
end
end

ActiveRecord::Base.send(:include, Commentable)

यह संभाल करने का पसंदीदा तरीका कौन सा है?

तथा

इसका उपयोग कब करना है?


एक अन्य तरीका ActiveRecord::Base से ActiveRecord::Base से अपना खुद का बेस क्लास बना सकता है और उसके बाद अपने मॉडल को उस बेस क्लास से उत्तीर्ण किया जाता है। इसने यह स्पष्ट करने का फायदा उठाया है कि आपके मॉडल वेनिला एक्टिवक्रैक पर नहीं चल रहे हैं:

class MyBase < ActiveRecord::Base
  self.abstract_class = true

  def self.a_class_method
  end

  def an_instance_method
  end
end

class Foo < MyBase
end

Foo.a_class_method
Foo.new.an_instance_method

मोरी के जवाब के साथ फिर से चर्चा करते हुए ... आप ऐसा कुछ कर सकते हैं: -

Module ActiveRecordUtilities

class MyBase < ActiveRecord::Base
  self.abstract_class = true

  def self.a_class_method
  end

  def an_instance_method
  end
end


end##class ends
end##module ends

और इसका इस्तेमाल कर सकते हैं ... मान लें user.rb में

include ActiveRecordUtilities::MyBase 



User.a_class_method
@user.instance_method

============================ या ====================

module MyUtils
  def do_something_funky
    # Some exciting code
  end
end

class Account < ActiveRecord::Base
  belongs_to :person, :extend => MyUtils
end
And then call it like this:

@account = Account.first
@account.person.do_something_funky

5 रेलवे के रूप में, अनुशंसित तरीका मॉड्यूल बनाने और उन मॉडलों में शामिल करना है जहां इसकी आवश्यकता है, या हर जगह ApplicationRecord का उपयोग करके, जो सभी मॉडलों से प्राप्त होते हैं। (आप आसानी से इस पैटर्न को रेल के पुराने संस्करणों में खरोंच से लागू कर सकते हैं।)

# app/models/concerns/my_module.rb
module MyModule
  extend ActiveSupport::Concern

  module ClassMethods
    def has_some_new_fancy_feature(options = {})
      ...
    end
  end
end

# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
  include MyModule
end

मॉड्यूल बहु-विरासत का एक रूप है, और कभी-कभी अनावश्यक जटिलता जोड़ते हैं जाँच करें कि क्या डेकोरेटर, सेवा या अन्य प्रकार की ऑब्जेक्ट पहले सबसे अधिक समझदारी बनाते हैं। सब कुछ एक फैंसी मैक्रो की ज़रूरत नहीं है जो आपके मॉडल में 50 कॉलबैक जोड़ता है। यदि आप ऐसा करते हैं तो आप अपने जीवन से घृणा करेंगे

यदि आप बंदर-पैच चाहते हैं (यह मत करो), यह मेरा पुराना उत्तर है:

# config/initializers/activerecord_extensions.rb
ActiveRecord::Base.send(:include, MyModule)

या बंदर-पैचिंग के बिना ( मोरी की प्रतिक्रिया देखें):

# app/models/base_model.rb
class BaseModel < ActiveRecord::Base
  self.abstract_class = true
  include MyModule
end

संपादित करें: एक बड़ी परियोजना में सड़क के कई महीनों बाद, मुझे लगता है कि हर मॉडल को नए बेस मॉडल वर्ग से प्राप्त होना बेहतर होगा, क्योंकि मोरी बताते हैं । ActiveRecord :: बेस में मॉड्यूल को सीधे शामिल करने में समस्या यह है कि यह तृतीय-पक्ष कोड में हस्तक्षेप कर सकता है जो कि ActiveRecord पर निर्भर करता है। यह केवल बंदर-पैच के लिए बेहतर नहीं है, जब आपके पास नहीं है। इस मामले में, एक नया बेस क्लास बनाने से लंबे समय तक सरल हो सकता है।





extend