Ruby : require vs require_relative-Ruby <1.9.2 및> = 1.9.2에서 실행하는 최상의 방법


153

내가 원하는 경우 가장 좋은 방법이다 require루비에서 상대 파일 나는 모두에 1.8.x 및> = 1.9.2에서 일하고 싶어?

몇 가지 옵션이 있습니다.

  • 그냥 $LOAD_PATH << '.'하고 모든 것을 잊어 버려
  • 하다 $LOAD_PATH << File.dirname(__FILE__)
  • require './path/to/file'
  • RUBY_VERSION<1.9.2 인지 확인한 다음로 정의 require_relative하고 나중에 필요한 곳에 require사용하십시오.require_relative
  • require_relative이미 존재 하는지 확인하고 , 존재하는 경우 이전과 같이 진행하십시오.
  • 루비 1.9에서는 완전히 작동하지 않는 것과 같은 이상한 구조를 사용하십시오 .
    require File.join(File.dirname(__FILE__), 'path/to/file')
    $ cat caller.rb
    require File.join(File.dirname(__FILE__), 'path/to/file')
    $ cat path/to/file.rb
    puts 'Some testing'
    $ ruby caller
    Some testing
    $ pwd
    /tmp
    $ ruby /tmp/caller
    Some testing
    $ ruby tmp/caller
    tmp/caller.rb:1:in 'require': no such file to load -- tmp/path/to/file (LoadError)
        from tmp/caller.rb:1:in '<main>'
  • 더 이상한 구성 : 작동하는 것처럼 보이지만 이상하고보기에는 좋지 않습니다.
    require File.join(File.expand_path(File.dirname(__FILE__)), 'path/to/file')
  • 백 포트 젬 사용 -종류가 무겁고 루비 젬 인프라가 필요하며 다른 해결 방법이 많이 포함되어 있지만 require상대 파일로 작업 하고 싶습니다 .

StackOverflow 에는 더 많은 예제를 제공 하는 밀접한 관련 질문이 있지만 명확한 답변을 제공하지는 않습니다. 이것이 모범 사례입니다.

Ruby <1.9.2 및> = 1.9.2 모두에서 응용 프로그램을 실행할 수있는 괜찮은 수준의 범용 솔루션이 있습니까?

최신 정보

설명 : "X를 할 수있다"와 같은 답을 원치 않습니다. 사실, 문제의 대부분의 선택을 이미 언급했습니다. 내가 원하는 근거 , 즉 이유 는 그것이 다른 사람의 사이에서 선택해야하는 이유 장단점이 있고 어떤 가장 좋은 방법입니다.


3
안녕하세요 누군가가 시작 것 사이의 차이점에서 설명 할 수 requirerequire_relative?
대령 패닉

3
이전 Ruby 1.8에서 파일을 실행 하고 현재 디렉토리에서 a.rb파일의 내용을 읽고 구문 분석 b.rb하도록하려면 (일반적으로와 같은 디렉토리 a.rb) 작성하면 require 'b'됩니다. 현재 디렉토리가 포함 된 기본 검색 경로로 괜찮을 것입니다. 보다 현대적인 Ruby 1.9에서는 표준 라이브러리 경로에서만 검색하는 require_relative 'b'것처럼이 경우 에 작성해야 require 'b'합니다. 제대로 설치되지 않는 간단한 스크립트 (예 : 스크립트 자체 설치 )에 대해서는 일종의 앞뒤 호환성이 있습니다 .
GreyCat

이제 사용할 수 있습니다 backports단지에 대한 require_relative내 대답을 참조 ...
마크 - 앙드레 Lafortune

답변:


64

이것에 대한 해결책은 방금 'aws'보석에 추가 되었으므로이 게시물에서 영감을 얻은 것처럼 공유 할 것이라고 생각했습니다.

https://github.com/appoxy/aws/blob/master/lib/awsbase/require_relative.rb

unless Kernel.respond_to?(:require_relative)
  module Kernel
    def require_relative(path)
      require File.join(File.dirname(caller[0]), path.to_str)
    end
  end
end

이를 통해 require_relative루비 1.8 및 1.9.1의 루비 1.9.2에서와 같이 사용할 수 있습니다 .


3
require_relative.rb 파일은 어떻게 필요합니까? require_relative.rb를 요구 한 다음 require_relative가 나머지 요구 사항을 필요로합니다. 아니면 뭔가 빠졌습니까?
ethicalhack3r

