Programming

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

procodes 2020. 6. 8. 21:21
반응형

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이미 존재 하는지 확인하고 , 존재하는 경우 이전과 같이 진행하십시오.
  • require File.join(File.dirname(__FILE__), 'path/to/file')
    루비 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.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')

Use backports gem - it's kind of heavy, it requires rubygems infrastructure and includes tons of other workarounds, while I just want require to work with relative files.

You have already answered why these are not the best options.

check if RUBY_VERSION < 1.9.2, then define require_relative as require, use require_relative everywhere where it's needed afterwards

check if require_relative already exists, if it does, try to proceed as in previous case

This may work, but there's safer and quicker way: to deal with the LoadError exception:

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

I'm a fan of using the rbx-require-relative gem (source). It was originally written for Rubinius, but it also supports MRI 1.8.7 and does nothing in 1.9.2. Requiring a gem is simple, and I don't have to throw code snippets into my project.

Add it to your Gemfile:

gem "rbx-require-relative"

Then require 'require_relative' before you require_relative.

For example, one of my test files looks like this:

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

This is the cleanest solution out of any of these IMO, and the gem isn't as heavy as backports.


The backports gem now allows individual loading of backports.

You could then simply:

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

This require will not affect newer versions, nor will it update any other builtin methods.


Another option is to tell the interpreter which paths to search

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

One issue I've not seen pointed out with the solutions based on __FILE__ is that they break with regards to symlinks. For example say I have:

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

The main script, the entry point, the application is foo.rb. This file is linked to ~/Scripts/foo which is in my $PATH. This require statement is broken when I execute 'foo':

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

Because __FILE__ is ~/Scripts/foo so the require statement above looks for ~/Scripts/foo/lib/someinclude.rb which obviously doesn't exist. The solution is simple. If __FILE__ is a symbolic link it needs to be dereferenced. Pathname#realpath will help us with this situation:

require "pathname"
require File.join(File.dirname(Pathname.new(__FILE__).realpath), "lib/someinclude")

If you were building a gem, you would not want to pollute the load path.

But, In the case of a standalone application it is very convenient to just add the current directory to the load path as you do in the first 2 examples.

My vote goes to the first option on the list.

I would love to see some solid Ruby best practices literature.


I would define my own relative_require if it doesn't exist (i.e. under 1.8) and then use the same syntax everywhere.


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

반응형