অ্যাক্টিভেকর্ড :: বেস প্রসারিত কারাগার


160

অ্যাক্টিভেকর্ডকে কীভাবে বাড়ানো যায় সে সম্পর্কে আমি কিছু পাঠ করেছি: বেস ক্লাস যাতে আমার মডেলগুলিতে কিছু বিশেষ পদ্ধতি থাকে। এটি প্রসারিত করার সহজ উপায় কী (ধাপে ধাপে টিউটোরিয়াল)?


কি ধরনের এক্সটেনশন? আমাদের এগিয়ে যেতে আরও বেশি প্রয়োজন।
jonnii

উত্তর:


336

বিভিন্ন পন্থা রয়েছে:

অ্যাক্টিভসপোর্ট :: কনসার্ন (পছন্দসই) ব্যবহার করা হচ্ছে

অ্যাক্টিভসপোর্ট :: আরও তথ্যের জন্য উদ্বেগ ডকুমেন্টেশন পড়ুন ।

নামক কোনো ফাইল তৈরি করুন active_record_extension.rbমধ্যে libডিরেক্টরি।

require 'active_support/concern'

module ActiveRecordExtension

  extend ActiveSupport::Concern

  # add your instance methods here
  def foo
     "foo"
  end

  # add your static(class) methods here
  class_methods do
    #E.g: Order.top_ten        
    def top_ten
      limit(10)
    end
  end
end

# include the extension 
ActiveRecord::Base.send(:include, ActiveRecordExtension)

config/initializersবলা ডিরেক্টরিতে একটি ফাইল তৈরি করুন এবং ফাইলটিতে extensions.rbনিম্নলিখিত লাইনটি যুক্ত করুন:

require "active_record_extension"

উত্তরাধিকার (পছন্দসই)

টবির উত্তর দেখুন

বানরের প্যাচিং (এড়ানো উচিত)

config/initializersবলা ডিরেক্টরিতে একটি ফাইল তৈরি করুন active_record_monkey_patch.rb

class ActiveRecord::Base     
  #instance method, E.g: Order.new.foo       
  def foo
   "foo"
  end

  #class method, E.g: Order.top_ten        
  def self.top_ten
    limit(10)
  end
end

জেমি জাওনস্কির নিয়মিত প্রকাশ সম্পর্কে বিখ্যাত উক্তিটি বানর-প্যাচিংয়ের সাথে জড়িত সমস্যাগুলি চিত্রিত করার জন্য পুনরায় ধারণা করা যেতে পারে।

কিছু লোক, যখন সমস্যার মুখোমুখি হয়, তখন "আমি জানি, আমি বানরের প্যাচিং ব্যবহার করব" think এখন তারা দুটি সমস্যা আছে।

বানরের প্যাচিং সহজ এবং দ্রুত। তবে, সংরক্ষণ করা সময় এবং প্রচেষ্টা সর্বদা ভবিষ্যতের কিছু সময় ফিরে পাওয়া যায়; যৌগিক সুদের সাথে। এই দিনগুলিতে আমি রেল কনসোলের কোনও সমাধান দ্রুত প্রোটোটাইপ করতে বাঁদর প্যাচিং সীমাবদ্ধ করি।


3
যা শুরু করেছো requireশেষে ফাইল environment.rb। আমি আমার উত্তরে এই অতিরিক্ত পদক্ষেপটি যুক্ত করেছি।
হরিশ শেঠি

1
@ হার্টলিব্রডি এটি কেবল পছন্দের বিষয়। যদি আপনি উত্তরাধিকার ব্যবহার করেন তবে আপনাকে একটি নতুন প্রবর্তন করতে ImprovedActiveRecordহবে এবং সেখান থেকে উত্তরাধিকারী হতে হবে, আপনি যখন ব্যবহার করছেন module, আপনি প্রশ্নে শ্রেণীর সংজ্ঞাটি আপডেট করছেন। আমি উত্তরাধিকার ব্যবহার করতাম (জাভা / সি ++ বছরের অভিজ্ঞতার কারণ)। আজকাল আমি বেশিরভাগ মডিউল ব্যবহার করি।
হরিশ শেঠি

