আমি একটি Ruby মডিউল ছাড়া একটি ইনস্ট্যান্স পদ্ধতি আহ্বান করতে পারেন?



module methods (6)

পটভূমি:

আমার একটি মডিউল রয়েছে যা বেশ কয়েকটি ইনস্ট্যান্স পদ্ধতি ঘোষণা করে

module UsefulThings
  def get_file; ...
  def delete_file; ...

  def format_text(x); ...
end

এবং আমি একটি ক্লাসের মধ্যে থেকে এই পদ্ধতির কিছু কল করতে চান। আপনি রুবি এই সাধারণত কিভাবে এই হল:

class UsefulWorker
  include UsefulThings

  def do_work
    format_text("abc")
    ...
  end
end

সমস্যা

include UsefulThings থেকে সব পদ্ধতি এনেছে include UsefulThings । এই ক্ষেত্রে আমি শুধুমাত্র format_text চাই এবং স্পষ্টত get_file এবং delete_file চাই না।

আমি এই জন্য অনেক সম্ভাব্য সমাধান দেখতে পারেন:

  1. একরকম যেহেতু এটি কোথাও ছাড়া মডিউল সরাসরি পদ্ধতি আহ্বান
    • আমি জানি না কিভাবে এই কাজ করা যায়। (তাই এই প্রশ্ন)
  2. একরকম দরকারী ব্যবহার অন্তর্ভুক্ত এবং শুধুমাত্র এর কিছু পদ্ধতিতে আনা
    • আমি জানি না কিভাবে এই কাজ করা যায়
  3. একটি প্রক্সি শ্রেণি তৈরি করুন, তার মধ্যে UsefulThings অন্তর্ভুক্ত করুন, তারপরে সেই প্রক্সি ইনস্ট্যান্সে format_text
    • এই কাজ করবে, কিন্তু বেনামী প্রক্সি ক্লাস একটি হ্যাক। ইশ।
  4. মডিউল বিভক্ত 2 বা আরও ছোট মডিউল মধ্যে
    • এটিও কাজ করবে এবং সম্ভবত আমার সবচেয়ে ভাল সমাধান যা আমি মনে করতে পারি, কিন্তু আমি এটি এড়াতে চাই যে আমি কয়েক ডজন এবং কয়েক ডজন মডিউলগুলির বিস্তারের সাথে শেষ করব - এটি পরিচালনা করা কষ্টকর হবে

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


Answer #1

আমার মনে হয় কেবল নিক্ষেপ করা একক কল (বিদ্যমান মডিউলগুলি পরিবর্তন বা নতুন তৈরি না করে) নিম্নরূপঃ

Class.new.extend(UsefulThings).get_file

Answer #2

আমি প্রশ্নটি বুঝতে পারছি, আপনি একটি মডিউল এর উদাহরণ পদ্ধতিগুলিকে ক্লাসে মেশাতে চান।

Module#include কাজ Module#include কিভাবে বিবেচনা করে শুরু করা যাক। ধরুন আমাদের কাছে দুটি মডিউল পদ্ধতি রয়েছে এমন একটি মডিউল দরকারী UsefulThings রয়েছে:

module UsefulThings
  def add1
    self + 1
  end
  def add3
    self + 3
  end
end

UsefulThings.instance_methods
  #=> [:add1, :add3]

এবং Fixnum include যে মডিউল:

class Fixnum
  def add2
    puts "cat"
  end
  def add3
    puts "dog"
  end
  include UsefulThings
end

আমরা যে দেখুন:

Fixnum.instance_methods.select { |m| m.to_s.start_with? "add" }
  #=> [:add2, :add3, :add1] 
1.add1
2 
1.add2
cat
1.add3
dog

আপনি কি UsefulThings#add3 প্রত্যাশা করছেন UsefulThings#add3 override, যাতে 1.add3 4 ফিরে আসবে? এই বিবেচনা:

Fixnum.ancestors
  #=> [Fixnum, UsefulThings, Integer, Numeric, Comparable,
  #    Object, Kernel, BasicObject] 

যখন শ্রেণীটি মডিউল include করে, তখন মডিউল ক্লাস 'সুপারক্লাস হয়ে যায়। সুতরাং, কিভাবে উত্তরাধিকার কাজ করে, add3 একটি উদাহরণে add3 পাঠানো Fixnum#add3 কে কল করা, dog ফেরত প্রদান করবে।

