Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

URI.join이 직관적이지 않은 이유는 무엇입니까?

우리는 여기 Honeybadge에서 이정표에 도달했습니다. 판매 페이지는 더 이상 주요 Rails 앱의 일부가 아닙니다. 몇 년 동안 제 위시리스트에 있었지만 정확히 최우선 순위는 아니었습니다.

이 마이그레이션의 일환으로 URI.join을 사용하고 있습니다. 특정 리디렉션 링크를 구성합니다. 그러나 나는 곧 문제에 봉착했다. URI.join 예상대로 작동하지 않았습니다.

다음과 같이 많은 경로 조각을 가져와서 함께 묶을 것으로 예상했습니다.

# This is what I was expecting. It didn't happen.
URI.join("https://www.honeybadger.io", "plans", "change")
=> "https://www.honeybadger.io/plans/change"

join 방법이 훨씬 낯설었습니다. 마지막 하나인 "변경"만 사용하여 내 경로 조각 중 하나를 삭제했습니다.

# This is what happened.
URI.join("https://www.honeybadger.io", "plans", "change")
=> "https://www.honeybadger.io/change"

그렇다면 왜 이런 식으로 작동합니까?

오해

URI.join을 기대했던 것으로 나타났습니다. Array#join의 특수 버전과 유사하게 동작 , URL 조각을 가져와 결합하여 전체 URL을 만듭니다.

그것은 그것이 하는 일이 아닙니다. 큰 놀라움.

join을 살펴보면 메서드의 코드를 보면 모든 인수를 반복하고 merge를 호출합니다. 각각에.

# File uri/rfc2396_parser.rb, line 236
def join(*uris)
  uris[0] = convert_to_uri(uris[0])
  uris.inject :merge
end

병합 방법은 다음 두 가지 작업을 수행합니다.

  1. "페이지"와 같은 문자열을 상대 URI 개체로 변환합니다.
  2. 기본 URI에 대한 상대 URI를 확인하려고 시도합니다. RFC2396, 섹션 5.2에 지정된 방식으로 정확히 이 작업을 수행합니다.

멋지네요. 그런데 제가 앞서 언급한 예상치 못한 행동을 어떻게 설명하나요?

URI.join("https://www.honeybadger.io", "plans", "change")
=> "https://www.honeybadger.io/change"

단계별로 살펴보겠습니다. 위의 코드는 다음과 같습니다.

URI.parse("https://www.honeybadger.io/plans").merge("change")

위의 코드는 절대 URI "https://www.honeybadger.io/plans"에 대해 상대 URI "변경"을 해결하려고 시도합니다.

이렇게 하려면 RFC2396, 섹션 5.2.6을 따르며 다음과 같이 명시되어 있습니다.

<블록 인용>

a) 기본 URI 경로 구성 요소의 마지막 세그먼트를 제외한 모든 부분이 버퍼에 복사됩니다. 즉, 마지막(가장 오른쪽) 슬래시 문자(있는 경우) 이후의 모든 문자는 제외됩니다.

b) 참조의 경로 구성 요소가 버퍼 문자열에 추가됩니다.

같이 놀자:

  1. 절대 URL의 마지막 부분을 제외한 모든 것을 복사합니다. "https://www.honeybadger.io/"를 제공합니다.
  2. 상대 경로를 추가하면 "https://www.honeybadger.io/change"가 됩니다.

세상이 다시 이해가 됩니다!

결론

동안 URI.join 다양한 경로 조각에서 URL을 빌드하는 데 사용할 수 있지만 실제로는 그렇게 하도록 설계된 것이 아닙니다. RFC에 지정된 표준에 따라 URI를 재귀적으로 병합하는 좀 더 복잡한 작업을 수행하도록 설계되었습니다.

새 판매 페이지로 리디렉션하는 데 사용할 URL을 구축하는 개인 프로젝트의 경우 Array#join을 대신 사용했습니다. :)

2016년 8월 12일 수정: 이 기사를 게시한 후 File.join 사용을 제안하는 몇 개의 트윗을 받았습니다. 이 목적을 위해. 이것은 이중 슬래시를 피하는 이점이 있습니다. /my//path 그러나 경로 구분 기호가 슬래시가 아닌 Windows와 같은 OS에서는 중단됩니다.