1
এটি একটি সামান্য বিদ্রূপজনক যে আপনার লিঙ্কটি আসলে প্রাসঙ্গিক করে তুলছে এবং লোকেরা কীভাবে উদ্ধৃতিটিকে অপব্যবহার করে এবং নির্দেশ করে। তবে সমস্ত গম্ভীরতায় আমি বুঝতে পারছি না কেন "বানর প্যাচিং" এই ক্ষেত্রে সবচেয়ে ভাল উপায় নয়। আপনি যদি একাধিক ক্লাসে যোগ করতে চান তবে একটি মডিউল স্পষ্টতই যাওয়ার উপায়। তবে যদি আপনার লক্ষ্যটি একটি শ্রেণি প্রসারিত করা হয় তবে তাই নয় যে রুবি এইভাবে বর্ধিত ক্লাসগুলি এত সহজ করলেন কেন?
এমসিবি

1
@ এমসিবি, প্রতিটি বড় প্রকল্পে বানর প্যাচিংয়ের কারণে প্রবর্তিত বাগ সনাক্তকরণের জন্য কয়েকটি গল্প রয়েছে। প্যাচিংয়ের কুফল সম্পর্কে Avdi এর একটি নিবন্ধ এখানে: devblog.avdi.org/2008/02/23/… । রুবি ২.০ একটি নতুন বৈশিষ্ট্য উপস্থাপন করেছে Refinementsযা বানরের প্যাচিংয়ের সাথে বেশিরভাগ ইস্যুগুলিকে সম্বোধন করে ( ইয়াহুদাকাটজ . com / 2010/11/30 / ruby-2-0-refinements-in- অনুশীলন )। কখনও কখনও একটি বৈশিষ্ট্য কেবল ভাগ্যকে প্ররোচিত করতে বাধ্য করতে আসে। এবং কখনও কখনও আপনি কি।
হরিশ শেঠি

1
পছন্দ করুন সর্বশেষ ডকুমেন্টেশন প্রতিবিম্বিত করার উত্তরটি আমি আপডেট করেছি (দেখে মনে হচ্ছে ক্লাস_মাদাগুলি 2014 সালে github.com/rails/rails/commit/… প্রবর্তিত হয়েছিল )
হরিশ শেঠি

70

আপনি কেবল শ্রেণি প্রসারিত করতে পারেন এবং কেবল উত্তরাধিকার ব্যবহার করতে পারেন।

class AbstractModel < ActiveRecord::Base  
  self.abstract_class = true
end

class Foo < AbstractModel
end

class Bar < AbstractModel
end

আমি এই ধারণাটি পছন্দ করি কারণ এটি করার একটি স্ট্যান্ডার্ড উপায় তবে ... আমি একটি ত্রুটি পেয়েছি টেবিল 'মোবুলো_ডিভলপমেন্ট.অ্যাবস্ট্রাক_মোডেলস' বিদ্যমান নেই: ফিল্ড থেকে ফিল শো করুন abstract_models। কোথায় রাখব?
xpepermint

23
self.abstract_class = trueআপনার যোগ করুন AbstractModel। রেলগুলি এখন মডেলটিকে একটি বিমূর্ত মডেল হিসাবে স্বীকৃতি দেবে।
হরিশ শেঠি

কি দারুন! ভেবে দেখেনি যে এটি সম্ভব হয়েছিল। এটি আগে চেষ্টা করেছিল এবং যখন অ্যাক্টিভেকর্ডটি ডেটাবেজে অনুসন্ধানের জন্য চেপে যায় AbstractModel। কে জানত যে একটি সাধারণ সেটার আমাকে জিনিসগুলি শুকিয়ে উঠতে সহায়তা করবে! (আমি ক্রিংজ করা শুরু করছিলাম ... এটি খারাপ ছিল)। ধন্যবাদ টবি এবং হরিশ!
dooleyo

আমার ক্ষেত্রে এটি অবশ্যই করার সর্বোত্তম উপায়: আমি এখানে বিদেশী পদ্ধতিগুলির সাথে আমার মডেলের দক্ষতাগুলি প্রসারিত করছি না, তবে আমার অ্যাপ্লিকেশনটির অনুরূপ আচরণকারী বস্তুর জন্য কমন পদ্ধতিগুলি রিফ্যাক্টর করছি। উত্তরাধিকার এখানে আরও বেশি অর্থবোধ করে । আপনি কী অর্জন করতে চান তার উপর নির্ভর করে কোনও পছন্দিক উপায় ছাড়া 2 টি সমাধান রয়েছে!
অগস্টিন রিডিংগার

