Quirky Ruby on Rails语法

时间:2015-08-29 13:16:57

标签: ruby-on-rails ruby ruby-on-rails-3

背景:新手rails开发人员在这里学习Michael Hartl的Ruby on Rails教程(https://www.railstutorial.org/),在其中使用User模型和Post模型开发一个类似Twitter的基本应用程序。根据我的理解生成用户路由是将以下内容插入routes.rb文件的常用方法:

resources :users

问题:我不明白你使用时的原因:

redirect_to @user

rails将该请求发送给UsersController#show,但它是通过以下方式调用user_url(@user)来实现的:

get "/users/id" => "users#show"

user_url中的单数(“user”)来自上面的代码?我认为user-url应该是users_url或users_path(正如我在某些地方看到的那样)。只是想弄清楚这个单数被编码到rails中的位置。

谢谢!

2 个答案:

答案 0 :(得分:1)

欢迎使用rails。

如果您查看所有路线,您可能会注意到为什么会立即发生这种情况。但是,由于设计增加了许多可能令人困惑的额外路线。

Rail的路由使用复数和单数模型的概念。

因此,假设您有一位用户,路径是单一的 - user_path(@user) - 并且此网址的网址为/users/1

如果您要查看所有用户的集合,则路径为复数 - users_path - 其网址为/users

与该用户相关的所有路线也是如此。当您谈论仅影响单个对象的操作时,路径是单数的,并且影响多个对象的操作是复数。长时间阅读,但因为它决定了如何解决行动,一个很好的资源是:http://guides.rubyonrails.org/routing.html

答案 1 :(得分:1)

让我们从redirect_to @user

开始,按照兔子洞的一些代码进行操作

redirect_to执行重定向,location设置为url_for(@user) link

def redirect_to(options = {}, response_status = {}) #:doc:
  ...
  self.location      = _compute_redirect_to_location(request, options)
  ...
end

def _compute_redirect_to_location(request, options) #:nodoc:
  ...
  else
    url_for(options)
 ...
end

到目前为止,这么好。 redirect_to对如何确定路径没有发言权。接下来,让我们看一下url_forlink

def url_for(options = nil)
  ...
  else
    ...
    builder = ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder.send(method)
    ...
      builder.handle_model_call(self, options)
    ...
end

看起来url_for负责决定如何构建网址。在这种情况下,它将被发送到HelperMethodBuilder。 link

   def handle_model_call(target, model)
      method, args = handle_model model
      target.send(method, *args)
   end

   def handle_model(record)
      ...
      named_route = if model.persisted?
                      ...
                      get_method_for_string model.model_name.singular_route_key
                    ...
      [named_route, args]
   end

   def get_method_for_string(str)
     "#{prefix}#{str}_#{suffix}"
   end

我们走了。 handle_model获取(持久化)记录model_name,该记录返回ActiveModel::Name个对象,并从中获取singular_route_key

pry(main)> User.first.model_name.singular_route_key  
=> "user"

get_method_for_string使用singular_route_key来完成调用的辅助方法。我将保留推导"prefix" / "suffix"作为学术练习的逻辑,但它应该返回"user_path"

因此,为了回答这个问题,单数形式被编码为ActiveModel :: Name和HelperMethodBuilder。希望有所帮助!