Rails REST маршрутизация: точки в идентификаторе элемента ресурса
У меня есть следующие маршруты на моих маршрутах. rb:
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 дает ошибку маршрутизации (никакого маршрута не найдено, я полагаю, потому что он распознает что-либо после точки в виде формата или потому, что ограничений маршрута). Как я могу преодолеть эту ошибку?
Ответы
Ответ 1
Вы можете заменить периоды на другой символ:
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"
ИЗМЕНИТЬ
Вы правы, это не касается уникальных логинов, которые сопоставляются с одним и тем же значением. Возможно, лучший способ - использовать ограничения сегмента на маршруте:
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 Routing Guide, раздел 3.2:
По умолчанию динамические сегменты не принимают точки - это потому, что dot используется как разделитель для отформатированных маршрутов. Если вам нужно использовать точка в динамическом сегменте добавляет ограничение, которое отменяет это - например: id = > /[^/] +/позволяет что угодно, кроме косой черты.
Ответ 2
Следующее определение ограничения разрешает точку в id, а также любой символ, кроме слэша.
Поддерживаемые форматы должны быть явно определены (здесь .html и .json), чтобы они не были приняты идентификатором.
resources :foobars,
:constraints => { :id => /[^\/]+(?=\.html\z|\.json\z)|[^\/]+/ }
Это ограничение определяет работу с Rails 3.1
Для более ранних версий Rails вам может потребоваться обратная поддержка вперед-назад в regin gem (она продается в стойке)
Ответ 3
Чтобы разрешить сегменту :id
содержать любой символ, кроме '/'
:
match 'users/(:id)' => 'users#show', :constraints => {:id => /[^\/]+/}
Это написано в другом месте в одном из ответов, но это ИМО самый простой способ.