Rails REST маршрутизация: точки в идентификаторе элемента ресурса - PullRequest
17 голосов
/ 07 марта 2011

У меня в маршрутах есть следующее:

resources :users, :except => [:new, :create] do
    get 'friends', :as => :friends, :on => :member, :to => "users#friends"
end

и следующие в моем user.rb:

def to_param
  self.login
end

И когда, например, пользователь с точками в логине (например, any.thing) приходит из Facebook, rails выдает ошибку маршрутизации (маршрут не найден, я полагаю, это потому, что он распознает что-либо после точки как формат или потому что ограничений маршрута). Как я могу прийти к этой ошибке?

Ответы [ 3 ]

34 голосов
/ 29 сентября 2011

Следующее определение ограничения разрешает точку в id, а также любой символ, кроме косой черты.

Поддерживаемые форматы должны быть явно определены (здесь .html и .json), чтобы их не принимал id.

resources :foobars,
  :constraints => { :id => /[^\/]+(?=\.html\z|\.json\z)|[^\/]+/ }

Это определение ограничения работает с Rails 3.1

Для более ранних версий Rails вам может потребоваться обратная поддержка в regin gem (она продается в геме для монтажа в стойку)

26 голосов
/ 07 марта 2011

Вы можете заменить точки на другой символ:

def to_param
  login.gsub(/\./,"-") # note: 'self' is not needed here
end

user = User.find_by_login("bart.simpson")
user_path(user) # => "/users/bart-simpson"

EDIT

Вы правы, это не относится к уникальным логинам, которые отображаются на одно и то же значение. Может быть, лучше использовать ограничения сегмента в маршруте:

  match 'users/(:id)' => 'users#show', 
    :constraints => { :id => /[0-9A-Za-z\-\.]+/ }

Это должно позволить "/users/bart-simpson" и /users/bart.simpson" генерировать :id => "bart-simpson" и :id => "bart.simpson" соответственно. Вам нужно изменить регулярное выражение, чтобы добавить все допустимые символы для URL.

Обратите внимание, что это упомянуто в Руководство по маршрутизации Rails , раздел 3.2:

По умолчанию динамические сегменты не принимают точки - это потому, что точка используется в качестве разделителя для форматированных маршрутов. Если вам нужно использовать точка в динамическом сегменте добавляет ограничение, которое переопределяет это - например :id => /[^\/]+/ разрешает все, кроме косой черты.

2 голосов
/ 12 мая 2015

Чтобы разрешить сегменту :id содержать любой символ, кроме '/':

match 'users/(:id)' => 'users#show', :constraints => {:id => /[^\/]+/}

Это написано в другом месте в одном из ответов, но это самый простой способ IMO.

...