programing

Ruby: require vs require_require_require - Ruby < 1.9.2 및 >= 1.9.2에서 실행되는 문제를 해결하기 위한 모범 사례

padding 2023. 6. 2. 20:13
반응형

Ruby: require vs require_require_require - 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하는 경우. 존재하는 경우 이전 사례와 같이 진행해 보십시오.
  • 와 같은 이상한 구조를 사용합니다.
    require File.join(File.dirname(__FILE__), 'path/to/file')
    Ruby 1.9에서 완전히 작동하지 않는 것 같습니다. 예를 들어, 다음과 같은 이유가 있습니다.
    $ 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 1과 12의 루비 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 " 열을구할것입다니성문자다▁the▁string"를 생성합니다./absolute/path/to/file.rb/../relative/path에 '아니다', '아니다', '아니다', '아니다' ... 구성요소를 .file.rb), 이경우, 반환을 반환합니다./absolute/path/to/relative/path.

이게 최선의 방법입니까?무슨 뜻인지에 따라 다르지만, 레일즈 코드 베이스에 온통 깔려 있는 것 같아서 적어도 충분히 일반적인 관용구라고 생각합니다.

곡괭이에는 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

기본적으로 테오가 대답한 것만 사용하지만 그래도 사용할 수 있습니다.require_relative.

$LOAD_PATH << '.'

$LOAD_PATH << File.dirname(__FILE__)

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

require './path/to/file'

루비_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')

백포트 보석을 사용합니다. 루비젬 인프라가 필요하고 다른 해결 방법도 많이 포함되어 있지만, 저는 상대적인 파일로 작업하기를 원합니다.

이러한 옵션이 최선의 옵션이 아닌 이유에 대해 이미 답변하셨습니다.

RUBY_VERSION < 1.9.2인지 확인한 다음 require_relative를 필요에 따라 정의하고 이후 필요한 모든 곳에서 require_relative를 사용합니다.

require_message가 이미 있는지 확인하고, 이미 있으면 이전 사례와 같이 진행해 보십시오.

이 방법이 효과적일 수도 있지만 로드 오류 예외를 처리하는 더 안전하고 빠른 방법이 있습니다.

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(소스)을 사용하는 것을 좋아합니다.원래 루비니우스를 위해 작성되었지만 MRI 1.8.7도 지원하며 1.9.2에서는 아무것도 수행하지 않습니다.보석을 요구하는 것은 간단하며, 제 프로젝트에 코드 스니펫을 던질 필요가 없습니다.

Gem 파일에 추가:

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

이제 보석을 통해 백포트를 개별적으로 로드할 수 있습니다.

그러면 간단하게 다음을 수행할 수 있습니다.

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

__FILE_을 기반으로 한 솔루션에서 제가 지적하지 않은 한 가지 문제는 심볼릭 링크와 관련하여 중단된다는 것입니다.예를 들어 다음과 같이 가정합니다.

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

메인 스크립트, 진입점, 응용 프로그램은 foo.rb입니다.이 파일은 내 $PATH에 있는 ~/스크립트/foo에 연결되어 있습니다.이 require 문은 'foo'를 실행하면 깨집니다.

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

__FILE__이 ~/Scripts/foo이므로 위의 require 문은 ~/Scripts/foo/lib/some include.rb를 찾습니다.해결책은 간단합니다.__FILE__이(가) 심볼 링크인 경우 이 링크를 참조 취소해야 합니다.pathname#realpath는 다음과 같은 상황을 해결하는 데 도움이 됩니다.

경로 이름 필요File.join(File.dirname(Pathname.new(__FILE__).realpath), "lib/some include")가 필요합니다.

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

그러나 독립 실행형 응용 프로그램의 경우 처음 두 예에서와 같이 현재 디렉터리를 로드 경로에 추가하면 매우 편리합니다.

저의 투표는 목록의 첫 번째 선택지로 갑니다.

저는 탄탄한 루비 베스트 프랙티스 문헌을 보고 싶습니다.

나는 나 자신을 정의할 것입니다.relative_require존재하지 않는 경우(예: 1.8 이하), 모든 곳에서 동일한 구문을 사용합니다.

Ruby on Rails way:

config_path = File.expand_path("../config.yml", __FILE__)

언급URL : https://stackoverflow.com/questions/4333286/ruby-require-vs-require-relative-best-practice-to-workaround-running-in-both

반응형