রুবি: বনাম প্রয়োজনীয়_ সম্পর্কিত সম্পর্কিত - রুবি <1.9.2 এবং> = 1.9.2 উভয় ক্ষেত্রেই চলমান সর্বোত্তম অনুশীলন


153

আমি requireযদি রুবির কোনও আপেক্ষিক ফাইল চাই এবং আমি এটি 1.8.x এবং> = 1.9.2 উভয় ক্ষেত্রেই কাজ করতে চাই তবে সবচেয়ে ভাল অনুশীলনটি কী ?

আমি কয়েকটি বিকল্প দেখতে পাচ্ছি:

  • শুধু কি $LOAD_PATH << '.'এবং সবকিছু ভুলে
  • করা $LOAD_PATH << File.dirname(__FILE__)
  • require './path/to/file'
  • চেক RUBY_VERSION<1.9.2, তারপর সংজ্ঞায়িত require_relativeহিসাবে require, ব্যবহার require_relativeসর্বত্র যেখানে এটি পরে দরকার
  • require_relativeইতিমধ্যে উপস্থিত আছে কিনা তা পরীক্ষা করে দেখুন , যদি তা হয় তবে আগের অবস্থার মতো এগিয়ে যাওয়ার চেষ্টা করুন
  • অদ্ভুত নির্মাণগুলি ব্যবহার করুন - হায় আফসোস তারা রুবি ১.৯ এ কাজ করে না বলে মনে হয়, কারণ, উদাহরণস্বরূপ:
    require File.join(File.dirname(__FILE__), 'path/to/file')
    $ cat caller.rb
    require File.join(File.dirname(__FILE__), 'path/to/file')
    $ cat path/to/file.rb
    puts 'Some testing'
    $ ruby caller
    Some testing
    $ pwd
    /tmp
    $ ruby /tmp/caller
    Some testing
    $ ruby tmp/caller
    tmp/caller.rb:1:in 'require': no such file to load -- tmp/path/to/file (LoadError)
        from tmp/caller.rb:1:in '<main>'
  • এমনকি অযৌক্তিক নির্মাণ: মনে হচ্ছে এটি কাজ করে তবে এটি অদ্ভুত এবং দেখতে খুব সুন্দর নয়।
    require File.join(File.expand_path(File.dirname(__FILE__)), 'path/to/file')
  • ব্যাকপোর্টস রত্ন ব্যবহার করুন - এটি একরকম ভারী, এর জন্য রুবিজেমসের পরিকাঠামো প্রয়োজন এবং এতে প্রচুর পরিমাণে অন্যান্য কাজের পরিমাণ রয়েছে, যখন আমি কেবল requireআপেক্ষিক ফাইলগুলির সাথে কাজ করতে চাই ।

স্ট্যাকওভারফ্লোতে একটি ঘনিষ্ঠভাবে সম্পর্কিত প্রশ্ন রয়েছে যা আরও কয়েকটি উদাহরণ দেয় তবে এটি একটি পরিষ্কার উত্তর দেয় না - এটি একটি সেরা অনুশীলন।

আমার অ্যাপ্লিকেশনটি রুবি <1.9.2 এবং> = 1.9.2 উভয়কে চালিত করার জন্য কি কোনও শালীন, স্বীকৃত-সর্বজনীন সার্বজনীন সমাধান রয়েছে?

হালনাগাদ

স্পষ্টতা: আমি "আপনি এক্স করতে পারেন" এর মতো উত্তরগুলি চাই না - আসলে, আমি ইতিমধ্যে প্রশ্নের বেশিরভাগ পছন্দ উল্লেখ করেছি। আমি যৌক্তিকতা চাই , অর্থাত্ কেন এটি সর্বোত্তম অনুশীলন, এর উপকারিতা কী এবং অন্যদের মধ্যে কেন এটি চয়ন করা উচিত।


3
হাই আমি নতুন কেউ স্টার্ট কি পার্থক্য থেকে ব্যাখ্যা গেল requireএবং require_relative?
কর্নেল আতঙ্ক