7
require_relative기능은 Ruby 코어 라이브러리의 확장 프로젝트에 포함되어 있습니다. rubyforge.org/projects/extensions 로 설치할 수 있어야합니다 gem install extensions. 그런 다음 코드에서 다음 줄을 추가하십시오 require_relative. require 'extensions / all'(Aurril의 게시물 에서 제공 )
thegreendroid

@ ethicalhack3r은 루비 스크립트 상단에 해당 코드를 복사하여 붙여 넣거나 레일에있는 경우 상단 environment.rb 또는 다른 곳에 넣습니다.
Travis Reeder

46

1.9.2로 점프하기 전에 상대 요구 사항에 다음을 사용했습니다.

require File.expand_path('../relative/path', __FILE__)

처음에 추가 '..'가있는 것처럼 보이기 때문에 처음 볼 때는 조금 이상합니다. 그 이유는 expand_path두 번째 인수를 기준으로 경로를 확장하고 두 번째 인수는 마치 디렉토리 인 것처럼 해석하기 때문입니다. __FILE__분명히 디렉토리 아니지만, 때문에 그 문제가되지 않습니다 expand_path파일이 존재하는 경우 상관하지 않는다 여부, 그냥 같은 일을 확장하는 몇 가지 규칙을 적용합니다 .., .하고 ~. 초기 "기다리는 시간 ..이 없습니까?" 위의 줄은 꽤 잘 작동한다고 생각합니다.

그 가정 __FILE__입니다 /absolute/path/to/file.rb무슨 일하는 즉, expand_path문자열을 구성합니다 /absolute/path/to/file.rb/../relative/path다음 해당 말한다 규칙 적용 ..(그 전에 경로 구성 요소를 제거해야합니다 file.rb반환,이 경우에는) /absolute/path/to/relative/path.

이것이 모범 사례입니까? 그 의미에 따라 다르지만 Rails 코드베이스 전체에있는 것처럼 보이므로 적어도 일반적인 관용구라고 말하고 싶습니다.


1
나는 이것도 일반적으로 본다. 추악하지만 잘 작동하는 것 같습니다.
yfeldblum

12
비트 클리너 : File.expand_path ( 'relative / path', File.dirname ( FILE )) 필요
Yannick Wurm

1
나는 그것이 더 깨끗하다고 ​​생각하지 않습니다. 그것들은 둘 다 지옥처럼 보이지 않으며 두 가지 나쁜 옵션 중에서 선택할 때 나는 타이핑이 덜 필요한 옵션을 선호합니다.
Theo

6
File.expand_path ( '../ relpath.x', File.dirname ( FILE ))은 더 장황하지만 더 나은 관용구 인 것 같습니다. 존재하지 않는 추가 디렉토리가있는 디렉토리 경로로 해석되는 파일 경로의 논란의 여지가있는 기능에 의존하면 해당 기능이 수정 될 때 중단 될 수 있습니다.
jpgeek

1
아마도 깨졌을 수도 있지만 유닉스에서는 영원히 그런 식이었습니다. 경로와 '..'의 해상도와 관련하여 디렉토리와 파일 사이에는 차이가 없습니다. 따라서 디렉토리에서 잠을 잃지 않습니다.
Theo

6

곡괭이에는 1.8의 스 니펫이 있습니다. 여기있어:

def require_relative(relative_feature)
  c = caller.first
  fail "Can't parse #{c}" unless c.rindex(/:\d+(:in `.*')?$/)
  file = $`
  if /\A\((.*)\)/ =~ file # eval, etc.
    raise LoadError, "require_relative is called in #{$1}"
  end
  absolute = File.expand_path(relative_feature, File.dirname(file))
  require absolute
end

기본적으로 Theo가 응답 한 것을 사용하지만 여전히 사용할 수 있습니다 require_relative.


이 스 니펫이 활성화되어 있는지 확인하는 방법은 무엇입니까? 사용 $RUBY_VERSION또는 require_relative직접 존재 여부를 확인 하여 ?
GreyCat

1
항상 오리 유형, require_relative정의되어 있는지 확인하십시오 .
Theo

@ Theo @GreyCat 예, 필요한지 확인합니다. 사람들이 보여줄 수 있도록 스 니펫을 여기에 넣었습니다. 개인적으로, 나는 어쨌든 그렉의 대답을 사용할 것입니다. 누군가가 스스로 그것을 언급하지 않고 언급했기 때문에 실제로 이것을 게시했습니다.
Paul Hoffer

6
$LOAD_PATH << '.'

$LOAD_PATH << File.dirname(__FILE__)

좋은 보안 습관은 아닙니다. 왜 전체 디렉토리를 공개해야합니까?

require './path/to/file'

RUBY_VERSION <1.9.2 인 경우 작동하지 않습니다

이상한 구조물을 사용하십시오

require File.join(File.dirname(__FILE__), 'path/to/file')

더 이상한 구성 :

require File.join(File.expand_path(File.dirname(__FILE__)), 'path/to/file')

backports gem 사용-종류가 무겁고 rubygems 인프라가 필요하며 수많은 다른 해결 방법이 포함되어 있지만 상대 파일로 작업해야합니다.

왜 이것이 최선의 선택이 아닌지에 대답했습니다.

RUBY_VERSION <1.9.2인지 확인한 다음 require_relative를 require로 정의하고 나중에 필요한 곳 ​​어디에서나 require_relative를 사용하십시오.

require_relative가 이미 존재하는지 확인하십시오 (존재하는 경우).

이것은 작동 할 수 있지만 LoadError 예외를 처리하는 더 안전하고 빠른 방법이 있습니다.

begin
  # require statements for 1.9.2 and above, such as:
  require "./path/to/file"
  # or
  require_local "path/to/file"
rescue LoadError
  # require statements other versions:
  require "path/to/file"
end

5

rbx-require-relative gem ( source ) 을 사용하는 팬입니다 . 원래 Rubinius 용으로 작성되었지만 MRI 1.8.7도 지원하며 1.9.2에서는 아무 것도 수행하지 않습니다. 보석을 요구하는 것은 간단하며 프로젝트에 코드 스 니펫을 넣을 필요가 없습니다.

Gemfile에 추가하십시오 :

gem "rbx-require-relative"

그럼 require 'require_relative'당신이하기 전에 require_relative.

예를 들어, 테스트 파일 중 하나는 다음과 같습니다.

require 'rubygems'
require 'bundler/setup'
require 'minitest/autorun'
require 'require_relative'
require_relative '../lib/foo'

이것은 이러한 IMO 중 가장 깨끗한 솔루션이며 보석은 백 포트만큼 무겁지 않습니다.


4

backports보석은 지금은 백 포트의 개별로드 할 수 있습니다.

그런 다음 간단히

require 'backports/1.9.1/kernel/require_relative'
# => Now require_relative works for all versions of Ruby

이것은 require최신 버전에는 영향을 미치지 않으며 다른 내장 메소드도 업데이트하지 않습니다.


3

또 다른 옵션은 통역사에게 검색 할 경로를 알려주는 것입니다

ruby -I /path/to/my/project caller.rb

3

__FILE__ 기반 솔루션에서 지적하지 않은 한 가지 문제는 심볼릭 링크와 관련하여 중단된다는 것입니다. 예를 들어 내가 가지고 있다고 말합니다.

~/Projects/MyProject/foo.rb
~/Projects/MyProject/lib/someinclude.rb

기본 스크립트, 진입 점, 응용 프로그램은 foo.rb입니다. 이 파일은 $ PATH에있는 ~ / Scripts / foo에 연결되어 있습니다. 'foo'를 실행할 때이 require 문이 손상되었습니다.

require File.join(File.dirname(__FILE__), "lib/someinclude")

__FILE__이 ~ / Scripts / foo이므로 위의 require 문은 분명히 존재하지 않는 ~ / Scripts / foo / lib / someinclude.rb를 찾습니다. 해결책은 간단합니다. __FILE__이 심볼릭 링크 인 경우 역 참조해야합니다. Pathname # realpath가이 상황에 도움이됩니다.

"경로 이름"이 필요합니다
File.join (File.dirname (Pathname.new (__ FILE __). realpath), "lib / someinclude")이 필요합니다.

2

보석을 만들고 있다면, 적재 경로를 오염시키고 싶지 않을 것입니다.

그러나 독립형 애플리케이션의 경우 처음 두 예제에서와 같이 현재 디렉토리를로드 경로에 추가하는 것이 매우 편리합니다.

투표는 목록의 첫 번째 옵션으로갑니다.

루비 모범 사례 문헌을보고 싶습니다.


1
Re : "저는 견고한 루비 모범 사례 문헌을보고 싶습니다." Gregory Brown의 Ruby Best Practices를 다운로드 할 수 있습니다 . Rails Best Practices 사이트를 확인할 수도 있습니다 .
마이클 스토커

1

relative_require존재하지 않으면 (즉 1.8 미만) 내 자신을 정의 한 다음 모든 곳에서 동일한 구문을 사용하십시오.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.