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

내가 원하는 경우 가장 좋은 방법이다 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를 할 수있다”와 같은 답을 원치 않습니다. 사실, 문제의 대부분의 선택을 이미 언급했습니다. 내가 원하는 근거 , 즉 이유 는 그것이 다른 사람의 사이에서 선택해야하는 이유 장단점이 있고 어떤 가장 좋은 방법입니다.



답변

이것에 대한 해결책은 방금 ‘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에서와 같이 사용할 수 있습니다 .


답변

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.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.


답변

$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


답변

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 중 가장 깨끗한 솔루션이며 보석은 백 포트만큼 무겁지 않습니다.


답변

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

그런 다음 간단히

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

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


답변

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

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