এটি আমার জন্য রেলস 4 এ কাজ করে না। আমি বিমূর্ত_মডেল.আরবি তৈরি করেছি এবং আমার মডেল ডিরেক্টরিতে রেখেছি। মডেলের ভিতরে এটি স্ব.অ্যাবস্ট্রাক_ক্লাস = সত্য ছিল তারপরে আমি আমার অন্যান্য মডেলগুলির উত্তরাধিকারী হয়েছি ... ব্যবহারকারীর <অ্যাবস্ট্রাকমোডেল । কনসোলে আমি পেয়েছি: ব্যবহারকারী (সংযোগ স্থাপনের জন্য 'ব্যবহারকারীর সংযোগ' কল করুন)
জোয়েল গ্রানাস

21

আপনি ActiveSupport::Concernআরও রেল কোর ইডিয়োমেটিক যেমন ব্যবহার করতে পারেন এবং হতে পারেন:

module MyExtension
  extend ActiveSupport::Concern

  def foo
  end

  module ClassMethods
    def bar
    end
  end
end

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

@ ড্যানিয়েলের মন্তব্য অনুসরণ করে [সম্পাদনা করুন]

তারপরে আপনার সমস্ত মডেলগুলিতে fooএকটি উদাহরণ পদ্ধতি এবং ClassMethodsক্লাস পদ্ধতি হিসাবে অন্তর্ভুক্ত থাকা পদ্ধতিগুলি অন্তর্ভুক্ত থাকবে। যেমন একটি FooBar < ActiveRecord::Baseআপনার হবে: FooBar.barএবংFooBar#foo

http://api.rubyonrails.org/classes/ActiveSupport/Concern.html


5
দ্রষ্টব্য যে InstanceMethodsরেলগুলি ৩.২ থেকে অবহেলিত হয়েছে, কেবলমাত্র আপনার পদ্ধতিগুলি মডিউল বডিটিতে রেখে দিন।
ড্যানিয়েল রিকোভস্কি

আমি ActiveRecord::Base.send(:include, MyExtension)একটি ইনিশিয়ালাইজারে রেখেছি এবং তারপরে এটি আমার জন্য কাজ করেছে। Ails.১.৯
ফুট ড্যান

18

রেলস 4 এর সাথে আপনার মডেলগুলিকে মডুলারাইজ করতে এবং ডিআরওয়াই করতে উদ্বেগগুলি ব্যবহার করার ধারণাটি হাইলাইট হয়েছে।

উদ্বেগগুলি মূলত আপনাকে একটি মডেলের অনুরূপ কোড বা একক মডিউলে একাধিক মডেল জুড়ে গোষ্ঠী তৈরি করতে দেয় এবং তারপরে মডেলগুলিতে এই মডিউলটি ব্যবহার করে। এখানে একটি উদাহরণ:

একটি নিবন্ধ মডেল, একটি ইভেন্ট মডেল এবং একটি মন্তব্য মডেল বিবেচনা করুন। একটি নিবন্ধ বা একটি ইভেন্ট অনেক মন্তব্য আছে। একটি মন্তব্য নিবন্ধ বা ইভেন্ট হয়।

Ditionতিহ্যগতভাবে, মডেলগুলি এর মতো দেখতে পারে:

মন্তব্য মডেল:

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

নিবন্ধ মডেল:

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

ইভেন্ট মডেল

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

আমরা লক্ষ্য করতে পারি যে, ইভেন্ট এবং আর্টিকেল মডেল উভয়ের পক্ষে একটি উল্লেখযোগ্য কোডের সাধারণ অংশ রয়েছে। উদ্বেগগুলি ব্যবহার করে আমরা এই সাধারণ কোডটি একটি পৃথক মডিউলে মন্তব্যযোগ্য হিসাবে বের করতে পারি।

এর জন্য অ্যাপ / মডেল / উদ্বেগগুলিতে একটি মন্তব্যযোগ্য.আরবি ফাইল তৈরি করুন।

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

এবং এখন আপনার মডেলগুলি দেখতে এইরকম:

মন্তব্য মডেল:

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

নিবন্ধ মডেল:

class Article < ActiveRecord::Base
    include Commentable
end

ইভেন্ট মডেল

class Event < ActiveRecord::Base    
    include Commentable
end

