রানটাইমে কোনও পদ্ধতির সংজ্ঞা দেওয়া আছে কীভাবে?


328

আমাদের সম্প্রতি একটি সমস্যা হয়েছিল যেখানে ধারাবাহিক কমিটস হওয়ার পরে, ব্যাকএন্ড প্রক্রিয়াটি চালাতে ব্যর্থ হয়েছিল। এখন, আমরা ভাল ছোট ছেলে-মেয়েরা ছিলাম এবং rake testপ্রতিটি চেক-ইন-এর পিছনে ছুটতাম তবে, রেলের লাইব্রেরি লোডিংয়ের কিছু অদ্ভুততার কারণে এটি কেবল তখন ঘটেছিল যখন আমরা এটি সরাসরি মোডারেল থেকে প্রডাকশন মোডে চালিয়েছিলাম।

আমি বাগটি ট্র্যাক করেছিলাম এবং এটি স্ট্রিং ক্লাসে একটি পদ্ধতিতে ওভাররাইট করা একটি নতুন রেল মণির কারণে যা রানটাইম রেল কোডের একটি সংকীর্ণ ব্যবহারকে ভেঙে দিয়েছে।

যাইহোক, দীর্ঘ গল্পের সংক্ষিপ্তসার, রুবিকে জিজ্ঞাসা করার কোনও উপায় আছে, রানটাইমের সময় যেখানে কোনও পদ্ধতি সংজ্ঞায়িত করা হয়েছে? এরকম কিছু কি whereami( :foo )ফিরে /path/to/some/file.rb line #45? এক্ষেত্রে, আমাকে বলছেন যে এটি স্ট্রিং ক্লাসে সংজ্ঞায়িত করা অসফল হবে, কারণ এটি কিছু লাইব্রেরি দ্বারা ওভারলোড হয়েছিল।

আমি আমার প্রকল্পের উত্সটির গ্যারান্টি 'def foo'দিতে পারি না , তাই গ্রেপিংয়ের জন্য অগত্যা আমার যা প্রয়োজন তা আমাকে দেয় না, আমার অনেকগুলি আছে কিনা তা উল্লেখ না করা def foo, কখনও কখনও আমি রানটাইম পর্যন্ত জানি না যে আমি কোনটি ব্যবহার করছি।


1
রুবি ১.৮..7 এ এই তথ্যটি সন্ধানের জন্য একটি বিশেষ পদ্ধতি যুক্ত করা হয়েছিল (এবং এটি এখনও 1.9.3 তে রয়েছে) ... আমার উত্তরটিতে বিশদ বিবরণ।
অ্যালেক্স

উত্তর:


419

এটি সত্যিই দেরি হয়ে গেছে, তবে একটি পদ্ধতি সংজ্ঞায়িত হয়েছে এমন আপনি কীভাবে খুঁজে পাবেন তা এখানে:

http://gist.github.com/76951

# How to find out where a method comes from.
# Learned this from Dave Thomas while teaching Advanced Ruby Studio
# Makes the case for separating method definitions into
# modules, especially when enhancing built-in classes.
module Perpetrator
  def crime
  end
end

class Fixnum
  include Perpetrator
end

p 2.method(:crime) # The "2" here is an instance of Fixnum.
#<Method: Fixnum(Perpetrator)#crime>

আপনি রুবি ১.৯++ এ থাকলে আপনি ব্যবহার করতে পারেন source_location

require 'csv'

p CSV.new('string').method(:flock)
# => #<Method: CSV#flock>

CSV.new('string').method(:flock).source_location
# => ["/path/to/ruby/1.9.2-p290/lib/ruby/1.9.1/forwardable.rb", 180]

নোট করুন যে এটি দেশীয় সংকলিত কোডের মতো সবকিছুতে কাজ করবে না। পদ্ধতি বর্গ কিছু ঝরঝরে ফাংশন, খুব, মত পদ্ধতি # মালিক যা ফাইল যেখানে পদ্ধতি সংজ্ঞায়িত করা হয় ফেরৎ।

সম্পাদনা করুন: আরো দেখুন __file__এবং __line__অন্যান্য উত্তরে এবং ree জন্য নোট, তারাও কুশলী করছি। - ডাব্লু


1
অ্যাক্টিভসপোর্ট-২.৩.১৪ ব্যবহার করে সোর্স_লোকশনটি 1.8.7-p334 এর জন্য কাজ করছে বলে মনে হচ্ছে
জেফ মাশ

পদ্ধতিটি সন্ধান করার পরে, পদ্ধতির ownerপদ্ধতিটি ব্যবহার করে দেখুন
জুলুয়াং

1
দুই নম্বরে কী 2.method(:crime)?
21

1
শ্রেণীর উদাহরণFixnum
কিটিহহ

1
গুরুত্বপূর্ণ দ্রষ্টব্য: এটি কোনও গতিশীল সংজ্ঞায়িত পদ্ধতি থেকে এড়াতে পারবে না method_missing। সুতরাং আপনার যদি মডিউল বা পূর্বসূর শ্রেণীর অভ্যন্তর class_evalবা এর সাথে থাকে তবে এই পদ্ধতিটি কার্যকর হবে না। define_methodmethod_missing
সিডিপালমার