3
পুরানো রুবি ১.৮-তে আপনি যদি ফাইল দৌড়ে থাকেন এবং বর্তমান ডিরেক্টরিতে a.rbদোভাষীকে পড়তে এবং ফাইলের বিষয়বস্তু বিশ্লেষণ করতে চান b.rb(সাধারণত একই দির যেমন থাকে a.rb) তবে আপনি কেবল লিখতে পারেন require 'b'এবং এটি ঠিক আছে কারণ ডিফল্ট অনুসন্ধানের পথে বর্তমান ডিরেক্টরি অন্তর্ভুক্ত রয়েছে। আরও আধুনিক রুবি ১.৯-এ আপনাকে require_relative 'b'এই ক্ষেত্রে লিখতে require 'b'হবে যেমন কেবল স্ট্যান্ডার্ড লাইব্রেরির পাথ অনুসন্ধান করতে হবে। সরল স্ক্রিপ্টগুলির যথাযথভাবে ইনস্টল করা যাচ্ছে না (যেমন, স্ক্রিপ্টগুলি নিজেরাই ইনস্টল করুন ) forward
গ্রেগেট

আপনি এখন backportsকেবল এই জন্য ব্যবহার করতে পারেন require_relative, আমার উত্তরটি দেখুন ...
মার্ক-আন্দ্রে লাফোর্টুন

উত্তর:


64

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

https://github.com/appoxy/aws/blob/master/lib/awsbase/require_relative.rb

unless Kernel.respond_to?(:require_relative)
  module Kernel
    def require_relative(path)
      require File.join(File.dirname(caller[0]), path.to_str)
    end
  end
end

এটি আপনাকে require_relativeরুবি ১.৯.২ এবং রুবি ১.৯.২ তে যেমন ব্যবহার করতে দেয় ।


3
কীভাবে আপনার প্রয়োজনীয়_relative.rb ফাইলের প্রয়োজন? আপনার প্রয়োজনীয়_relative.rb প্রয়োজন এবং তারপরে প্রয়োজনীয়_র সম্পর্কিত প্রয়োজন re নাকি আমি কিছু মিস করছি?
এথিক্যালহ্যাক 3 ই

7
require_relativeফাংশন রুবি কোর লাইব্রেরী একটি এক্সটেনশন প্রকল্পের মধ্যে অন্তর্ভুক্ত করা হয়, এখানে পাওয়া গেছে: rubyforge.org/projects/extensions আপনি তাদের সাথে ইনস্টল করতে সক্ষম হওয়া উচিত gem install extensions। তারপর আপনার কোডে আগে নিম্নলিখিত লাইন যোগ require_relative: প্রয়োজন 'এক্সটেনশন / সব' (Aurril এর পোস্ট থেকে sourced এখানে )
thegreendroid

@ ethicalhack3r কেবল আপনার রুবি স্ক্রিপ্টের শীর্ষে বা রেলগুলিতে that কোডটি অনুলিপি করুন এবং পেস্ট করুন, এটিকে শীর্ষ পরিবেশে ফেলে দিন r rb বা অন্য কিছু।
ট্র্যাভিস রেডার

46

আমি জাম্পটি 1.9.2 এ যাওয়ার আগে আমি আপেক্ষিকের জন্য নিম্নলিখিতগুলি ব্যবহার করেছি:

require File.expand_path('../relative/path', __FILE__)

