Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Ruby의 코드 로더:Zeitwerk 이해

Ruby의 코드 로더 - Zeitwerk 이해

Zeitwerk를 사용하면 모든 곳에서 클래스와 모듈을 사용할 수 있다는 사실을 알고 프로그래밍을 간소화할 수 있습니다.

코드 로더란 무엇입니까?

코드 로더를 사용하면 개발자가 classes를 정의할 수 있습니다. 및 modules 다른 파일과 폴더에 걸쳐 있고 명시적으로 요구하지 않고 코드베이스 전체에서 사용합니다. Rails는 코드 로더를 사용하는 소프트웨어의 좋은 예입니다. Rails 프로그래밍에는 명시적인 require가 필요하지 않습니다. 컨트롤러에서 모델을 사용하기 전에 로드 모델을 호출합니다. 사실, Rails 6에서는 app의 모든 것이 디렉토리는 몇 가지 예외를 제외하고 앱 부팅 시 자동으로 로드됩니다.

코드 로딩이 require를 호출하는 것이라고 생각하기 쉽지만 , 그렇게 간단하지 않습니다. 코드 로딩은 다음과 같이 세 부분으로 더 나눌 수 있습니다.

  • 자동 로드: 이는 코드가 필요에 따라 즉석에서 로드됨을 의미합니다. 예를 들어, Rails에서 rails s 실행 모든 모델, 컨트롤러 등을 로드하지는 않습니다. 그러나 User 모델의 첫 번째 히트에서 , 자동 로딩 메커니즘을 실행하여 모델을 찾고 사용합니다. 이것은 작동 중인 자동 로드입니다. 이것은 더 빠른 앱과 rails console이 있기 때문에 개발 환경에 몇 가지 이점이 있습니다. 시작 시간. Rails.config.autoload_path 자동 로드할 경로를 제어합니다.
  • 빠른 로딩: 즉, 앱 시작 시 코드가 메모리에 로드되고 상수를 요구하기 전에 호출될 때까지 기다리지 않습니다. Rails에서 코드는 프로덕션 환경에서 즉시 로드됩니다. 위의 설명에 따르면 프로덕션에서 코드를 자동 로드하면 각 상수가 즉석에서 필요하기 때문에 응답 시간이 느려집니다. Rails.config.eager_load_paths 즉시 로드할 경로를 제어합니다.
  • 다시 로드: 코드 로더는 autoload_path의 파일 변경 사항을 지속적으로 감시합니다. 변경 사항이 감지되면 파일을 다시 로드합니다. Rails에서는 rails s를 실행할 수 있으므로 개발에 매우 ​​유용할 수 있습니다. Rails 서버를 다시 시작할 필요 없이 동시에 변경할 수 있습니다. 다시 로드 중입니다.

우리는 이러한 개념의 대부분이 Rails에서 개발되고 실행되고 있음을 쉽게 알 수 있습니다. Zeitwerk는 이것을 변경합니다! Zeitwerk를 사용하면 모든 코드 로드 작업을 모든 Ruby 프로젝트에 가져올 수 있습니다.

자이트베르크란 무엇입니까?

Zeitwerk는 효율적이고 스레드로부터 안전한 Ruby용 코드 로더이며 웹 프레임워크(Rails, Hanami, Sinatra), Cli 도구 및 gem을 포함한 모든 Ruby 프로젝트에서 사용할 수 있습니다. 이를 통해 모든 곳에서 클래스와 모듈을 사용할 수 있다는 사실을 알고 프로그래밍을 간소화할 수 있습니다. 전통적으로 Rails와 일부 다른 gem에는 이 기능을 활성화하는 코드 로더가 내장되어 있습니다. 그러나 Zeitwerk는 이러한 개념을 보석으로 추출하고 Rubyists가 이러한 개념을 프로젝트에 적용할 수 있도록 합니다.

자이트베르크 설치

먼저 gem을 설치해야 합니다.

gem install zeitwerk

# OR in your Gemfile
gem 'zeitwerk', '~> 2.4.0'

자이트베르크 구성

이제 기본 사항부터 시작하겠습니다.

require 'zeitwerk'
loader = Zeitwerk::Loader.new
...
loader.setup

위의 코드는 로더 인스턴스를 인스턴스화하고 setup을 호출합니다. . setup 호출 후 , 로더가 코드를 로드할 준비가 되었습니다. 그러나 그 전에 loader에 필요한 모든 구성이 이미 덮여 있어야합니다. 이 기사에서는 loader의 몇 가지 구성을 다룰 것입니다. 및 코드 구조화 규칙.

  • 파일 구조:Zeitwerk가 작동하려면 파일 및 디렉토리 이름이 정의한 모듈 및 클래스 이름과 일치해야 합니다. 예를 들어,
  lib/my_gem.rb         -> MyGem
  lib/my_gem/foo.rb     -> MyGem::Foo
  lib/my_gem/bar_baz.rb -> MyGem::BarBaz
  lib/my_gem/woo/zoo.rb -> MyGem::Woo::Zoo
  • 루트 네임스페이스:루트 네임스페이스는 Zeitwerk 당신의 코드를 찾을 수 있습니다. modules일 때 및 classes 참조되는 경우 Zeitwerk는 일치하는 파일 이름으로 루트 네임스페이스를 검색하는 것을 알고 있습니다. 예를 들어,
  require 'zeitwerk'
  loader = Zeitwerk::Loader.new
  loader.push_dir("app/models")
  loader.push_dir("app/controllers")

  // matches as follows
  app/models/user.rb                        -> User
  app/controllers/admin/users_controller.rb -> Admin::UsersController

