Rails url helper не кодирует амперсанды - PullRequest
11 голосов
/ 09 декабря 2010

Поэтому я пытаюсь использовать вспомогательный URL-адрес Rails (page_url) для создания URL-адресов, содержащих специальные символы, включая амперсанды. Большинство случаев работают так, как вы ожидаете:

(rdb:1) page_url('foo', :host => 'host')
"http://host/pages/foo"
(rdb:1) page_url('foo_%_bar', :host => 'host')
"http://host/pages/foo_%25_bar"

Но по какой-то странной причине амперсанды не спасаются:

(rdb:1) page_url('foo_&_bar', :host => 'host')
"http://host/pages/foo_&_bar"

И если я их заранее спасу, они испортятся:

(rdb:1) page_url('foo_%26_bar', :host => 'host')
"http://host/pages/foo_%2526_bar"

CGI::escape, с другой стороны, прекрасно их избегает:

(rdb:1) CGI::escape('foo_&_bar')
"foo_%26_bar"

Что происходит, и как мне обойти это? (С чем-то более приятным, чем gsub('&', '%26'), то есть.)

Ответы [ 2 ]

15 голосов
/ 22 марта 2011

Я не могу сказать вам более хороший способ справиться с этим - но я могу объяснить, почему это происходит.

Амперсанды не являются недействительными символами для URL. В противном случае у вас возникнут проблемы с: "http://host/pages/foo?bar=baz&style=foo_style" или чем-то другим.

Edit: Углубившись в исходный код, похоже, что Rails использует CGI.escape только для параметров.

Помощник, генераторы url используют url_for (под обложками), который в итоге вызывает: http://apidock.com/rails/ActionController/Routing/Route/generate Который вызывает вещи глубоко в sprivate-методах исходного кода ... но в конечном итоге вызывает CGI.escape (сначала посмотрите в actionpack / lib / action_controller / routing / route.rb, затем в actionpack / lib / action_controller / routing / сегменты.rb)

Конечным результатом является то, что на самом URL-адресе rails использует URI.escape, который вообще не обновляет амперсанды:

>> CGI.escape('/my_foo_&_bar')
=> "%2Fmy_foo_%26_bar"
>> URI.escape('/my_foo_&_bar')
=> "/my_foo_&_bar"

В настоящее время вы ничего не можете с этим поделать, не направив фактический запрос на добавление команды rails.

... если у вас нет возможности отказаться от использования амперсандов в своих URL-адресах Вы всегда можете распаковать их самостоятельно для всех URL:

def my_clean_url(the_url)
   return the_url.gsub(/&/,'_')
end
>> my_clean_url('/my_foo_&_bar')
=> "/my_foo___bar"

page_url(my_clean_url('/my_foo_&_bar'))
9 голосов
/ 22 сентября 2016

Для всех тех, кто пытается просто кодировать что-либо, кроме a-z, A-Z, 0-9 и подчеркивания:

URI.encode(string, /\W/)

Скажем, у вас есть контент, который может содержать, например, амперсанды, и вы хотите использовать это содержимое в качестве параметра body для ссылки mailto: без /\W/ амперсанд (который является безопасным символом URI) не будет закодирован и, следовательно, будет частично разорван.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...