Rails REST路由:资源项ID中的点

san*_*rew 17 rest ruby-on-rails url-routing ruby-on-rails-3

我在我的routes.rb中有以下内容:

resources :users, :except => [:new, :create] do
    get 'friends', :as => :friends, :on => :member, :to => "users#friends"
end
Run Code Online (Sandbox Code Playgroud)

并在我的user.rb中关注:

def to_param
  self.login
end
Run Code Online (Sandbox Code Playgroud)

例如,当登录点上的用户(例如'any.thing')来自facebook时,rails会发出路由错误(没有找到路由,我想这是因为它将点后面的任何内容识别为格式或因为路径限制).我怎么能克服这个错误?

sen*_*sov 36

以下约束定义允许id中的点以及除斜杠之外的任何字符.

必须明确定义支持的格式(此处为.html和.json),以便不被id占用.

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

该约束定义适用于Rails 3.1

对于早期的Rails版本,您可能需要在regin gem中支持前瞻性支持(它以机架式gem出售)

  • 或者`:constraints => {:id =>/[^\/] +(?=#{ActionController :: Renderers :: RENDERERS.map {| e |"\\.#{e} \\ z"}. join("|")})| [^\/] + /}` (3认同)

zet*_*tic 26

您可以用其他字符替换句点:

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"
Run Code Online (Sandbox Code Playgroud)

编辑

你是对的,这无法处理映射到相同值的唯一登录.也许更好的方法是在路线中使用分段约束:

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

这应该允许"/users/bart-simpson"/users/bart.simpson"产生:id => "bart-simpson":id => "bart.simpson"分别.您必须更改正则表达式以添加URL的所有可接受字符.

请注意,这在Rails路由指南的 3.2节中提到:

默认情况下,动态段不接受点 - 这是因为点用作格式化路径的分隔符.如果需要在动态段中使用点,请添加一个覆盖它的约束 - 例如,:id => /[^\/]+/允许除斜杠之外的任何内容.