Чим навантаження відрізняється від вимог у Ruby?


Відповіді:


98

requireшукає бібліотеку за всіма визначеними шляхами пошуку, а також додає .rb або .so до імені файлу, яке ви вводите. Це також гарантує, що бібліотека включається лише один раз. Отже, якщо для вашої програми потрібні бібліотеки A та B та бібліотека B, бібліотека запитів A теж A буде завантажена лише один раз.

З loadвас виникла необхідність створення повне ім'я бібліотеки і завантажуються кожен раз , коли ви називаєте load- навіть якщо він вже перебуває в пам'яті.


Дякую, сер, тож ми можемо сказати .rb не потрібно при завантаженні. І "вимагати" не дзвонить весь час, якщо це в пам'яті?
Арпіт Вайшнав

4
requireвідстежує те, що вже було завантажено через $LOADED_FEATURES( $") глобальний масив, який loadігнорує.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

39

Ще одна відмінність між Kernel#requireіKernel#load полягає в тому, що Kernel#loadприймає необов’язковий другий аргумент, який дозволяє обернути завантажений код в анонімний порожній модуль.

На жаль, це не дуже корисно. По-перше, loadредагованому коду легко вирватися з модуля, просто отримавши доступ до глобального простору імен, тобто вони все одно можуть мавпати щось подібне class ::String; def foo; end end. А по-друге, loadне повертає модуль, в який він загортає код, тому вам, по суті, доведеться виловлювати його ObjectSpace::each_object(Module)вручну.


Дуже добре знати! Не Kernel#loadмав ідеї, мав інший аргумент
Джош Бода

На жаль, це не дуже корисно. По-перше, loadредагованому коду легко вирватися з модуля, просто отримавши доступ до глобального простору імен, тобто вони все одно можуть мавпати щось подібне class ::String; def foo; end end. А по-друге, loadне повертає модуль, в який він загортає код, тому вам, по суті, доведеться виловлювати його ObjectSpace::each_object(Module)вручну.
Jörg W Mittag

4

Я запускав програму Rails, і в Gemfile у мене був спеціальний власний камінь, який я створив із опцією "require: false". Тепер, коли я завантажив сервер Rails або консоль Rails, я зміг зажадати самоцвіт в ініціалізаторі, і дорогоцінний камінь було завантажено. Однак, коли я провів перевірку характеристик специфікації з rspec та capybara, я отримав помилку завантаження. І я був абсолютно здивований, чому самоцвіт не був знайдений у $ LOAD_PATH під час запуску тесту.

Тож я переглянув усі різні способи взаємодії рубігів та пакета, які завантажуються, вимагають. І це короткий опис моїх висновків, які допомогли мені знайти рішення моєї конкретної проблеми:

навантаження

1) Ви можете передати йому абсолютний шлях до рубінового файлу, і він виконає код у цьому файлі.

load('/Users/myuser/foo.rb')

2) Ви можете пройти відносний шлях до завантаження. Якщо ви знаходитесь в тому ж каталозі, що і файл, він знайде його:

> load('./foo.rb')
foo.rb loaded!
=> true

Але якщо ви спробуєте завантажити файл із іншого каталогу за допомогою load (), він не знайде його з відносним шляхом на основі поточного робочого каталогу (наприклад, /):

> load('./foo.rb')
LoadError: cannot load such file -- foo.rb

3) Як показано вище, load завжди повертає true (якщо файл не вдалося завантажити, він піднімає a LoadError).

4) Імпортуються глобальні змінні, класи, константи та методи, але не локальні змінні.

5) Двічі викликавши навантаження на один і той самий файл, буде виконано код у цьому файлі двічі. Якщо вказаний файл визначає константу, він визначить цю константу двічі, що видасть попередження.

6) $ LOAD_PATH - масив абсолютних шляхів. Якщо ви передаєте завантаження лише імені файлу, він прокручуватиме $ LOAD_PATH і шукатиме файл у кожному каталозі.

> $LOAD_PATH.push("/Users/myuser")
> load('foo.rb')
foo.rb loaded!
 => true