두 가지 사용 사례에 대해 루트 네임스페이스를 정의하는 두 가지 기본 방법이 있습니다. 기본 방법은 다음과 같습니다.

  // init.rb
  require 'zeitwerk'
  loader = Zeitwerk::Loader.new
  loader.push_dir("#{__dir__}/bar")
  ...
  loader.setup

  // bar/foo.rb
  class Foo; end

이것은 Foo 클래스를 의미합니다. 명시적인 Bar::Foo 없이 참조할 수 있습니다. , bar 디렉토리가 루트 네임스페이스 역할을 하기 때문입니다. 네임스페이스를 정의하는 두 번째 방법은 push_dir 호출에서 네임스페이스를 명시적으로 지정하는 것입니다. :

  // init.rb
  require 'zeitwerk'

  module Bar
  end
  loader = Zeitwerk::Loader.new
  loader.push_dir("#{__dir__}/src", namespace: Bar)
  loader.setup

  // src/foo.rb
  class Bar::Foo; end

이 코드에서 주의해야 할 몇 가지 사항이 있습니다.

  1. 모듈 Bar push_dir에서 사용하기 전에 이미 정의되었습니다. . 사용하려는 모듈이 타사에 의해 정의된 경우 push_dir 호출에서 사용하기 전에 간단한 require가 모듈을 정의합니다. .
  2. push_dir 명시적으로 네임스페이스 Bar를 지정합니다. .
  3. 파일 src/foo.rb 정의된 Bar::Foo Foo가 아닌 , 그리고 src/bar/foo.rb와 같은 디렉토리를 생성할 필요가 없었습니다. .
  • 독립 코드 로더:설계상 Zeitwerk를 사용하면 각 프로젝트 또는 앱 종속성이 개별 프로젝트 트리를 관리할 수 있습니다. 이는 각 종속성의 코드 로딩 메커니즘이 해당 종속성에 의해 관리됨을 의미합니다. 예를 들어, Rails 6에서 Zeitwerk는 Rails 앱에 대한 코드 로드를 처리하고 각 gem 종속성이 자체 프로젝트 트리를 개별적으로 관리할 수 있도록 합니다. 여러 코드 로더 간에 파일이 겹치는 것은 오류 조건입니다.

  • 자동 로드:위의 설정으로 setup을 호출하면 모든 클래스와 모듈은 주문형으로 제공될 것입니다.

  • 다시 로드:다시 로드를 활성화하려면 loader 명시적으로 구성해야 합니다. 예를 들어,

  loader = Zeitwerk::Loader.new
  ...
  loader.enable_reloading # you need to opt-in before setup
  loader.setup
  ...
  loader.reload

loader.reload 호출은 프로젝트 트리를 즉석에서 다시 로드하고 모든 새로운 변경 사항을 즉시 볼 수 있습니다. 그러나 파일 시스템의 변경 사항을 감지하고 loader.reload를 호출하기 위한 주변 메커니즘이 여전히 필요합니다. . 간단한 버전은 다음과 같습니다.

  require 'filewatcher'

  loader = Zeitwerk::Loader.new
  ...
  loader.enable_reloading
  loader.setup
  ...

  my_filewatcher = Filewatcher.new('lib/')
  Thread.new(my_filewatcher) {|fw| fw.watch {|filename| loader.reload } }

Rails에서 Zeitwerk 사용

Zeitwerk는 Rails 6.0에서 기본적으로 활성화되어 있습니다. 그러나 선택 해제하고 Rails classic을 사용할 수 있습니다. 코드 로더.

# config/application.rb
config.load_defaults "6.0"
config.autoloader = :classic

보석에서 Zeitwerk 사용

Zeitwerk는 표준 gem 구조(lib/special_gem ). 이 편리한 방법은 다음과 같이 사용할 수 있습니다.

# lib/special_gem.rb
require 'zeitwerk'

module SpecialGem
end

loader = Zeitwerk::Loader.for_gem
loader.setup

표준 gem 구조를 사용하면 for_gem 호출은 lib를 추가합니다. 디렉토리를 루트 네임스페이스로 사용하여 lib의 모든 코드 활성화 디렉토리를 자동으로 찾습니다.

더 많은 영감을 얻으려면 Zeitwerk를 사용하여 보석을 확인하십시오.

  • 카라프카
  • 제트기

참조

Rails 자동 로딩 — 작동 방식 및 작동하지 않는 경우

자이트베르크