এখন এর একটি পদ্ধতি যুক্ত করুন :add2 যোগ করুন:

module UsefulThings
  def add1
    self + 1
  end
  def add2
    self + 2
  end
  def add3
    self + 3
  end
end

আমরা এখন add1 এবং add3 শুধুমাত্র পদ্ধতি include Fixnum ইচ্ছুক। তাই করছেন, আমরা উপরে হিসাবে একই ফলাফল পেতে আশা করি।

ধরুন, উপরে হিসাবে, আমরা চালানো:

class Fixnum
  def add2
    puts "cat"
  end
  def add3
    puts "dog"
  end
  include UsefulThings
end

ফলাফলটি কি? অবাঞ্ছিত পদ্ধতি :add2 যুক্ত করা Fixnum , :add1 যোগ করা হয়েছে এবং, আমি উপরে বর্ণিত কারণগুলির জন্য, :add3 যোগ করা হয়নি। সুতরাং আমাদের যা করতে হবে তা undef :add2 । আমরা একটি সহজ সহায়ক পদ্ধতির সাথে এটি করতে পারি:

module Helpers
  def self.include_some(mod, klass, *args)
    klass.send(:include, mod)
    (mod.instance_methods - args - klass.instance_methods).each do |m|
      klass.send(:undef_method, m)
    end
  end
end

যা আমরা এই মত আহ্বান:

class Fixnum
  def add2
    puts "cat"
  end
  def add3
    puts "dog"
  end
  Helpers.include_some(UsefulThings, self, :add1, :add3)
end

তারপর:

Fixnum.instance_methods.select { |m| m.to_s.start_with? "add" }
  #=> [:add2, :add3, :add1] 
1.add1
2 
1.add2
cat
1.add3
dog

যা আমরা চাই ফলাফল।


Answer #3

প্রথমত, আমি আপনার প্রয়োজনীয় দরকারী জিনিসগুলিতে মডিউলটি ভাঙ্গার সুপারিশ করব। কিন্তু আপনি সর্বদা আপনার অনুরোধের জন্য বর্ধিত একটি শ্রেণী তৈরি করতে পারেন:

module UsefulThings
  def a
    puts "aaay"
  end
  def b
    puts "beee"
  end
end

def test
  ob = Class.new.send(:include, UsefulThings).new
  ob.a
end

test

Answer #4

প্রায় 9 বছর পর এখানে একটি সাধারণ সমাধান:

module CreateModuleFunctions
  def self.included(base)
    base.instance_methods.each do |method|
      base.module_eval do
        module_function(method)
        public(method)
      end
    end
  end
end

RSpec.describe CreateModuleFunctions do
  context "when included into a Module" do
    it "makes the Module's methods invokable via the Module" do
      module ModuleIncluded
        def instance_method_1;end
        def instance_method_2;end

        include CreateModuleFunctions
      end

      expect { ModuleIncluded.instance_method_1 }.to_not raise_error
    end
  end
end

প্রয়োগ করা প্রয়োজন দুর্ভাগ্যজনক কৌশল পদ্ধতিগুলি সংজ্ঞায়িত করার পরে মডিউল অন্তর্ভুক্ত করা হয়। প্রসঙ্গে আপনি ModuleIncluded.send(:include, CreateModuleFunctions) হিসাবে সংজ্ঞায়িত হওয়ার পরে এটি অন্তর্ভুক্ত করতে পারেন ModuleIncluded.send(:include, CreateModuleFunctions)

অথবা আপনি reflection_utils মণির মাধ্যমে এটি ব্যবহার করতে পারেন।

spec.add_dependency "reflection_utils", ">= 0.3.0"

require 'reflection_utils'
include ReflectionUtils::CreateModuleFunctions

Answer #5

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

module UsefulThings
  def self.get_file; ...
  def self.delete_file; ...

  def self.format_text(x); ...
end

এবং তারপর আপনি তাদের সাথে কল করতে পারেন

UsefulThings.format_text("xxx")

অথবা

UsefulThings::format_text("xxx")

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


Answer #6

যদি আপনি মডিউলটির "মালিক" হন তবে এটি করার আরেকটি উপায় হল module_function ব্যবহার module_function

module UsefulThings
  def a
    puts "aaay"
  end
  module_function :a

  def b
    puts "beee"
  end
end

def test
  UsefulThings.a
  UsefulThings.b # Fails!  Not a module method
end

test




methods