вимагати

1) Двічі вимагаючи виклику одного і того ж файлу, виконується лише один раз. Також досить розумно не завантажувати один і той же файл двічі, якщо ви посилаєтесь на нього один раз із відносним шляхом та один раз із абсолютним шляхом.

2) вимагати повернення true, якщо файл був виконаний, і false, якщо його не було.

3) require відстежує, які файли вже завантажені в глобальну змінну $ LOADED_FEATURES.

4) Вам не потрібно включати розширення файлу:

require 'foo'

5) require буде шукати foo.rb, а також динамічні файли бібліотеки, такі як foo.so, foo.o або foo.dll. Ось як ви можете зателефонувати коду С із рубіну.

6) require не перевіряє поточний каталог, оскільки поточний каталог за замовчуванням не знаходиться в $ LOAD_PATH.

7) require_relative бере шлях відносно поточного файлу, а не робочого каталогу процесу.

Рубігеми

1) Rubygems - це менеджер пакетів, призначений для легкого управління встановленням бібліотек Ruby, які називаються gems.

2) Він упаковує свій вміст як zip-файл, що містить купу рубінових файлів та / або динамічних бібліотечних файлів, які можна імпортувати за допомогою вашого коду, разом з деякими метаданими.

3) Rubygems замінює метод за замовчуванням require на власну версію. Ця версія переглядатиме ваші встановлені дорогоцінні камені на додаток до каталогів у $ LOAD_PATH. Якщо Rubygems знайде файл у ваших дорогоцінних каменях, він додасть цей самоцвіт до вашого $ LOAD_PATH.

4) Команда gem install встановлює всі залежності gem і встановлює їх. Насправді він встановлює всі залежності дорогоцінного каменя, перш ніж встановлювати сам камінь.

Пакувальник

1) Bundler дозволяє вказати всі дорогоцінні камені, які потрібні вашому проекту, а також, які версії цих дорогоцінних каменів. Потім команда bundle встановлює всі ці дорогоцінні камені та їх залежності.

2) Ви вказуєте, які дорогоцінні камені вам потрібні у файлі під назвою Gemfile.

3) Команда bundle також встановлює всі дорогоцінні камені, перелічені в Gemfile.lock, у певних перелічених версіях.

4) Поставивши bundle exec перед командою, наприклад bundle exec rspec, гарантує, що require завантажить версію дорогоцінного каменя, вказану у вашому Gemfile.lock.

Рейки та набір

1) У config / boot.rb потрібно виконати 'bundler / setup'. Бандлер гарантує, що Рубі може знайти всі дорогоцінні камені в Gemfile (і всі їх залежності). require 'bundler / setup' автоматично виявить ваш Gemfile і зробить усі дорогоцінні камені у вашому Gemfile доступними для Ruby (у технічному плані це ставить дорогоцінні камені "на шлях завантаження"). Ви можете сприймати це як додавання деяких додаткових повноважень, щоб вимагати "рубімів".

ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])

2) Тепер, коли ваш код доступний Ruby, ви можете зажадати дорогоцінні камені, які вам потрібні. Наприклад, ви можете вимагати "синатра". Якщо у вас багато залежностей, ви можете сказати "вимагати всіх дорогоцінних каменів у моєму Gemfile". Для цього поставте наступний код відразу ж після вибору 'bundler / setup':

Bundler.require(:default)

3) За замовчуванням для виклику Bundler.require потрібен кожен дорогоцінний камінь у вашому Gemfile. Якщо в рядку в Gemfile написано gem 'foo',: require => false, тоді він переконається, що foo встановлено, але він не викликає require. Вам потрібно буде зателефонувати require ('foo'), якщо ви хочете використовувати самоцвіт.

Отже, враховуючи цю широту знань, я повернувся до питання мого тесту і зрозумів, що я повинен явно вимагати самоцвіт у rails_helper.rb, оскільки Bundler.setup додав його до $ LOAD_PATH, але вимагає: false виключає Bundler.require вимагати цього явно . І тоді питання було вирішено.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.