IT story

$ LOAD_PATH (Ruby)에 디렉토리 추가

hot-time 2020. 9. 6. 12:01
반응형

$ 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

As you can see, though this is as simple an example I could create while using a project I'm currently working on, if you're not careful the quick and dirty way will lead to repeated paths. The longer way will check for repeated paths and make sure they don't occur.

If you're an experienced Rails programmer, you probably have a very good idea of what you're doing and likely not make the mistake of repeating paths. If you're a newbie, I would go with the longer way until you understand really what you're doing.


Best I have come across for adding a dir via relative path when using Rspec. I find it verbose enough but also still a nice one liner.

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

There is a gem which will let you setup your load path with nicer and cleaner code. Check this out: https://github.com/nayyara-samuel/load-path.

It also has good documentation


I know it's been a long time since this question was first asked, but I have an additional answer that I want to share.

I have several Ruby applications that were developed by another programmer over several years, and they re-use the same classes in the different applications although they might access the same database. Since this violates the DRY rule, I decided to create a class library to be shared by all of the Ruby applications. I could have put it in the main Ruby library, but that would hide custom code in the common codebase which I didn't want to do.

I had a problem where I had a name conflict between an already defined name "profile.rb", and a class I was using. This conflict wasn't a problem until I tried to create the common code library. Normally, Ruby searches application locations first, then goes to the $LOAD_PATH locations.

The application_controller.rb could not find the class I created, and threw an error on the original definition because it is not a class. Since I removed the class definition from the app/models section of the application, Ruby could not find it there and went looking for it in the Ruby paths.

So, I modified the $LOAD_PATH variable to include a path to the library directory I was using. This can be done in the environment.rb file at initialization time.

Even with the new directory added to the search path, Ruby was throwing an error because it was preferentially taking the system-defined file first. The search path in the $LOAD_PATH variable preferentially searches the Ruby paths first.

So, I needed to change the search order so that Ruby found the class in my common library before it searched the built-in libraries.

This code did it in the environment.rb file:

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

I don't think you can use any of the advanced coding constructs given before at this level, but it works just fine if you want to setup something at initialization time in your app. You must maintain the original order of the original $LOAD_PATH variable when it is added back to the new variable otherwise some of the main Ruby classes get lost.

In the application_controller.rb file, I simply use a

require 'profile'
require 'etc' #etc

and this loads the custom library files for the entire application, i.e., I don't have to use require commands in every controller.

For me, this was the solution I was looking for, and I thought I would add it to this answer to pass the information along.

참고URL : https://stackoverflow.com/questions/837123/adding-a-directory-to-load-path-ruby

반응형