$ LOAD_PATH (Ruby)에 디렉토리 추가 데 일반적으로 사용되는 두 가지

현재 실행중인 파일의 디렉토리를 $ LOAD_PATH (또는 $ :)에 추가하는 데 일반적으로 사용되는 두 가지 기술을 보았습니다. gem을 사용하지 않는 경우이 작업의 장점을 확인했습니다. 하나는 다른 것보다 더 장황 해 보이지만, 다른 하나와 함께 갈 이유가 있습니까?

첫 번째, 장황한 방법 (과도 할 수 있음) :

$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))

더 간단하고 빠르고 더럽습니다.

$:.unshift File.dirname(__FILE__)

다른 하나와 함께 갈 이유가 있습니까?



답변

나는 $:.unshift File.dirname(__FILE__)다른 것보다 코드에서 더 많이 사용하는 것을 보았 기 때문에 다른 것보다 가라고 말할 것입니다 $LOAD_PATH.


답변

Ruby로드 경로는 일반적으로 $ :로 작성되는 것으로 보이지만 짧다고해서 더 나아지지는 않습니다. 영리함보다 명료 함을 선호하거나 그 자체로 간결함이 당신을 가렵 게 만든다면, 다른 모든 사람들이 그렇다고해서 그렇게 할 필요는 없습니다. 인사 …

$LOAD_PATH

… 그리고 작별 인사를 …

# I don't quite understand what this is doing...
$:


답변

나는 ‘빠르고 더러운’방식을 너무 좋아하지 않습니다. 루비를 처음 접하는 사람이라면 누구나 무엇을 고민 할 것 $:.입니다.

나는 이것이 더 분명하다고 생각합니다.

libdir = File.dirname(__FILE__)
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)

또는 내가 전체 경로에 관심이 있다면 …

libdir = File.expand_path(File.dirname(__FILE__))
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)

업데이트 2009/09/10

늦게 나는 다음을하고있다 :

$:.unshift(File.expand_path(File.dirname(__FILE__))) unless
    $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))

나는 GitHub를 탐색하는 동안 여러 루비 프로젝트에서 그것을 보았다.

컨벤션 인 것 같습니까?


답변

당신이 입력하면 script/console레일스 프로젝트를 입력 $:, 당신은 루비를로드하는 데 필요한 모든 디렉토리를 포함하는 배열을 얻을 것이다. 이 작은 연습에서 빼놓을 수없는 것은 그것이 $:배열이라는 것입니다. 따라서 다른 디렉토리 앞에 unshift메서드 나 <<연산자를 추가하는 것과 같은 기능을 수행 할 수 있습니다 . 당신은 당신의 문에 묵시적으로 $:$LOAD_PATH동일합니다.

앞서 언급했듯이 빠르고 더러운 방식으로 수행 할 때의 단점은 다음과 같습니다. 부팅 경로에 이미 디렉토리가있는 경우 자체적으로 반복됩니다.

예:

내가 만든 todo라는 플러그인이 있습니다. 내 디렉토리는 다음과 같이 구성됩니다.

/ --- 공급 업체
  |
  | --- / 플러그인
        |
        | --- / 할일
              |
              | --- / lib
                    |
                    | --- / 앱
                          |
                          | --- / 모델
                          | --- / 컨트롤러
              |
              | --- / 레일
                    |
                    | --- init.rb

init.rb 파일에 다음 코드를 입력했습니다.

## In vendor/plugins/todo/rails/init.rb
    %w{ models controllers models }.each do |dir|
      path = File.expand_path(File.join(File.dirname(__FILE__), '../lib', 'app', dir))
      $LOAD_PATH << path
      ActiveSupport::Dependencies.load_paths << path
      ActiveSupport::Dependencies.load_once_paths.delete(path)
    end 

코드 블록이 ‘models’, ‘controllers’, ‘models’문자열에 대해 블록 내부의 작업을 수행하도록 지시하는 방법에 유의하십시오. 여기서 ‘models’를 반복합니다. (참고로 %w{ ... }Ruby가 문자열 배열을 보유하도록 지시하는 또 다른 방법입니다.) 를 실행할 때 script/console다음을 입력합니다.

>> puts $:

문자열의 내용을 더 쉽게 읽을 수 있도록 입력합니다. 내가 얻는 출력은 다음과 같습니다.

...
...
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/controllers
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models

