Передавать URL-адреса в качестве параметров в Rails

#ruby-on-rails

#ruby-on-rails

Вопрос:

Это немного странно.

У меня есть маршрут:

 match "program/:program_id" => "program#details"
  

При вызове этого все работает:

 /program/1
  

Однако идентификаторы программ, которые я использую, — это не только цифры. На самом деле это URL-адреса, подобные so: crid://blah.com/d1e5

Как я могу передать URL-адрес с помощью RESTful-подхода в качестве параметра?

Очевидно, что вызов этого не работает:

 /program/crid://blah.com/d1e5
/program/crid://blah.com/d1e5
  

Комментарии:

1. @edgerunner Почему вы удалили теги?

2. @slhck, это объясняется довольно длинной тирадой о том, почему теги здесь следует использовать не как ключевые слова, а скорее как идентификаторы платформы или экспертизы. Вы заставляете экспертов rails просматривать ваш вопрос, но у вас нет никого, кто называет себя «экспертами по передаче параметров». Такие теги только загрязняют пространство тегов. Вот почему я удаляю их везде, где я их вижу 🙂 (И ваш тег Rails 3 исчез, потому что ваш вопрос не зависит от конкретной версии)

3. @edgerunner Я понимаю вашу точку зрения, но где общий консенсус по этому поводу? (Мета-сообщение, запись часто задаваемых вопросов …) Почему тогда должен быть тег с именем «передача параметров» или «REST»?

4. @slhck На meta была дискуссия по этому поводу. Я попытаюсь откопать это для вас. Там есть всевозможные теги, у большинства из них очень мало подписчиков. Теги, которые имеют надлежащее следование, в основном являются либо тегами платформы / продукта, такими как Rails или Textmate, либо основными, независимыми от платформы темами, такими как удобство использования (REST был бы уместен здесь, но ваш вопрос касается помещения URL в URL, REST больше о том, как ресурс представлен и доступен, вот почему я его сократил.)

5. Однако передача параметров — это специфичная для языка подтема, которой не имеет смысла следовать. Я мог бы легко ответить на любой вопрос о передаче параметров в Ruby, но я бы полностью растерялся при передаче параметров для C . Хорошей эвристикой для выбора полезных тегов было бы подумать, можете ли вы увидеть указанный тег в списке вакансий. (Кто-нибудь, кто передает параметры с опытом работы более 5 лет?) Другой хорошей ссылкой является количество подписчиков, которые есть у тега. У тегов Keywordish очень мало подписчиков. Даже самый непонятный тег платформы / продукта имеет гораздо больше подписчиков.

Ответ №1:

Используйте program/*program_id вместо program/:program_id .

Ответ №2:

В RFC 1738 говорится:

… только буквенно-цифровые, специальные символы «$-_. !*'(),», и зарезервированные символы, используемые для их зарезервированных целей, могут использоваться в URL в незашифрованном виде.

Итак, если вы пытаетесь поместить URL в URL, вам придется либо смириться с закодированными символами, потому что двоеточие : является недопустимым символом, кроме как в качестве разделителя протокола, и потому что двойная косая черта // разрешена только в корне URL-адреса, либо вам придется удалить протокол и корень из вашего URL-адреса и начать с домена. Это:

Вы можете либо сделать это:

 /program/crid%3A%2F/blah.com/d1e5
  

или это

 /program/blah.com/d1e5
  

Компромиссом при использовании Rails может быть помещение протокола в сегмент URL следующим образом:

 /program/crid/blah.com/d1e5
  

которые вы можете собрать в своем params массиве с помощью

 match "program/:protocol/*program_id" => "program#details
  

*program_id Сегмент собирает (globs) оставшуюся часть URL-адреса в одну запись в params массиве.

при необходимости вы можете повторно скомбинировать это в своем контроллере:

 url = "#{params[:protocol]://#{params[:program_id]}}"
  

так что:

 # GET /program/crid/blah.com/d1e5
params[:protocol]   #=> "crid"
params[:program_id] #=> "blah.com/d1e5"
url = "#{params[:protocol]://#{params[:program_id]}}"
#=> "crid://blah.com/d1e5"
  

Комментарии:

1. Отличный вариант! Спасибо за подробный ответ. Я воспользуюсь этим в будущем. Пока я буду придерживаться «простого» подхода, используя параметр в кодировке URL с помощью *program_id .