83

উপরের সমাধানের চেয়ে আপনি কিছুটা এগিয়ে যেতে পারেন। রুবি 1.8 এন্টারপ্রাইজ সংস্করণের জন্য, উদাহরণগুলির জন্য পদ্ধতি __file__এবং __line__পদ্ধতি রয়েছে Method:

require 'rubygems'
require 'activesupport'

m = 2.days.method(:ago)
# => #<Method: Fixnum(ActiveSupport::CoreExtensions::Numeric::Time)#ago>

m.__file__
# => "/Users/james/.rvm/gems/ree-1.8.7-2010.01/gems/activesupport-2.3.8/lib/active_support/core_ext/numeric/time.rb"
m.__line__
# => 64

রুবির ১.৯ এবং এর বাইরেও source_location(ধন্যবাদ জোনাথন!):

require 'active_support/all'
m = 2.days.method(:ago)
# => #<Method: Fixnum(Numeric)#ago>    # comes from the Numeric module

m.source_location   # show file and line
# => ["/var/lib/gems/1.9.1/gems/activesupport-3.0.6/.../numeric/time.rb", 63]

2
উভয়ের জন্য: আমি "অনির্ধারিত পদ্ধতি NoMethodError" পেতে __file__এবং __line__কোনো Methodবর্গ উদাহরণস্বরূপ, উদা: method(:method).__file__
বিক্রত চৌধুরী চৌধুরী

আপনার কাছে রুবির কোন সংস্করণ আছে?
জেমস অ্যাডাম

রুবি 1.8.7 (2010-06-23 প্যাচলেভেল 299) [x86_64-লিনাক্স]
বিক্রান্ত চৌধুরী চৌধুরী

19
রুবি ১.৯-এ, m.__file__এবং m.__line__প্রতিস্থাপন করা হয়েছে m.source_location
জোনাথন ট্রান

রুবি ২.১ সম্পর্কে কী?
লোকেশ

38

আমি এই থ্রেডে দেরিতে আসছি, এবং অবাক হয়েছি যে কেউ উল্লেখ করেনি Method#owner

class A; def hello; puts "hello"; end end
class B < A; end
b = B.new
b.method(:hello).owner
=> A

2
আমি অবাক হয়েছি যে আপনি মেথড ক্লাসটি স্পষ্টভাবে উল্লেখ করেছেন । আরেকটি স্বল্প পরিচিত ধন 1.9 চালু: Method#parameters
fny

13

একটি নতুন অনুরূপ প্রশ্ন থেকে আমার উত্তর অনুলিপি করা যা এই সমস্যায় নতুন তথ্য যুক্ত করে।

রুবি ১.৯ এর সোর্স_ লোকেশন নামক একটি পদ্ধতি রয়েছে :

রুবি উত্স ফাইল নাম এবং এই পদ্ধতিটি সহ লাইন নম্বর প্রদান করে বা শূন্যে (যেমন নেটিভ) এই পদ্ধতিটি সংজ্ঞায়িত না করা থাকলে শূন্য হয় il

এটি এই রত্নটির দ্বারা 1.8.7 এ ব্যাকপোর্ট করা হয়েছে :

সুতরাং আপনি পদ্ধতির জন্য অনুরোধ করতে পারেন:

m = Foo::Bar.method(:create)

এবং তারপরে source_locationসেই পদ্ধতির জন্য জিজ্ঞাসা করুন :

m.source_location

এটি ফাইলের নাম এবং লাইন নম্বর সহ একটি অ্যারে প্রদান করবে। যেমন ActiveRecord::Base#validatesএই রিটার্নের জন্য:

ActiveRecord::Base.method(:validates).source_location
# => ["/Users/laas/.rvm/gems/ruby-1.9.2-p0@arveaurik/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]

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

কর্মে:

where_is(ActiveRecord::Base, :validates)

# => ["/Users/laas/.rvm/gems/ruby-1.9.2-p0@arveaurik/gems/activemodel-3.2.2/lib/active_model/validations/validates.rb", 81]

টেক্সটমেটযুক্ত ম্যাকগুলিতে, এটি নির্দিষ্ট স্থানে সম্পাদককে পপ আপ করে।


7

এটি সাহায্য করতে পারে তবে আপনাকে নিজের কোড করতে হবে। ব্লগ থেকে আটকানো:

রুবি একটি মেথড_ডেড () কলব্যাক সরবরাহ করে যা প্রতি ক্লাসের মধ্যে কোনও পদ্ধতি যুক্ত বা পুনরায় সংজ্ঞায়িত হওয়ার সময় অনুরোধ করা হয়। এটি মডিউল শ্রেণির অংশ এবং প্রতিটি ক্লাস একটি মডিউল। এর সাথে দুটি সম্পর্কিত কলব্যাক রয়েছে যাকে মেথড_ম্রেভড () এবং মেথড_অনডাফাইনড () বলা হয়।

