Есть ли библиотека / гем Ruby, которая будет генерировать URL-адрес на основе набора параметров?

Механизм генерации URL-адресов Rails (большинство из которых в какой-то момент проходит через polymorphic_url) позволяет передавать хэш, который сериализуется в строку запроса, по крайней мере, для запросов GET. Как лучше всего получить такую ​​функциональность, но поверх любого базового пути?

Например, хотелось бы иметь что-то вроде следующего:

generate_url('http://www.google.com/', :q => 'hello world')
  # => 'http://www.google.com/?q=hello+world'

Я, конечно, мог бы написать свой собственный, который строго соответствует требованиям моего приложения, но если бы существовала какая-то каноническая библиотека для этого, я бы предпочел ее использовать :).


person Steven    schedule 27.05.2011    source источник


Ответы (4)


Да, в стандартной библиотеке Ruby вы найдете целый модуль классов для работы с URI. Есть один для HTTP. Вы можете вызвать #build с некоторыми аргументами, как вы показали.

http://www.ruby-doc.org/stdlib/libdoc/uri/rdoc/classes/URI/HTTP.html#M009497.

Для самой строки запроса просто используйте добавление хэша Rails #to_query. т.е.

uri = URI::HTTP.build(:host => "www.google.com", :query => { :q => "test" }.to_query)
person d11wtq    schedule 27.05.2011
comment
Чудесно! Я не могу сказать, что когда-либо видел модуль URI раньше, так что это супер круто. - person Steven; 27.05.2011
comment
@Nakilon, какую версию Rails вы используете? - person d11wtq; 30.04.2013
comment
это работает, только если вы используете рельсы. Есть ли альтернатива, если вы не используете рельсы? - person Stefan Hendriks; 24.06.2013
comment
Используйте CGI.escape для кодирования значений. В остальном все просто. your_hash.map{|k,v| [CGI.escape(k.to_s), "=", CGI.escape(v.to_s)]}.map(&:join).join("&"). - person d11wtq; 25.06.2013
comment
@StefanHendriks Это неправда: модуль URI - это стандартная библиотека Ruby - для него НЕ требуется Rails. Вы должны ввести require 'uri', прежде чем использовать код в этом ответе. В остальном он работает так, как рекламируется. - person Steve Midgley; 06.10.2014
comment
Это не удается, если в одном из поддоменов хоста есть символы подчеркивания. - person l8nite; 30.01.2016
comment
Альтернатива Hash#to_query: URI.encode_www_form - person tokland; 15.02.2016
comment
@SteveMidgley Я пробовал использовать Ruby 2.5.5, но #to_query нет, даже если я сделал require 'uri'. - person Franklin Yu; 06.05.2019
comment
@FranklinYu - вам нужно установить Rails (или, возможно, просто ActiveSupport), чтобы получить этот метод. Я думаю, это то, что вы хотите установить / потребовать: apidock.com/rails/Hash/to_query - person Steve Midgley; 06.05.2019
comment
@SteveMidgley Но 5 лет назад вы сказали, что для этого не требуется Rails? - person Franklin Yu; 06.05.2019
comment
@FranklinYu Я думаю, что ошибся, что to_query - это stdlib. Я обновлю свой ответ, предлагая включить ActiveSupport. Вам не нужно устанавливать Rails - вам просто нужно установить ActiveSupport, который имеет гораздо меньший вес. Кроме того, если вы посмотрите комментарии выше, есть предложение, которое не включает to_query, которое немного сложнее. your_hash.map{|k,v| [CGI.escape(k.to_s), "=", CGI.escape(v.to_s)]}.map(&:join).join("&") - person Steve Midgley; 07.05.2019
comment
@tokland, не могли бы вы написать свой собственный ответ, потому что я не вижу URI.encode_www_form в других ответах, и это кажется правильным решением только со стандартными библиотеками. - person akostadinov; 21.12.2020
comment
@akostadinov: готово - person tokland; 22.12.2020

Поздно к вечеринке, но позвольте мне настоятельно рекомендовать гем Addressable. Помимо других полезных функций, он поддерживает запись и анализ uri с помощью шаблонов URI RFC 6570 . Чтобы адаптировать данный пример, попробуйте:

gsearch = Addressable::Template.new('http://google.com/{?query*}')
gsearch.expand(query: {:q => 'hello world'}).to_s
# => "http://www.google.com/?q=hello%20world"

or

gsearch = Addressable::Template.new('http://www.google.com/{?q}')
gsearch.expand(:q => 'hello world').to_s
# => "http://www.google.com/?q=hello%20world"
person wobh    schedule 06.05.2016
comment
пожалуйста, проверьте этот URL, он будет полезен для повышения качества вашего контента - person Willie Cheng; 06.05.2016
comment
Почистил и добавил примеры. Спасибо, @willie! - person wobh; 07.05.2016
comment
Я заметил, что гем Thor использует Addressable только для Ruby 1.8. Было ли что-то добавлено после этого, чтобы оно больше не понадобилось? - person labyrinth; 04.11.2017


Я бы предложил свой гем iri, который упрощает создание URL-адресов через свободный интерфейс:

require 'iri'
url = Iri.new('http://google.com/')
  .append('find').append('me') # -> http://google.com/find/me
  .add(q: 'books about OOP', limit: 50) # -> ?q=books+about+OOP&limit=50
  .del(:q) # remove this query parameter
  .del('limit') # remove this one too
  .over(q: 'books about tennis', limit: 10) # replace these params
  .scheme('https') # replace 'http' with 'https'
  .host('localhost') # replace the host name
  .port('443') # replace the port
  .path('/new/path') # replace the path of the URI, leaving the query untouched
  .cut('/q') # replace everything after the host and port
  .to_s # convert it to a string
person yegor256    schedule 21.04.2020