보시다시피 이것은 제가 현재 작업중인 프로젝트를 사용하는 동안 만들 수있는 간단한 예제이지만,주의하지 않으면 빠르고 더러운 방법은 반복되는 경로로 이어질 것입니다. 더 긴 방법은 반복되는 경로를 확인하고 발생하지 않는지 확인합니다.

숙련 된 Rails 프로그래머라면 현재 수행중인 작업에 대해 매우 잘 알고있을 것이며 경로를 반복하는 실수를하지 않을 것입니다. 당신이 초보자라면 당신이하는 일을 정말로 이해할 때까지 더 긴 길을 갈 것입니다.


답변

Rspec을 사용할 때 상대 경로를 통해 dir을 추가하는 것이 가장 좋습니다. 나는 그것이 충분히 장황하지만 여전히 좋은 라이너라고 생각합니다.

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))


답변

더 멋지고 깨끗한 코드로로드 경로를 설정할 수있는 gem이 있습니다. https://github.com/nayyara-samuel/load-path를 확인 하십시오 .

또한 좋은 문서가 있습니다.


답변

이 질문이 처음 제기 된 지 오래되었지만 공유하고 싶은 추가 답변이 있습니다.

몇 년에 걸쳐 다른 프로그래머가 개발 한 Ruby 애플리케이션이 여러 개 있으며 동일한 데이터베이스에 액세스 할 수 있지만 다른 애플리케이션에서 동일한 클래스를 재사용합니다. 이것은 DRY 규칙을 위반하기 때문에 모든 Ruby 애플리케이션에서 공유 할 클래스 라이브러리를 만들기로 결정했습니다. 메인 루비 라이브러리에 넣을 수는 있었지만 원하지 않는 공통 코드베이스에 커스텀 코드를 숨길 수있었습니다.

이미 정의 된 이름 “profile.rb”와 내가 사용중인 클래스간에 이름 충돌이 발생하는 문제가있었습니다. 이 충돌은 공통 코드 라이브러리를 만들 때까지 문제가되지 않았습니다. 일반적으로 Ruby는 먼저 애플리케이션 위치를 검색 한 다음 $ LOAD_PATH 위치로 이동합니다.

application_controller.rb는 내가 만든 클래스를 찾을 수 없으며 클래스가 아니기 때문에 원래 정의에 오류가 발생했습니다. 애플리케이션의 app / models 섹션에서 클래스 정의를 제거했기 때문에 Ruby가 거기에서 찾을 수 없었고 Ruby 경로에서 찾아 보았습니다.

그래서 사용하고 있던 라이브러리 디렉토리의 경로를 포함하도록 $ LOAD_PATH 변수를 수정했습니다. 초기화시 environment.rb 파일에서 수행 할 수 있습니다.

검색 경로에 새 디렉토리가 추가 된 경우에도 Ruby는 우선적으로 시스템 정의 파일을 먼저 가져 오기 때문에 오류가 발생했습니다. $ LOAD_PATH 변수의 검색 경로는 먼저 Ruby 경로를 우선적으로 검색합니다.

그래서 Ruby가 내장 라이브러리를 검색하기 전에 공통 라이브러리에서 클래스를 찾을 수 있도록 검색 순서를 변경해야했습니다.

이 코드는 environment.rb 파일에서 수행했습니다.

Rails::Initializer.run do |config|

* * * * *

path = []
path.concat($LOAD_PATH)
$LOAD_PATH.clear
$LOAD_PATH << 'C:\web\common\lib'
$LOAD_PATH << 'C:\web\common'
$LOAD_PATH.concat(path)

* * * * *

end

이 수준에서 이전에 제공된 고급 코딩 구조를 사용할 수 없다고 생각하지만 앱에서 초기화 시간에 무언가를 설정하려는 경우 잘 작동합니다. 새 변수에 다시 추가 될 때 원래 $ LOAD_PATH 변수의 원래 순서를 유지해야합니다. 그렇지 않으면 일부 주요 Ruby 클래스가 손실됩니다.

application_controller.rb 파일에서 간단히

require 'profile'
require 'etc' #etc

그리고 이것은 전체 애플리케이션에 대한 사용자 정의 라이브러리 파일을로드합니다. 즉, 모든 컨트롤러에서 require 명령을 사용할 필요가 없습니다.

저에게는 이것이 제가 찾고 있던 해결책이었고 정보를 전달하기 위해이 답변에 추가 할 것이라고 생각했습니다.