ruby بالعربية ما هو الفرق بين required_relative وتتطلب في روبي؟




معنى pearl (6)

ما هو الفرق بين require_relative require في روبي؟


Answer #1

من واجهة برمجة تطبيقات Ruby :

require_relative تكمل تتطلب طريقة builtin من خلال السماح لك بتحميل ملف متعلق بالملف الذي يحتوي على العبارة require_relative.

عندما تتطلب استخدام لتحميل ملف ، فأنت عادةً تصل إلى وظيفة تم تثبيتها بشكل صحيح ، وجعلها في المتناول ، في نظامك. تتطلب لا تقدم حلا جيدا لتحميل الملفات داخل رمز المشروع. قد يكون ذلك مفيدًا خلال مرحلة التطوير ، أو للوصول إلى بيانات الاختبار ، أو حتى الوصول إلى الملفات التي "تم قفلها" داخل مشروع ، وليس للاستخدام الخارجي.

على سبيل المثال ، إذا كانت لديك فصول اختبار وحدة في دليل "الاختبار" وبيانات خاصة بها ضمن دليل "اختبار / بيانات" الاختبار ، فقد تستخدم سطرًا مثل هذا في حالة الاختبار:

require_relative "data/customer_data_1" 

بما أن "الاختبار" أو "الاختبار / البيانات" لا يحتمل أن يكونا في مسار مكتبة روبي (ولأسباب وجيهة) ، فإن الأمر المعتاد لن يعثر عليها. require_relative هو حل جيد لهذه المشكلة بالذات.

يمكنك تضمين أو حذف الامتداد (.rb أو .so) للملف الذي تقوم بتحميله.

يجب أن يستجيب المسار إلى to_str.

يمكنك العثور على الوثائق على http://extensions.rubyforge.org/rdoc/classes/Kernel.html


Answer #2

require_relative هي مجموعة فرعية مناسبة require

require_relative('path')

يساوي:

require(File.expand_path('path', File.dirname(__FILE__)))

إذا تم تحديد __FILE__ ، أو أنه يرفع LoadError خلاف ذلك.

وهذا يعني أن:

  • require_relative 'a' و require_relative './a' تتطلب نسبيًا للملف الحالي ( __FILE__ ).

    هذا هو ما تريد استخدامه عند الطلب داخل مكتبتك ، حيث أنك لا تريد أن تعتمد النتيجة على الدليل الحالي للمتصل.

  • eval('require_relative("a.rb")') يثير LoadError لأنه لم يتم تعريف __FILE__ داخل eval .

    هذا هو السبب في أنه لا يمكنك استخدام require_relative في اختبارات RSpec ، والتي تحصل على eval ed.

العمليات التالية ممكنة فقط مع require :

  • require './a.rb' يتطلب نسبة إلى الدليل الحالي

  • require 'a.rb' استخدام مسار البحث ( $LOAD_PATH ) $LOAD_PATH . لا يجد الملفات المتعلقة بالدليل الحالي أو المسار.

    هذا غير ممكن مع require_relative لأن المستندات تقول أن البحث عن المسار لا يحدث إلا عندما "لا File.expand_path اسم الملف إلى مسار مطلق" (أي يبدأ بـ / أو ./ أو ../ ) ، وهو دائمًا ما يكون لـ File.expand_path .

العملية التالية ممكنة مع كلاهما ، لكنك سوف تحتاج إلى استخدام require ذلك لأنه أقصر وأكثر كفاءة:

  • require '/a.rb' و require_relative '/a.rb' كلاهما يتطلب المسار المطلق.

قراءة المصدر

عندما لا تكون المستندات واضحة ، فإنني أوصي بأن تلقي نظرة على المصادر (تبديل المصدر في المستندات). في بعض الحالات ، يساعد على فهم ما يجري.

تطلب:

VALUE rb_f_require(VALUE obj, VALUE fname) {
  return rb_require_safe(fname, rb_safe_level());
}

require_relative:

VALUE rb_f_require_relative(VALUE obj, VALUE fname) {
    VALUE base = rb_current_realfilepath();
    if (NIL_P(base)) {
        rb_loaderror("cannot infer basepath");
    }
    base = rb_file_dirname(base);
    return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
}

هذا يسمح لنا باستنتاج ذلك

require_relative('path')

بالضبط مثل:

require(File.expand_path('path', File.dirname(__FILE__)))

لان:

rb_file_absolute_path   =~ File.expand_path
rb_file_dirname1        =~ File.dirname
rb_current_realfilepath =~ __FILE__

Answer #3

الإجابات الأعلى صحيحة ، ولكنها تقنية عميقة. لأولئك الجدد على روبي -

  • سيتم استخدام require_relative الأرجح لجلب التعليمات البرمجية من ملف آخر كتبته.

على سبيل المثال ، ماذا لو كان لديك بيانات في ~/my-project/data.rb وتريد تضمين ذلك في ~/my-project/solution.rb ؟ في solution.rb يمكنك إضافة require_relative 'data' .

من المهم ملاحظة أن هذه الملفات لا تحتاج إلى أن تكون في نفس الدليل. require_relative '../../folder1/folder2/data' صالح أيضًا.

  • سوف تستخدم على الأرجح لجلب رمز من مكتبة كتب شخص آخر.

على سبيل المثال ، ماذا لو كنت تريد استخدام إحدى وظائف المساعد المتوفرة في مكتبة active_support ؟ ستحتاج إلى تثبيت الأحجار الكريمة مع gem install activesupport ثم في الملف require 'active_support' .

require 'active_support/all'
"FooBar".underscore

قال بشكل مختلف

  • requires_relative يتطلب ملفًا محددًا بشكل خاص بالنسبة إلى الملف الذي يطلق عليه.

  • require يتطلب ملف تضمين في $ LOAD_PATH.


Answer #4

require استخدام الدليل الحالي الذي تقوم بتشغيل البرنامج منه

require_relative يستخدم دليل مكان وجود هذا البرنامج نفسه

على سبيل المثال ، إذا كان البرنامج في ~/code ويسمى 1.rb وقمت بعمل قرص مضغوط إلى هذا الدليل

cd ~/code

وتحاول وتشغيل برنامج روبي مع

ruby 1.rb

ثم ضمن 1.rb

require './2.rb'
require_relative '3.rb'

كلاهما سوف يعمل.

ومع ذلك إذا كنت في دليل آخر ، قل

cd ~/tmp

وتحاول وتشغيل البرنامج مع

ruby ../1.rb

ثم سوف تحصل على خطأ مثل

/home/durrantm/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- ./2.rb (LoadError)
    from /home/durrantm/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from ../1.rb:1:in `<main>'

عند محاولة استخدام

require './2.rb'

في حين تستخدم

require_relative '3.rb'

لا يزال يعمل على ما يرام لأن المرجع (إلى 3.rb ) يتعلق 3.rb الذي يوجد به البرنامج ( 1.rb ).


Answer #5

أنا فقط رأيت رمز RSpec لديه بعض التعليق على require_relative كونها O (1) ثابتة require أن تكون O (N) خطي. لذلك ربما يكون الفرق هو أن require_relative هو الخيار المفضل أكثر من require .


Answer #6

أريد أن أضيف أنه عند استخدام النوافذ ، يمكنك استخدام require './1.rb' إذا كان البرنامج النصي يتم تشغيله محليًا أو من محرك أقراص شبكة معيّن ، ولكن عند تشغيله من مسار UNC \ servername \ sharename \ folder تحتاج إلى استخدام require_relative './1.rb' أنا لا require_relative './1.rb' في المناقشة التي تستخدم لأسباب أخرى.





require