http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby


6

আপনি যদি পদ্ধতিটি ক্র্যাশ করতে পারেন তবে আপনি একটি ব্যাকট্র্যাস পাবেন যা এটি আপনাকে ঠিক কোথায় তা বলে দেবে।

দুর্ভাগ্যক্রমে, আপনি যদি এটি ক্রাশ করতে না পারেন তবে এটি কোথায় সংজ্ঞায়িত করা হয়েছে তা আপনি জানতে পারবেন না। যদি আপনি পদ্ধতিটি ওভাররাইট করে বা ওভাররাইড করে বানরের চেষ্টা করে থাকেন তবে কোনও ক্র্যাশ আপনার ওভাররাইট বা ওভাররাইড হওয়া পদ্ধতি থেকে আসবে এবং এটি কোনও কাজে আসবে না।

ক্র্যাশিং পদ্ধতিগুলির কার্যকর উপায়:

  1. পাশ nilযেখানে এটা নিষিদ্ধ - অনেক সময় পদ্ধতি একটি তুলবে ArgumentErrorবা সদা উপস্থিত NoMethodErrorএকটি শূন্য বর্গ উপর।
  2. যদি আপনার কাছে পদ্ধতিটি সম্পর্কে অভ্যন্তর জ্ঞান থাকে এবং আপনি জানেন যে পদ্ধতিটি পরিবর্তিতভাবে অন্য কোনও পদ্ধতিকে কল করে, তবে আপনি অন্য পদ্ধতিটি মুছে ফেলতে এবং এর ভিতরে বাড়াতে পারেন।

আপনি কোড এক্সেস থাকে, তাহলে আপনি ঠিক যেমন সহজে ঢোকাতে পারবেন require 'ruby-debug'; debugger আপনার কোডে যেখানে আপনি ড্রপ করতে চান।
টিনের মানুষ

"দুর্ভাগ্যক্রমে, আপনি যদি এটি ক্রাশ করতে না পারেন তবে এটি কোথায় সংজ্ঞায়িত করা হয়েছে তা আপনি জানতে পারবেন না" " সত্য না. অন্যান্য উত্তর দেখুন।
মার্টিন টি।

6

সম্ভবত #source_locationপদ্ধতিটি কোথা থেকে এসেছে তা সন্ধান করতে সহায়তা করতে পারে।

উদা:

ModelName.method(:has_one).source_location

প্রত্যাবর্তন

[project_path/vendor/ruby/version_number/gems/activerecord-number/lib/active_record/associations.rb", line_number_of_where_method_is]

অথবা

ModelName.new.method(:valid?).source_location

প্রত্যাবর্তন

[project_path/vendor/ruby/version_number/gems/activerecord-number/lib/active_record/validations.rb", line_number_of_where_method_is]

4

খুব দেরিতে উত্তর :) তবে আগের উত্তরগুলি আমার কোনও কাজে আসেনি

set_trace_func proc{ |event, file, line, id, binding, classname|
  printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
# call your method
set_trace_func nil

আপনি কেন পাস করছেন nil?
অরূপ রক্ষিত

ডকুমেন্টেশন থেকে অরূপক্ষিত: cing ট্রেসিংয়ের জন্য হ্যান্ডলার হিসাবে প্রোক স্থাপন করে, বা পরামিতি থাকলে ট্রেসিং অক্ষম করে nil»
টাইগ করুন

3

আপনি এটির মতো কিছু করতে সক্ষম হতে পারেন:

foo_finder.rb:

 class String
   def String.method_added(name)
     if (name==:foo)
        puts "defining #{name} in:\n\t"
        puts caller.join("\n\t")
     end
   end
 end

তারপরে foo_finder এর আগে এমন কিছু দিয়ে লোড হয়েছে তা নিশ্চিত করুন

ruby -r foo_finder.rb railsapp

(আমি কেবল রেললাইন দিয়ে গণ্ডগোল করেছি, তাই আমি ঠিক জানি না, তবে আমি ধারণা করি যে এটির মতো শুরু করার উপায় আছে))

এটি আপনাকে স্ট্রিং # ফু এর সমস্ত পুনরায় সংজ্ঞা প্রদর্শন করবে। সামান্য মেটা-প্রোগ্রামিংয়ের সাহায্যে আপনি যে কোনও ক্রিয়াকলাপের জন্য এটি সাধারণ করতে পারেন। তবে ফাইলটি পূর্বে লোড করা দরকার যা প্রকৃতপক্ষে পুনরায় সংজ্ঞা দেয়।


3

আপনি যেখানে থাকেন সেখানে সর্বদা ব্যাকট্র্যাস পেতে পারেন caller()


1
আপনাকে কী বলেছে এটি সন্ধানের জন্য এটি দরকারী তবে যখন আপনি কোথায় কিছু সংজ্ঞায়িত করা হয়েছে তা সন্ধান করার সময় ভাল নয়।
টিন ম্যান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.