কনসার্নস ব্যবহার করার সময় আমি একটি বিষয় হাইলাইট করতে চাই যে কনসার্নগুলি 'প্রযুক্তিগত' গ্রুপিংয়ের পরিবর্তে 'ডোমেন ভিত্তিক' গ্রুপিংয়ের জন্য ব্যবহার করা উচিত। উদাহরণস্বরূপ, একটি ডোমেন গ্রুপিং 'কমেন্টেবল', 'টেগেবল' ইত্যাদির মতো based

এখানে একটি পোস্টের লিঙ্কটি আমি মডেলগুলিতে উদ্বেগ বোঝার জন্য খুব দরকারী বলে মনে করি।

আশা করি লেখাটি সাহায্য করবে :)


7

ধাপ 1

module FooExtension
  def foo
    puts "bar :)"
  end
end
ActiveRecord::Base.send :include, FooExtension

ধাপ ২

# Require the above file in an initializer (in config/initializers)
require 'lib/foo_extension.rb'

ধাপ 3

There is no step 3 :)

1
আমার ধারণা ধাপ 2 অবশ্যই কনফিগারেশন / পরিবেশ.আরবিতে স্থাপন করা উচিত। এটি আমার পক্ষে কাজ করছে না :(। আপনি কি আরও কিছু সাহায্য লিখতে পারেন?
থেক্স

5

5 রেলগুলি প্রসারিত করার জন্য একটি অন্তর্নির্মিত প্রক্রিয়া সরবরাহ করে ActiveRecord::Base

এটি অতিরিক্ত স্তর সরবরাহ করে অর্জিত হয়:

# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
  # put your extensions here
end

এবং সমস্ত মডেল সেই একের উত্তরাধিকার সূত্রে:

class Post < ApplicationRecord
end

যেমন এই ব্লগপোস্ট দেখুন


4

এই বিষয়টিতে কেবল যুক্ত করতে, কীভাবে এই জাতীয় এক্সটেনশানগুলি পরীক্ষা করতে হবে তা নিয়ে কাজ করার জন্য আমি কিছুটা সময় কাটিয়েছি (আমি এই ActiveSupport::Concernপথে নামলাম))

আমি কীভাবে আমার এক্সটেনশানগুলি পরীক্ষার জন্য একটি মডেল সেট আপ করব তা এখানে।

describe ModelExtensions do
  describe :some_method do
    it 'should return the value of foo' do
      ActiveRecord::Migration.create_table :test_models do |t|
        t.string :foo
      end

      test_model_class = Class.new(ActiveRecord::Base) do
        def self.name
          'TestModel'
        end

        attr_accessible :foo
      end

      model = test_model_class.new(:foo => 'bar')

      model.some_method.should == 'bar'
    end
  end
end

4

রেল 5 এর সাথে সমস্ত মডেল অ্যাপ্লিকেশন রেকর্ড থেকে উত্তরাধিকার সূত্রে প্রাপ্ত এবং এটি অন্যান্য এক্সটেনশন লাইব্রেরিগুলিকে অন্তর্ভুক্ত বা প্রসারিত করার দুর্দান্ত উপায় দেয়।

# app/models/concerns/special_methods.rb
module SpecialMethods
  extend ActiveSupport::Concern

  scope :this_month, -> { 
    where("date_trunc('month',created_at) = date_trunc('month',now())")
  }

  def foo
    # Code
  end
end

ধরুন, বিশেষ পদ্ধতিগুলির মডিউলটি সমস্ত মডেল জুড়ে উপলব্ধ হওয়া দরকার, এটিকে প্রয়োগ_record.rb ফাইলে অন্তর্ভুক্ত করুন। আমরা যদি এটি নির্দিষ্ট মডেলগুলির জন্য প্রয়োগ করতে চাই, তবে এটি সংশ্লিষ্ট মডেল শ্রেণিতে অন্তর্ভুক্ত করুন।

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

# app/models/user.rb
class User < ApplicationRecord
  include SpecialMethods

  # Code
end

আপনি যদি মডিউলটিতে ক্লাসের পদ্ধতি হিসাবে সংজ্ঞায়িত পদ্ধতিগুলি দেখতে চান তবে মডিউলটি অ্যাপ্লিকেশন রেকর্ডে প্রসারিত করুন।

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

আশা করি এটি অন্যকে সহায়তা করবে!


0

আমার আছে

ActiveRecord::Base.extend Foo::Bar

একটি ইনিশিয়ালাইজারে

নীচের মত একটি মডিউল জন্য

module Foo
  module Bar
  end
end
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.