Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

यह समझना कि कैसे Rbenv, RubyGems और Bundler एक साथ काम करते हैं

रूबी में निर्भरता प्रबंधन में आमतौर पर रूबी और मणि संस्करणों को निर्दिष्ट करना शामिल होता है जिस पर हमारी परियोजना निर्भर करती है। रूबी के साथ काम करने के मेरे अनुभव में, डिबगिंग निर्भरता मेरी सबसे बड़ी चुनौतियों में से एक रही है। असफलताएं आम नहीं हैं क्योंकि कई चीजें "बस काम करती हैं"; हालांकि, जब चीजें गलत हो जाती हैं, तो आमतौर पर उन्हें डीबग करना और ठीक करना अनावश्यक रूप से कठिन होता है। इस लेख में, मैं रूबी में निर्भरता प्रबंधन में शामिल टुकड़ों को रखूंगा। यह इन अजीब मुद्दों को होने पर डीबग करने में सहायता करेगा।

यह समझना कि कैसे Rbenv, RubyGems और Bundler एक साथ काम करते हैं

रूबी कोड लोड हो रहा है

डिफ़ॉल्ट रूप से, रूबी भाषा कहीं और परिभाषित कोड लोड करने के लिए दो प्रमुख तरीके प्रदान करती है:load &require

load 'json.rb'
require 'json.rb'
require_relative 'json.rb'

दोनों लोडिंग विधियां पूर्ण और सापेक्ष पथ दोनों को तर्क के रूप में स्वीकार करती हैं। हालांकि, दो अलग-अलग कारक हैं:

  1. एकाधिक कॉल load फ़ाइल को फिर से निष्पादित करेगा, जबकि require . के लिए एकाधिक कॉल फ़ाइल को फिर से निष्पादित नहीं करेगा; इसके बजाय, यह false लौटाएगा ।
  2. load करने के लिए कॉल करता है केवल निरपेक्ष और सापेक्ष पथों का समाधान करता है। require . के लिए कॉल $LOAD_PATH . पर जांच करता है जब पथ पूर्ण पथ का समाधान नहीं करता है।

एक तीसरा प्रकार है require_relative , जो रूबी प्रक्रिया की कार्यशील निर्देशिका के बजाय वर्तमान फ़ाइल के स्थान के सापेक्ष कोड की आवश्यकता के लिए सापेक्ष पथ का उपयोग करता है।

आरबीएनवी

एक संस्करण प्रबंधक एक उपकरण है जिसका उपयोग हमारे दुभाषिया (इस मामले में, रूबी) के संस्करणों के बीच प्रबंधन और आसानी से स्विच करने के लिए किया जाता है और हमारी परियोजना के लिए संबंधित रत्न खोजने के लिए स्थान निर्दिष्ट करता है। संस्करण प्रबंधक मोटे तौर पर भाषा अज्ञेयवादी उपकरण हैं, और विभिन्न भाषाओं में उनके संबंधित कार्यान्वयन होते हैं, जैसे कि Nvm, n Node.js के लिए, pyenv के लिए Python, और Rbenv, rvm, और रूबी के लिए chruby। अब, चलिए rbenv लेते हैं स्पिन के लिए, क्या हम?

रूबी संस्करण स्थापित करें

हम कमांड का उपयोग करते हैं rbenv install रूबी के किसी भी संस्करण को स्थापित करने के लिए:

# Install ruby 2.6.1
$ rbenv install 2.6.1
Downloading openssl-1.1.1i.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242
Installing openssl-1.1.1i...
Installed openssl-1.1.1i to /home/directory/.rbenv/versions/2.6.1

Downloading ruby-2.6.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.1.tar.bz2
Installing ruby-2.6.1...
ruby-build: using readline from homebrew
Installed ruby-2.6.1 to /home/directory/.rbenv/versions/2.6.1

# Check Installation
$ rbenv versions # Shows all versions installed.
  system
  2.6.1

