【问题标题】:Quirky Ruby on Rails Syntax古怪的 Ruby on Rails 语法
【发布时间】:2015-08-29 13:16:56
【问题描述】:

背景:新手 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-url 应该是 users_url 或 users_path (正如我在某些地方看到的那样)。只是想弄清楚这个单数在哪里被编码到 Rails 中。

谢谢!

【问题讨论】:

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


    【解决方案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。希望对您有所帮助!

    【讨论】:

    • 还有 vualá!谢谢,非常感谢。
    【解决方案2】:

    欢迎来到 Rails。

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

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

    假设你有一个用户,路径是单一的——user_path(@user)——而这个 URL 是/users/1

    如果你想查看所有用户的集合,路径是复数 -- users_path -- 并且这个 URL 是 /users

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

    【讨论】:

    • 所以我知道路径users_path 和URL /users 来自哪里,因为当我运行rake routes 时,我看到resources : users 生成的几个路由,例如users GET /users(.:format) users#index。我看到这次溃败的 URI 是users,这对我来说都很有意义。但我看不出用户的单数来自代码的哪里。
    • 它只是一个返回正确 URL 的语义助手。因为您只在寻找单个对象,所以助手是单数的。所有路径助手都是这种方式,除非您深入研究 Rails 核心,否则您不会“看到”代码。
    • 好的,所以它在 Rails 核心中,我不会在任何路线中明确看到它,这就是我想知道的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    • 1970-01-01
    • 2015-07-25
    • 2016-01-31
    相关资源
    最近更新 更多