Rails RESTful ресурсы, использующие to_param для поля, содержащего символы-разделители - PullRequest
8 голосов
/ 04 июня 2009

Я хочу, чтобы мое приложение Rails 2.3.2 отвечало и генерировало URL-адреса следующим образом:

/websites/asd.com
/websites/asd.com/dns_records/new

В моем config / rout.rb у меня есть:

map.resources :websites, :has_many => :dns_records
map.resources :dns_records, :belongs_to => :website

Затем я могу получить доступ к таким ресурсам, как:

/websites/1
/websites/1/dns_records

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

class Website < ActiveRecord::Base
    def to_param
        domain_name
    end
    ...
end

# app/views/websites/index.erb
<% @websites.each do |w| %>
<%= link_to "Show #{w}", website_path(w) %>
<% end %>

# Produces a link to:
/websites/example_without_periods_in_name

Однако для доменных имен, содержащих «.» персонажи, Rails становится несчастным. Я считаю, что это потому, что "." символ определяется в ActionController :: Routing :: SEPARATORS, в котором перечислены специальные символы для разделения URL-адреса. Это позволяет вам делать такие вещи, как /websites/1.xml.

ТАК, есть ли чистый способ разрешить '.' символы в URL-адресах RESTful?

Я попытался переопределить ActionController :: Routing :: SEPARATORS, чтобы он не включал «.», Что является абсолютно плохим способом решения проблемы. Это портит сгенерированные URL, добавляя к ним «.: Format».

Я также знаю, что могу добавить: needs => {: id => regexp} в мой config / rout.rb, чтобы соответствовать имени домена, которое включает в себя '. (без этого params [: id] устанавливается на часть имени домена перед первым '.'), но это не помогает при генерации URL / путей RESTful.

Большое спасибо :) Ник

Ответы [ 3 ]

4 голосов
/ 05 июня 2009

Решил проблему, с большим спасибо http://poocs.net/2007/11/14/special-characters-and-nested-routes (и см. http://dev.rubyonrails.org/ticket/6426 для дополнительной справки)

Мне нужно было добавить: needs => {: website_id => regexp} для каждого вложенного маршрута, который также собирался включать доменное имя с точками в нем.

Вот мой рабочий маршрут:

map.resources :websites, :requirements => { :id => /[a-zA-Z0-9\-\.]+/ } do |websites|
    websites.with_options :requirements => { :website_id => /[a-zA-Z0-9\-\.]+/ }  do |websites_requirements|
        websites_requirements.resources :dns_records
    end
end

<%= link_to 'New DNS Record', new_website_dns_record_path(@website) %>

# Produces the URL
/websites/asd.com/dns_records/new

Звонок на

websites.with_options

просто соответствует DRY, так что: не нужно указывать требования для всех вложенных маршрутов для веб-сайтов. Так что я мог бы также иметь

websites_requirements.resources :accounts
websites_requirements.resources :monthly_bandwidth_records
etc.
1 голос
/ 04 июня 2009

Это интересный вопрос. Я не думаю, что вы можете избавиться от плохого '.:format', добавленного до конца, если вы сделаете базовый map.resources. Если вам нужны точки в именах, вы не соответствует обычным стилям рельсов, и я думаю, что пользовательский маршрут может быть в порядке, если вы абсолютно NEED '.' в URL.

Однако, возможно, вам следует подумать об изменении определения to_param. Что бы вы подумали об использовании следующего?

def to_param
   domain_name.sub('.','_dot_')
end

Я думаю, что если вы используете это для управления веб-сайтами клиентов, это довольно элегантный способ создания хороших (и оптимизированных для SEO) URL, таких как

/websites/asd_dot_com/dns_records/new
/websites/asd_dot_com/
0 голосов
/ 05 августа 2010

Некоторое время назад у меня была похожая проблема, и я нашел похожее решение. Использование / .+/ в качестве требования для рассматриваемого параметра работало нормально для меня.

http://zargony.com/2009/05/05/routing-parameters-with-a-dot

...