# Lookup versions available for installation
$ rbenv install -L
1.8.5-p52
1.8.5-p113
1.8.5-p114
...
2.7.0-rc1
2.7.0-rc2
2.7.0
...
truffleruby+graalvm-20.1.0
truffleruby+graalvm-20.2.0
truffleruby+graalvm-20.3.0

# The full list above amounts to about 500 versions, scrolling through the entire list is a lot.
# The command below is an easy shortcut to find your specific version with fzf.
$ rbenv install `rbenv install -L | fzf`

संस्करणों के बीच स्विच करें

रूबी के संस्करणों के बीच स्विच करने के तरीके की पहचान करने के कई तरीके हैं; निरपवाद रूप से, rbenv निम्नलिखित करता है:

  • RBENV_VERSION की जांच करता है ।
  • एक .ruby-version की खोज करता है स्क्रिप्ट की निर्देशिका और उसके पैरेंट में फ़ाइल तब तक रखें जब तक कि वह रूट डायरेक्टरी में न आ जाए।
  • एक .ruby-version की खोज करता है फ़ाइल $PWD . में और इसकी मूल निर्देशिका जब तक यह रूट निर्देशिका को हिट नहीं करती।
  • वैश्विक फ़ाइल का उपयोग करता है ~/.rbenv/version

प्राथमिकता ऊपर से नीचे तक जाती है। ~/.rbenv/version अंतिम फ़ॉलबैक है और इसे वैश्विक संस्करण के रूप में माना जाता है। नीचे देखें:

# Inside First Project Root

# Select ruby version for project
$ touch .ruby-version && echo "2.7.1" >> .ruby-version

# Verify selected version
$ ruby --version
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin20] # Result

$ rbenv version
2.7.1 (set by /path/to/current/directory/.ruby-version) # Result

# Change selected version
$ : >> .ruby-version && echo "2.6.1" >> .ruby-version

# Verify selection change
$ ruby --version
ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-darwin20] # Result

$ rbenv version
2.6.1 (set by /path/to/current/directory/.ruby-version)

# Change selection with RBENV_VERSION while .ruby-version is present
$ export RBENV_VERSION=2.5.1

# Verify selection change
# .ruby-version is ignored.
$ ruby --version
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin20] # Result

$ rbenv version
2.5.1 (set by RBENV_VERSION environment variable) # Result

# Change to a version that is not installed & remove RBENV_VERSION
$ unset RBENV_VERSION & : >> .ruby-version && echo "2.4.1" >> .ruby-version