প্রথমবার এটি দেখলে এটি কিছুটা অদ্ভুত, কারণ মনে হচ্ছে শুরুতে কোনও অতিরিক্ত '..' রয়েছে। কারণটি হ'ল expand_pathদ্বিতীয় আর্গুমেন্টের তুলনায় কোনও পথ প্রসারিত হবে এবং দ্বিতীয় যুক্তিটি ব্যাখ্যা করা হবে যেন এটি একটি ডিরেক্টরি। __FILE__স্পষ্টতই কোনও ডিরেক্টরি নয়, তবে expand_pathফাইলগুলির উপস্থিতি আছে বা না থাকায় এটি বিবেচ্য নয়, এটি .., .এবং এর মতো জিনিসগুলি প্রসারিত করার জন্য কিছু বিধি প্রয়োগ করবে ~। আপনি যদি প্রাথমিক "ওয়েটামিন্যুটটি পেতে পারেন তবে সেখানে কোনও অতিরিক্ত ..নেই?" আমি মনে করি যে উপরের লাইনটি বেশ ভালভাবে কাজ করে।

Assuming যে __FILE__হয় /absolute/path/to/file.rbসেখানে কি ঘটছে যে, expand_pathস্ট্রিং গঠন করা হবে /absolute/path/to/file.rb/../relative/path, এবং তারপর একটি নিয়ম যে বলছেন আবেদন ..এটা আগে পাথ উপাদান অপসারণ করা উচিত ( file.rbএই ক্ষেত্রে), ফেরার /absolute/path/to/relative/path

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


1
আমি সাধারণত এটি দেখতে। এটি কুৎসিত, তবে এটি ভালভাবে কাজ করছে বলে মনে হচ্ছে।
yfeldblum

12
একটু ক্লিনার: File.expand_path ( 'আপেক্ষিক / পথ', File.dirname (প্রয়োজন ফাইল ))
Yannick Wurm

1
আমি মনে করি না এটি খুব পরিষ্কার, এটি আরও দীর্ঘ। এরা উভয়েই নরক হিসাবে পলাতক, এবং দুটি খারাপ বিকল্পের মধ্যে বেছে নেওয়ার সময় আমি পছন্দ করি কম টাইপিংয়ের জন্য।
থিও

6
দেখে মনে হচ্ছে ফাইল.এক্সপ্যান্ড_পাথ ('../ রেলপথ.এক্স', ফাইল.ডিরনাম ( ফাইল )) এটি আরও ভার্বোস হলেও, আরও ভাল প্রতিমা । অতিরিক্ত অস্তিত্বের ডিরেক্টরি সহ ডিরেক্টরি পথ হিসাবে ব্যাখ্যা করা কোনও ফাইল পাথের তর্কযোগ্যভাবে ভাঙা কার্যকারিতার উপর নির্ভর করা যখন / যদি সেই কার্যকারিতা স্থির হয়ে থাকে।
jpgeek

1
ভাঙা, সম্ভবত, তবে ইউনিক্সে চিরকাল এটাই ছিল। ডিরেক্টরি এবং '..' এর রেজোলিউশনের ক্ষেত্রে কোনও ডিরেক্টরি এবং কোনও ফাইলের মধ্যে কেবল কোনও পার্থক্য নেই - তাই আমি এটিতে কোনও ঘুম হারাচ্ছি না।
থিও

6

পিকাক্সে এর জন্য একটি স্নিপেট রয়েছে 1.8। এটা এখানে:

def require_relative(relative_feature)
  c = caller.first
  fail "Can't parse #{c}" unless c.rindex(/:\d+(:in `.*')?$/)
  file = $`
  if /\A\((.*)\)/ =~ file # eval, etc.
    raise LoadError, "require_relative is called in #{$1}"
  end
  absolute = File.expand_path(relative_feature, File.dirname(file))
  require absolute
end

এটি মূলত থিওর উত্তরগুলি কেবলমাত্র ব্যবহার করে তবে আপনি এখনও ব্যবহার করতে পারেন require_relative


এই স্নিপেটটি সঠিকভাবে চালু করা উচিত কিনা তা কীভাবে পরীক্ষা করবেন? ব্যবহার করছেন $RUBY_VERSIONবা require_relativeসরাসরি উপস্থিত আছে কিনা তা যাচাই করে?
গ্রেইগ্যাট

1
সর্বদা হাঁসের ধরণ, require_relativeসংজ্ঞায়িত কিনা তা পরীক্ষা করুন ।
থিও

@ থিও @ গ্রেগেট হ্যাঁ, আমি এটির প্রয়োজন কিনা তা পরীক্ষা করে দেখি। আমি লোকদের দেখানোর জন্য স্নিপেটটি এখানে রেখেছিলাম। ব্যক্তিগতভাবে, আমি যাইহোক যাইহোক গ্রেগের উত্তরটি ব্যবহার করতে পারি, আমি সত্যিই কেবল এটি পোস্ট করছিলাম কারণ কেউ নিজেরাই না রেখেই এটি উল্লেখ করেছে।
পল হাফার 21

6
$LOAD_PATH << '.'

$LOAD_PATH << File.dirname(__FILE__)

এটি কোনও ভাল সুরক্ষা অভ্যাস নয়: আপনি কেন আপনার পুরো ডিরেক্টরিটি প্রকাশ করবেন?

require './path/to/file'

এটি কাজ করে না যদি RUBY_VERSION <1.9.2

অদ্ভুত নির্মাণ যেমন ব্যবহার

require File.join(File.dirname(__FILE__), 'path/to/file')

এমনকি ওয়েয়ার্ড নির্মাণ:

require File.join(File.expand_path(File.dirname(__FILE__)), 'path/to/file')

ব্যাকপোর্টস রত্ন ব্যবহার করুন - এটি একরকম ভারী, এর জন্য রুবিজেমসের পরিকাঠামো প্রয়োজন এবং এতে প্রচুর পরিমাণে অন্যান্য কাজের পরিমাণ রয়েছে, যখন আমি কেবল আপেক্ষিক ফাইলগুলির সাথে কাজ করতে চাই।

এগুলি কেন সর্বোত্তম বিকল্প নয় তা আপনি ইতিমধ্যে উত্তর দিয়েছেন।

RUBY_VERSION <1.9.2 কিনা তা পরীক্ষা করে দেখুন, প্রয়োজন অনুসারে প্রয়োজন_ সম্পর্কিত সম্পর্কিত সংজ্ঞায়িত করুন, যেখানে প্রয়োজন তার পরে যেখানে প্রয়োজন সেখানে_ প্রয়োজন সম্পর্কিত ব্যবহার করুন

প্রয়োজনীয়_সম্পর্কিত ইতিমধ্যে উপস্থিত রয়েছে কিনা তা পরীক্ষা করে দেখুন, যদি তা হয় তবে পূর্ববর্তী ক্ষেত্রে যেমনটি এগিয়ে চলার চেষ্টা করুন

এটি কাজ করতে পারে তবে নিরাপদ এবং দ্রুততর উপায় রয়েছে: লোডেরর ব্যতিক্রমটি মোকাবেলা করতে:

begin
  # require statements for 1.9.2 and above, such as:
  require "./path/to/file"
  # or
  require_local "path/to/file"
rescue LoadError
  # require statements other versions:
  require "path/to/file"
end

5

আমি আরবিএক্স-প্রয়োজনীয়-আপেক্ষিক রত্ন ( উত্স ) ব্যবহারের অনুরাগী । এটি মূলত রুবিনিয়াসের জন্য লেখা হয়েছিল, তবে এটি এমআরআই 1.8.7 কে সমর্থন করে এবং 1.9.2 এ কিছুই করেনা। একটি রত্ন প্রয়োজন সহজ, এবং আমি আমার প্রকল্পে কোড স্নিপেট নিক্ষেপ করতে হবে না।

এটি আপনার জেমফাইলে যুক্ত করুন:

gem "rbx-require-relative"

তারপর require 'require_relative'আপনি আগে require_relative

উদাহরণস্বরূপ, আমার পরীক্ষার ফাইলগুলির মধ্যে একটি এর মতো দেখাচ্ছে:

require 'rubygems'
require 'bundler/setup'
require 'minitest/autorun'
require 'require_relative'
require_relative '../lib/foo'

এটি এই আইএমও এর যে কোনও একটি থেকে পরিষ্কার সমাধান, এবং রত্নটি ব্যাকপোর্টের মতো ভারী নয়।


4

দ্য backportsমণি এখন ব্যাকপোর্ট পৃথক লোড করতে পারবেন।

আপনি তখন সহজভাবে বলতে পারেন:

require 'backports/1.9.1/kernel/require_relative'
# => Now require_relative works for all versions of Ruby

এটি requireনতুন সংস্করণগুলিকে প্রভাবিত করবে না, বা এটি অন্য কোনও বিল্টিন পদ্ধতি আপডেট করবে না।


3

আরেকটি বিকল্প হ'ল দোভাষীকে কোন পাথ অনুসন্ধান করতে হবে তা বলা

ruby -I /path/to/my/project caller.rb

3

আমি __FILE__ এর উপর ভিত্তি করে সমাধানগুলি সমাধান করে দেখিনি এমন একটি সমস্যা হ'ল তারা সিমলিংকের সাথে সম্পর্ক ছিন্ন করে। উদাহরণস্বরূপ বলুন আমার কাছে রয়েছে:

~/Projects/MyProject/foo.rb
~/Projects/MyProject/lib/someinclude.rb

মূল স্ক্রিপ্ট, এন্ট্রি পয়েন্ট, অ্যাপ্লিকেশনটি foo.rb. এই ফাইলটি আমার AT PATH এ থাকা oo / স্ক্রিপ্ট / ফু এর সাথে লিঙ্কযুক্ত। যখন আমি 'foo' চালিত করি তখন এর জন্য বিবৃতিটি নষ্ট হয়ে যায়:

require File.join(File.dirname(__FILE__), "lib/someinclude")

কারণ __FILE__ হল ~ / স্ক্রিপ্টস / foo সুতরাং উপরের প্রয়োজনীয় বিবৃতিটি ~ / স্ক্রিপ্টস / foo / lib / someincolve.rb এর সন্ধান করে যা সম্ভবত উপস্থিত নেই doesn't সমাধান সহজ। যদি __FILE__ একটি প্রতীকী লিঙ্ক হয় তবে এটির ডিফারেন্স করা দরকার। পথের নাম # রিয়েলপথ আমাদের এই পরিস্থিতিতে সহায়তা করবে:

"পথের নাম" প্রয়োজন
ফাইল.জয়িন (ফাইল.ডাইরনাম (প্যাথনাম.নেইউ (__ ফাইল ফাইল __)। রিয়েলপথ), "লিবিব / সামান্য অন্তর্ভুক্ত") প্রয়োজন

2

আপনি যদি কোনও মণি নির্মাণ করছিলেন তবে আপনি লোডের পথটিকে দূষিত করতে চাইবেন না।

তবে, স্ট্যান্ডেলোন অ্যাপ্লিকেশনের ক্ষেত্রে আপনি প্রথম 2 উদাহরণের মতো লোড পাথের সাথে বর্তমান ডিরেক্টরিটি যুক্ত করা খুব সুবিধাজনক।

আমার ভোট তালিকার প্রথম বিকল্পে যায়।

আমি কিছু দৃ Rub় রুবির সেরা অনুশীলন সাহিত্য দেখতে পছন্দ করব।


1
পুনরায়: "আমি কিছু দৃ Rub় রুবি সেরা সাহিত্যের চর্চা দেখতে পছন্দ করব" " আপনি গ্রেগরি ব্রাউন এর রুবি সেরা অভ্যাসগুলি ডাউনলোড করতে পারেন । আপনিও রেল সেরা অভ্যাস সাইটগুলি পরীক্ষা করে দেখতে পারেন ।
মাইকেল স্টালকার

1

আমি নিজের নিজস্বটিকে সংজ্ঞায়িত করব relative_requireযদি এটি বিদ্যমান না থাকে (অর্থাত্ 1.8 এর নীচে) এবং তারপরে সর্বত্র একই বাক্য গঠন ব্যবহার করুন।


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