# Verify selection change
$ ruby --version
rbenv: version `2.4.1' is not installed (set by full/path/to/current/directory/.ruby-version) # Result

शिम्स और रीहैशिंग

डीबग करने में सक्षम होने के लिए इन दो अवधारणाओं को ठीक से समझने की आवश्यकता है rbenv प्रभावी ढंग से।

शिम्स हल्के बैश स्क्रिप्ट हैं जो आपके PATH . में मौजूद हैं कमांड को इंटरसेप्ट करना और उन्हें निष्पादन के लिए उपयुक्त संस्करण में रूट करना। उच्च स्तर पर, प्रत्येक आदेश (उदा., rspec ) का अनुवाद rbenv exec rspec . में किया गया है . नीचे विवरण देखें।

सबसे पहले, rbenv सभी कमांड के लिए एक शिम बनाता है (rspec , bundle , आदि) सभी स्थापित रूबी संस्करणों में संस्करण की परवाह किए बिना सीएलआई को कॉल को इंटरसेप्ट करने के लिए। ये शिम ~/.rbenv/shims . पर मिल सकते हैं . हर शिम में वही बैश स्क्रिप्ट होती है, जैसा कि नीचे दिखाया गया है:

#!/usr/bin/env bash
set -e
[ -n "$RBENV_DEBUG" ] && set -x

program="${0##*/}"
if [ "$program" = "ruby" ]; then
   for arg; do
     case "$arg" in
     -e* | -- ) break ;;
     */* )
        if [ -f "$arg" ]; then
         export RBENV_DIR="${arg%/*}"
         break
       fi
       ;;
     esac
   done
 fi

 export RBENV_ROOT="/home/directory/.rbenv"
 exec "/usr/local/Cellar/rbenv/1.1.2/libexec/rbenv" exec "$program" "$@"

इसके बाद, ऊपर की स्क्रिप्ट मोटे तौर पर निम्नलिखित में बदल जाती है:

  • यदि प्रोग्राम का नाम ruby है तर्क के साथ -e ,
    • अनुवाद करें rbenv exec ruby <args>
  • यदि प्रोग्राम का नाम ruby है स्क्रिप्ट के पथ के साथ,
    • RBENV_DIR सेट करें स्क्रिप्ट की निर्देशिका में। यह सक्षम करता है rbenv .ruby-version . को खोजने के लिए $PWD . से पहले स्क्रिप्ट की निर्देशिका में . यदि एक .ruby-version दोनों स्थानों में निर्दिष्ट है, rbenv स्क्रिप्ट की निर्देशिका का चयन करता है।
  • यदि प्रोग्राम का नाम रूबी नहीं है,
    • अनुवाद करें rbenv exec <program-name> <args>

अंत में, rbenv exec <command-name> <args> RBENV_VERSION . को चेक करके कमांड को पास करने के लिए सही संस्करण की पहचान करता है पर्यावरणपरिवर्ती तारक। याद रखें, RBENV_VERSION ऊपर परिभाषित एल्गोरिथम द्वारा सेट किया गया है।

आपके PATH . पर शर्म आती है प्रीपेड होना चाहिए; यह सुनिश्चित करता है कि वे आपके रूबी निष्पादन योग्य के लिए संपर्क का पहला बिंदु हैं और ठीक से इंटरसेप्ट कर सकते हैं। आपके PATH . को समझने का सबसे अच्छा तरीका मैंने पाया सेटअप करें और जानें कि आपके शिम ठीक से इंटरसेप्ट कर रहे हैं या नहीं:

$ which -a bundle

/path/to/home/.rbenv/shims/bundle
/usr/bin/bundle

which -a bundle :यह भोलेपन से आपके PATH . को देखता है और जिस क्रम में यह पाया जाता है, उस स्थान पर प्रिंट आउट करता है जहां bundle पाया जा सकता है। अगर ~/.rbenv/shims . में किसी भी चीज़ से पहले कुछ छपा हुआ है , इसका मतलब है कि आपके शिम ठीक से सेट नहीं हैं। rbenv which bundle इसे प्रकट नहीं करेगा क्योंकि कमांड rbenv . के संदर्भ में काम करता है अपना PATH नहीं खोज रहे हैं ।

रीहैशिंग शिम बनाने की प्रक्रिया है। जब आप एक रूबी रत्न स्थापित करते हैं जो निष्पादन योग्य प्रदान करता है, जैसे rspec , आपको rbenv rehash चलाने की आवश्यकता है शिम बनाने के लिए ताकि बाद में rspec . पर कॉल किया जा सके rbenv . द्वारा इंटरसेप्ट किया जा सकता है और उपयुक्त रूबी संस्करण पर चला गया।

रूबीजेम्स

इसके बाद रूबीगेम्स है। यह आधिकारिक रूबी साइट से उपलब्ध है। RubyGems एक रूबी पैकेजिंग प्रणाली है जिसे पुस्तकालयों के निर्माण, साझाकरण और स्थापना की सुविधा के लिए डिज़ाइन किया गया है; कुछ मायनों में, यह एक वितरण पैकेजिंग प्रणाली है, कहते हैं, उपयुक्त-प्राप्त करें, लेकिन रूबी सॉफ़्टवेयर पर लक्षित है। RubyGems रत्नों को साझा करने का वास्तविक तरीका है। वे आमतौर पर ~/.rbenv/versions/{version-number}/lib/ruby/gems/{minor-version}/ पर इंस्टॉल किए जाते हैं। , या इसका संस्करण, इस पर निर्भर करता है कि किस संस्करण प्रबंधक का उपयोग किया गया है। रूबी की डिफ़ॉल्ट आवश्यक विधि Kernel.require रत्न स्थापना निर्देशिका से रत्न लोड करने के लिए कोई तंत्र प्रदान नहीं करता है। RubyGems बंदर-पैच Kernel.require करने के लिए

  • सबसे पहले, $LOAD_PATH में रत्न खोजें ।
  • अगर नहीं मिला, तो GEMS INSTALLATION DIRECTORY में रत्न खोजें .
    • एक बार मिल जाने पर, पथ को $LOAD_PATH . में जोड़ें ।

यह "मूल रूप से" काम करता है क्योंकि रूबी डिफ़ॉल्ट रूप से 1.9 संस्करण के बाद से RubyGems के साथ आया है; पिछले रूबी संस्करणों को रूबीजम्स को मैन्युअल रूप से स्थापित करने की आवश्यकता थी। हालांकि यह मूल रूप से काम करता है, डिबगिंग करते समय इस अंतर को जानना भी महत्वपूर्ण है।

एक रत्न एक विशिष्ट समस्या को हल करने के लिए उपयोग किए जाने वाले संबंधित कोड का एक समूह है। रत्न स्थापित करें और रत्न पर्यावरण के बारे में निम्न प्रकार से जानकारी प्राप्त करें:

$ gem install gemname
$ gem env

RubyGems Environment: 
    - RUBYGEMS VERSION: 3.1.2 
    - RUBY VERSION: 2.7.1 (2020-03-31 patchlevel 83) [x86_64-darwin20] 
    - INSTALLATION DIRECTORY: /path/to/home/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0 
    - USER INSTALLATION DIRECTORY: /path/to/home/.gem/ruby/2.7.0 
    - RUBY EXECUTABLE: /path/to/home/.rbenv/versions/2.7.1/bin/ruby 
    - GIT EXECUTABLE: /usr/bin/git 
    - EXECUTABLE DIRECTORY: /path/to/home/.rbenv/versions/2.7.1/bin 
    - SPEC CACHE DIRECTORY: /path/to/home/.gem/specs 
    - SYSTEM CONFIGURATION DIRECTORY: /path/to/home/.rbenv/versions/2.7.1/etc 
    - RUBYGEMS PLATFORMS:   
        - ruby   
        - x86_64-darwin-20 
    - GEM PATHS:    
        - /path/to/home/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0    
        - /path/to/home/.gem/ruby/2.7.0 
    - GEM CONFIGURATION:    
        ...
    - REMOTE SOURCES:    
        - https://rubygems.org/ 
    - SHELL PATH:    
        - /path/to/home/.rbenv/versions/2.7.1/bin

RubyGems इस समस्या को कैसे हल करता है? यह बंदर Kernel को पैच कर देता है अपने स्वयं के require with के साथ सिस्टम की आवश्यकता है तरीका। इस जगह के साथ, जब require honeybadger कहा जाता है, यह रत्न फ़ोल्डर के माध्यम से honeybadger.rb के लिए खोज करता है और रत्न मिलने पर सक्रिय हो जाता है।

उदाहरण के लिए, require 'honeybadger' निम्न के जैसा कुछ उत्पन्न करता है:

  • spec = Gem::Specification.find_by_path('honeybadger')
  • spec.activate

किसी रत्न को सक्रिय करने का सीधा सा अर्थ है उसे $LOAD_PATH . में डालना . RubyGems, मणि को डाउनलोड करने से पहले, रत्न की सभी निर्भरताओं को डाउनलोड करने में भी मदद करता है।

इसके अलावा, Rubygems एक अच्छी सुविधा के साथ जहाज करता है जो आपको संबंधित रत्न की निर्देशिका को gem open <gem-name> के साथ खोलने में सक्षम बनाता है।; उदाहरण के लिए,

यह समझना कि कैसे Rbenv, RubyGems और Bundler एक साथ काम करते हैं

यह हमें हमारे ऐप द्वारा संदर्भित रत्न के विशिष्ट संस्करण को आसानी से ढूंढने/ट्रेस करने की अनुमति देता है।

बंडलर

इस स्तर पर, बंडलर हमारी सभी परियोजना निर्भरताओं को आसानी से निर्दिष्ट करने में हमारी सहायता करता है और वैकल्पिक रूप से प्रत्येक के लिए एक संस्करण निर्दिष्ट करता है। फिर, यह हमारे रत्नों को हल करता है, साथ ही इसे और इसकी निर्भरता को स्थापित करता है। वास्तविक दुनिया के अनुप्रयोगों का निर्माण पूर्व-बंडलर कई चुनौतियों के साथ आया, जैसे कि निम्न:

  • हमारे एप्लिकेशन कई निर्भरता के साथ मौजूद हैं, और इन निर्भरताओं में कई अन्य निर्भरताएं और उनके संबंधित संस्करण हैं। एक रत्न का गलत संस्करण स्थापित करने से हमारा ऐप आसानी से टूट जाएगा, और इस समस्या को ठीक करने में बहुत सारे आँसू शामिल थे।
  • साथ ही, हमारी निर्भरता के दो(2) समान तृतीय-स्तरीय निर्भरता को संदर्भित कर सकते हैं। संगतता ढूँढना एक समस्या थी, और यदि कोई थी, तो यह एक समस्या थी।
  • जहां हमारे पास एक ही मशीन पर कई एप्लिकेशन हैं, विभिन्न निर्भरता के साथ, हमारा एप्लिकेशन मशीन पर इंस्टॉल किए गए किसी भी रत्न तक पहुंच सकता है, जो कम से कम विशेषाधिकार के सिद्धांत के खिलाफ जाता है और मशीन पर स्थापित सभी रत्नों के लिए हमारे एप्लिकेशन को उजागर करता है, चाहे कुछ भी हो क्या वे दुर्भावनापूर्ण हैं।

बंडलर तीनों समस्याओं को हल करता है और हमें निम्न कार्य करके अपनी ऐप निर्भरता को प्रबंधित करने का एक समझदार तरीका देता है।

बंडलर निर्भरता को हल करता है और एक लॉकफाइल बनाता है:

# Gemfile
gem 'httparty'

अगर हम bundle run चलाते हैं या bundle install , यह लॉकफाइल उत्पन्न करेगा:

GEM
  specs:
    httparty (0.18.1)
      mime-types (~> 3.0)
      multi_xml (>= 0.5.2)
    mime-types (3.3.1)
      mime-types-data (~> 3.2015)
    mime-types-data (3.2020.1104)
    multi_xml (0.6.0)

PLATFORMS
  ruby

DEPENDENCIES
  httparty

BUNDLED WITH
   2.1.4

ऊपर से, बंडलर httparty . का संस्करण तैयार करता है स्थापित करने के लिए, साथ ही साथ Gemfile.lock. . में अपनी निर्भरताएं यह फ़ाइल हमारी ऐप निर्भरता का खाका है और इसे संस्करण नियंत्रण में चेक किया जाना चाहिए। यह सुनिश्चित करता है कि हमारी परियोजना निर्भरताएं पूरे वातावरण (विकास, मंचन, या उत्पादन) के अनुरूप हों।

बंडलर निर्भरता के बीच संगतता का समाधान करता है

यह httparty . के लिए निर्भरता का समाधान करता है इसकी निर्भरता के लिए एक उपयुक्त संस्करण ढूंढकर और उन्हें निर्दिष्ट करके। बंडलर रत्नों के बीच निर्भरता को हल करने का भी प्रयास करता है। उदाहरण के लिए,

# Gemfile
gem 'httparty' # That relies on gem 'mime-types', '>= 3.0.1, < 4.0.1'
gem 'rest-client' # That relies on gem 'mime-types', '>= 2.0.1, < 3.0'

ऊपर दिया गया उदाहरण मनमाना है और इसके परिणामस्वरूप एक त्रुटि होगी, जैसे कि निम्न:

Bundler could not find compatible versions for gem "mime-types":
In Gemfile:
    httparty was resolved to 0.18.1, which depends on
        mime-types ('>= 3.0.1, < 4.0.1')

    rest-client was resolved to 2.0.4, which depends on
        mime-types ('>= 2.0.1, < 3.0')

ऐसा इसलिए है क्योंकि दो रत्नों में ऐसी निर्भरताएँ होती हैं जो संगत नहीं होती हैं और जिन्हें स्वचालित रूप से हल नहीं किया जा सकता है।

बंडलर स्थापित रत्नों तक पहुंच को प्रतिबंधित करता है लेकिन हमारे Gemfile में निर्दिष्ट नहीं है।

निम्न की तरह एक नमूना जेमफाइल में,

# Gemfile
gem 'httparty'

# irb
require 'rest-client'

# raises
LoadError (cannot load such file -- rest-client)

यह सुनिश्चित करता है कि केवल हमारे Gemfile . में निर्दिष्ट निर्भरताएँ हमारी परियोजना के लिए आवश्यक हो सकता है।

बंडल निष्पादन

जब आप rspec run चलाते हैं किसी प्रोजेक्ट निर्देशिका में, Gemfile में निर्दिष्ट किए गए संस्करण के अलावा किसी भिन्न संस्करण को चलाने की संभावना है . ऐसा इसलिए है क्योंकि Gemfile . में निर्दिष्ट संस्करण बनाम चलाने के लिए नवीनतम संस्करण का चयन किया जाएगा . bundle exec rspec सुनिश्चित करता है rspec उस प्रोजेक्ट के संदर्भ में चलाया जाता है (यानी, जेमफाइल में निर्दिष्ट रत्न)।

बंडल बिनस्टब्स

अक्सर, हम ऐसे लेख पढ़ते हैं जहां हम ./bin/rails . जैसे कमांड चलाते हैं; यह कमांड bundle exec rails के समान है . Binstubs bundle exec . के उपयोग को आसान बनाने के लिए रूबी एक्ज़ीक्यूटिव के चारों ओर रैपर हैं ।

एक बिनस्टब रन उत्पन्न करने के लिए, bundle binstubs gem-name का उपयोग करें . यह ./bin . में एक बिनस्टब बनाता है फ़ोल्डर लेकिन --path . के साथ कॉन्फ़िगर किया जा सकता है निर्देशिका अगर सेट है।

संदर्भ

अधिक जानने के लिए, इन संदर्भों को देखें:

  • रत्न कैसे काम करते हैं?
  • आरबीएनवी
  • रूबीजेम्स
  • बंडलर

  1. WPS क्या है और यह कैसे काम करता है?

    WPS का मतलब वाई-फाई संरक्षित सेटअप है। WPS का क्या अर्थ है? WPS न्यूनतम प्रयास के साथ घर पर एक सुरक्षित वाई-फाई नेटवर्क स्थापित करने की एक विधि है। इसमें आमतौर पर इसे सक्रिय करने के लिए आपके राउटर पर WPS बटन को दबाना शामिल है। कई राउटर पर WPS बटन 2006 में वाई-फाई एलायंस द्वारा बनाया गया था। इसका

  1. रूबी 2.6 में एमजेआईटी क्या है और यह कैसे काम करता है?

    रूबी के प्रदर्शन में बहुत सुधार हो रहा है, संस्करण दर संस्करण… और रूबी विकास टीम रूबी को और भी तेज बनाने के लिए हर संभव प्रयास कर रही है! इन प्रयासों में से एक 3×3 परियोजना है। लक्ष्य? रूबी 3.0, रूबी 2.0 से 3 गुना तेज होगा । इस प्रोजेक्ट का एक हिस्सा नया MJIT कंपाइलर है, जो इस लेख का विषय है। MJ

  1. कोरटाना और एलेक्सा का एक साथ उपयोग कैसे करें

    माइक्रोसॉफ्ट आखिरकार जनवरी में अपने बिल्ड डेवलपर सम्मेलन में घोषणा करने के बाद एलेक्सा को विंडोज 10 पीसी और कॉर्टाना को इको स्पीकर में लाता है। वर्तमान में पूर्वावलोकन केवल युनाइटेड स्टेट्स में उपलब्ध है, लेकिन ऐसा लगता है कि इस साझेदारी को अभी लंबा रास्ता तय करना है। हम एक बहुआयामी दुनिया में रहते