24、Rails路由系统:定义、定制与使用

Rails路由系统:定义、定制与使用

在Rails应用程序中,路由系统起着至关重要的作用,它负责将传入的请求映射到相应的控制器和动作。下面我们将详细探讨Rails路由系统的各个方面。

1. 使用map.connect定义路由

创建新的Rails应用程序时,会生成一个 config/routes.rb 文件,其中定义了两条默认(未命名或匿名)路由:

map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'

路由子系统会尝试在定义的模式和传入请求的URL之间找到匹配项。例如,对于第一条路由 map.connect ':controller/:action/:id' ,如果请求的URL是 /library/borrow/25189 ,Rails会将URL中的第一个令牌( library )映射到 :controller 参数,第二个令牌( borrow )映射到 :action 参数,第三个令牌( 25189 )映射到 :id 参数。此时, params 对象如下:

params = { :controller => "library", :action => "borrow", :id => "25189" }

Rails将实例化 library 控制器并执行其中定义的 borrow 动作来处理请求。作为开发者,可以通过 params[:id] 在控制器中获取 :id 参数。

默认参数

并非所有三个参数都是严格必需的。例如,省略 id ,请求路径为 /library/catalog 时,参数如下:

params = { :controller => "library", :action => "catalog" }

即使缺少第三个参数,这种匹配也是可能的,因为 connect :id 定义了默认值。除非在URL中指定了值,否则 :id nil ,并且 nil 参数不会包含在 params 对象中。同样,当缺少动作时, connect 定义的默认值为 "index" ,因此 /library 将映射到 { :controller => "library", :action => "index" }

2. 定制路由

默认路由比较通用,其模式可以匹配包含任意控制器名称、任意动作名称和任意 id 的请求URL,并且支持任何HTTP动词。但它并非能匹配所有路径,例如 /library/borrow/43274/something /library/something/borrow/43274 就无法匹配,因为它们有四个令牌,而不是预期的三个。

:id 参数可以有任何值,不一定局限于字符串形式的数字,不过由于 params[:id] 通常会传递给 ActiveRecord::Base find 方法,所以经常是数字。 :controller :action 是特殊命名的参数,分别用于标识处理请求的控制器和动作。模式中的其他符号,包括 :id ,都将被视为常规命名参数并包含在 params 对象中。

可以通过向 connect 方法传递选项(如 :controller :action )来显式要求特定的控制器和/或动作。例如:

map.connect 'library/:action/:isbn', :controller => "library" 

对于请求路径 /library/borrow/9780470189481 ,将映射为:

params = { :controller=> "library", :action=> "borrow", :isbn=> "9780470189481" }

该路由也会匹配 /library/archive/9780470189481 ,映射结果为:

params = { :controller=> "library", :action=> "archive", :isbn=> "9780470189481" }

这里动作是可变的,但控制器是固定的,请求路径必须以 /library/ 开头,后面跟着动作和ISBN。 :id 默认为 nil ,但自定义命名参数 :isbn 没有默认值,因此必须提供值才能匹配。

也可以通过 :defaults 选项定义自己的默认值。例如,使 :isbn 成为可选参数:

map.connect 'library/:action/:isbn', :controller => "library",
                                     :defaults => { :isbn => nil }

如果省略ISBN,它将不会出现在参数哈希中,并且由于移除了这个约束,现在也可以省略动作,使用 :action 的默认值 "index"

3. 路由通配符

在路由模式中,可以使用类似Ruby方法中可变参数的方式来捕获URL中可变数量的斜杠分隔令牌。如果在模式中放置 *path (或其他名称),可以通过 params[:path] 捕获URL中的可变数量的令牌,这称为“路由通配符”。与常规Ruby方法不同,通配符不必是模式中的最后一个参数。

例如,模式为 'library/:action/:isbn/*extra/preview' ,用户请求的路径为 '/library/borrow/9780470189481/3/weeks/preview' ,不仅路径与模式匹配,还可以通过 params[:extra] 访问额外的参数,其值为 ["3", "weeks"]

4. 路由选项

connect 方法接受第二个参数,即选项哈希,以下是一些常见的选项:
| 选项 | 描述 |
| — | — |
| :action | 用于指示当请求的URL与路由声明指定的模式匹配时,应该由哪个动作处理请求。如果模式中存在 :action ,则该值优先于 :action 选项。 |
| :conditions | 用于定义路由的限制,支持 :method 条件,指定哪些HTTP方法可以访问该路由,如 :post :get :put :delete :any 。 |
| :controller | 用于指示应该将哪个控制器映射到该路由。如果模式中存在 :controller ,则 :controller => "example" 选项仅在URL中未提供控制器时适用。 |
| :defaults | 用于为传递给 connect 的模式中包含的一个或多个命名参数指定默认值。 |
| :<parameter_name> | 根据分配的值,此选项可用于两个不同的任务。当分配正则表达式时,为命名参数设置要求;当分配常规值时,将参数添加到 params 对象中。 |
| :requirements | 用于指定URL中一个或多个参数的格式约束。如果请求中指定的任何参数不满足 :requirements 哈希中定义的条件,则该路由将不适用。 |

5. 路由优先级

routes.rb 文件中定义的路由块可以包含多个路由,可能会有多个路由匹配传入的请求URL和HTTP动词。但每个请求只能映射到一个路由,因此路由系统为每个定义的路由分配了不同的优先级。模式匹配算法从顶部开始向下检查每个路由的模式、条件和要求,直到找到匹配项。找到匹配的路由后,不再检查该请求的其他路由。

这意味着路由块中的路由按优先级顺序排列,第一条路由优先级最高,最后一条路由优先级最低。默认路由通常放在块的末尾,因为它们比较通用,可以在更具体的路由不适用时作为“兜底”路由。如果没有路由匹配传入的请求,将引发 ActionController::RoutingError 异常。

例如,对于简单博客应用的 routes.rb 文件,如果将默认路由放在顶部:

# Don’t do this
ActionController::Routing::Routes.draw do |map|
  map.connect ':controller/:action/:id'
  map.connect ':controller/:action/:id.:format'
  map.root :controller => "articles"
  map.resources :articles, :has_many => :comments, 
                           :collection => { :unpublished => :get }
end

当收到RESTful请求 /articles/3/show 时,路由会尝试与第一条路由匹配,最终会将请求错误地映射到动作 3 id show 。因此,在RESTful应用中,如果不需要默认路由,建议将其注释掉。

6. 从控制台使用路由

控制台在处理路由时也非常有用,主要有两个任务:确定哪个路由匹配给定的URL,以及根据控制器、动作和参数获取URL。

所有在 routes.rb 中定义的路由都添加到 Routes 对象中,可以通过以下步骤从控制台使用路由:
1. 启动控制台并将 ActionController::Routing::Routes 分配给一个局部变量:

>> routes = ActionController::Routing::Routes
  1. 如果要测试尚未定义的控制器的路由,可以将它们的名称放在数组中并传递给 use_controllers!
>> ActionController::Routing::use_controllers! ["main", "library"]
  1. 重新加载路由文件:
>> load 'config/routes.rb'
  1. 使用 recognize_path 方法识别路径:
>> routes.recognize_path '/main/show/3'
=> {:action => "show", :controller => "main", :id => "3"}
  1. 使用 generate 方法生成URL:
>> routes.generate :controller => 'main', :coupon => 1920321
=> "/main?coupon=1920321"
7. 命名路由

connect 方法生成未命名路由,而 ActionController 提供了为路由定义标签的能力,即命名路由。例如,在 routes.rb 文件中定义:

map.root :controller => "articles"

通过使用 root 而不是 connect ,创建了一个命名路由 root ,可以通过 root_url (如 http://localhost:3000/ )和 root_path (如 / )轻松访问。

命名路由很方便,因为可以使用辅助方法来引用它们,而不必每次都向 url_for redirect_to link_to 等方法指定控制器、动作、默认值等。虽然 root 路由的优势不太明显,但在更复杂的场景中,命名路由的优势会更加突出。

graph LR
    A[传入请求] --> B{路由匹配}
    B -->|匹配成功| C[执行对应控制器和动作]
    B -->|匹配失败| D[抛出RoutingError异常]

综上所述,Rails的路由系统提供了丰富的功能和灵活性,通过合理定义和定制路由,可以更好地处理各种请求。在实际开发中,要注意路由的优先级和参数的使用,以确保请求能够正确映射到相应的控制器和动作。同时,命名路由和控制台的使用也能提高开发效率。

Rails路由系统:定义、定制与使用

8. 命名路由的优势与应用场景

命名路由在实际开发中具有显著的优势,尤其是在处理复杂的路由逻辑时。除了前面提到的 root 路由,我们可以通过更多的例子来展示其强大之处。

假设我们有一个电子商务应用,其中有商品展示、购物车和订单处理等功能。我们可以在 routes.rb 中定义以下命名路由:

map.products :controller => "products", :action => "index"
map.cart :controller => "cart", :action => "show"
map.checkout :controller => "orders", :action => "new"

这样,在视图或控制器中,我们可以使用生成的辅助方法来引用这些路由,而无需每次都手动构建URL。例如:

# 在视图中生成商品列表页面的链接
<%= link_to "商品列表", products_url %>

# 在控制器中重定向到购物车页面
redirect_to cart_path

命名路由的另一个重要应用场景是在国际化应用中。当我们需要支持多种语言时,不同语言的URL可能会有所不同。使用命名路由,我们可以轻松地根据当前语言环境生成正确的URL。例如,在使用 i18n 进行国际化时,我们可以这样定义路由:

map.with_options :path_names => { :new => 'neu', :edit => 'bearbeiten' } do |map|
  map.products :controller => "products", :action => "index"
end

这样,在德语环境下, products_url 生成的URL可能会包含德语的路径名称,而在其他语言环境下则会根据相应的配置生成正确的URL。

9. 路由与RESTful架构的结合

在现代Web开发中,RESTful架构是一种非常流行的设计风格,它强调资源的统一接口和状态转移。Rails的路由系统与RESTful架构紧密结合,提供了便捷的方式来定义RESTful路由。

routes.rb 中,我们可以使用 map.resources 方法来定义RESTful资源的路由。例如,对于一个博客应用的文章资源,我们可以这样定义:

map.resources :articles

这将自动生成以下一组RESTful路由:
| HTTP方法 | 路径 | 动作 | 用途 |
| — | — | — | — |
| GET | /articles | index | 显示所有文章列表 |
| GET | /articles/new | new | 显示创建新文章的表单 |
| POST | /articles | create | 创建新文章 |
| GET | /articles/:id | show | 显示单篇文章 |
| GET | /articles/:id/edit | edit | 显示编辑文章的表单 |
| PUT | /articles/:id | update | 更新文章 |
| DELETE | /articles/:id | destroy | 删除文章 |

这种自动生成的路由使得我们可以很方便地实现RESTful风格的API。同时,我们还可以通过 map.resources 的选项来定制这些路由。例如,如果我们希望文章资源有一个自定义的动作 unpublished ,可以这样定义:

map.resources :articles, :collection => { :unpublished => :get }

这将生成一个新的路由 GET /articles/unpublished ,用于显示未发布的文章列表。

10. 路由的错误处理

在实际应用中,不可避免地会遇到一些无法匹配的路由请求。为了提供更好的用户体验,我们需要对这些错误进行适当的处理。

当没有路由匹配传入的请求时,Rails会抛出 ActionController::RoutingError 异常。我们可以在 ApplicationController 中捕获这个异常,并返回一个自定义的错误页面。例如:

class ApplicationController < ActionController::Base
  rescue_from ActionController::RoutingError, with: :render_404

  private

  def render_404
    render file: "#{Rails.root}/public/404.html", status: 404, layout: false
  end
end

这样,当用户访问一个不存在的路由时,将显示自定义的404错误页面。

此外,我们还可以通过 map.connect 定义一些特殊的路由来处理常见的错误情况。例如,我们可以定义一个路由来处理所有未匹配的请求:

map.connect '*path', :controller => 'errors', :action => 'not_found'

ErrorsController 中,我们可以实现 not_found 动作来处理这些未匹配的请求:

class ErrorsController < ApplicationController
  def not_found
    render status: 404
  end
end
11. 路由的性能优化

随着应用的发展,路由规则可能会变得越来越复杂,这可能会影响路由匹配的性能。为了优化路由性能,我们可以采取以下几个措施:

  • 减少路由数量 :尽量避免定义过多的冗余路由。对于一些可以合并的路由,进行合并处理。例如,如果有多个路由的逻辑非常相似,可以考虑使用路由通配符或参数来简化路由定义。
  • 合理安排路由顺序 :将最常用的路由放在路由文件的顶部,这样可以减少路由匹配的时间。因为路由匹配算法是从顶部开始向下检查的,越早找到匹配的路由,性能就越好。
  • 使用缓存 :Rails的路由系统会对路由信息进行缓存,以提高匹配速度。在生产环境中,确保路由缓存是启用的,可以通过设置 config.action_controller.perform_caching = true 来启用缓存。
12. 路由的测试

在开发过程中,对路由进行测试是确保路由功能正确性的重要步骤。Rails提供了方便的测试工具来测试路由。

我们可以使用 ActionController::TestCase 来编写路由测试。例如,对于前面定义的博客应用的文章资源路由,我们可以编写以下测试用例:

require 'test_helper'

class RoutesTest < ActionController::TestCase
  test "should route to articles index" do
    assert_routing "/articles", { :controller => "articles", :action => "index" }
  end

  test "should route to show an article" do
    assert_routing "/articles/1", { :controller => "articles", :action => "show", :id => "1" }
  end
end

通过这些测试用例,我们可以验证路由是否按照预期进行匹配。如果路由发生了变化,测试用例可以帮助我们及时发现问题。

13. 路由系统的工作流程总结

为了更好地理解Rails路由系统的工作原理,我们可以总结其工作流程如下:

graph LR
    A[客户端发送请求] --> B{路由匹配开始}
    B --> C[从路由文件顶部开始检查路由]
    C --> D{是否匹配当前路由}
    D -->|是| E[提取参数,执行对应控制器和动作]
    D -->|否| F{是否还有下一条路由}
    F -->|是| C
    F -->|否| G[抛出RoutingError异常]
    E --> H[处理请求,生成响应]
    H --> I[将响应返回给客户端]

当客户端发送请求时,Rails的路由系统会从 routes.rb 文件的顶部开始,依次检查每条路由的模式、条件和要求,直到找到匹配的路由。如果找到匹配的路由,会提取URL中的参数,并执行对应的控制器和动作。如果没有找到匹配的路由,则会抛出 ActionController::RoutingError 异常。

综上所述,Rails的路由系统是一个功能强大且灵活的工具,它为我们处理请求提供了丰富的功能和便捷的方式。通过合理使用路由选项、命名路由、RESTful路由等特性,以及注意路由的优先级、性能优化和测试等方面,我们可以构建出高效、可维护的Web应用。在实际开发中,深入理解和掌握路由系统的工作原理和使用方法,将有助于我们更好地实现各种复杂的业务逻辑。

内容概要:本文介绍了一个基于冠豪猪优化算法(CPO)的无人机三维路径规划项目,利用Python实现了在复杂三维环境中为无人机规划安全、高效、低能耗飞行路径的完整解决方案。项目涵盖空间环境建模、无人机动力学约束、路径编码、多目标代价函数设计以及CPO算法的核心实现。通过体素网格建模、动态障碍物处理、路径平滑技术和多约束融合机制,系统能够在高维、密集障碍环境下快速搜索出满足飞行可行性、安全性能效最优的路径,并支持在线重规划以适应动态环境变化。文中还提供了关键模块的代码示例,包括环境建模、路径评估和CPO优化流程。; 适合人群:具备一定Python编程基础和优化算法基础知识,从事无人机、智能机器人、路径规划或智能优化算法研究的相关科研人员工程技术人员,尤其适合研究生及有一定工作经验的研发工程师。; 使用场景及目标:①应用于复杂三维环境下的无人机自主导航避障;②研究智能优化算法(如CPO)在路径规划中的实际部署性能优化;③实现多目标(路径最短、能耗最低、安全性最高)耦合条件下的工程化路径求解;④构建可扩展的智能无人系统决策框架。; 阅读建议:建议结合文中模型架构代码示例进行实践运行,重点关注目标函数设计、CPO算法改进策略约束处理机制,宜在仿真环境中测试不同场景以深入理解算法行为系统鲁棒性。
在科技快速演进的时代背景下,移动终端性能持续提升,用户对移动应用的功能需求日益增长。增强现实、虚拟现实、机器人导航、自动驾驶辅助、手势识别、物体检测距离测量等前沿技术正成为研究应用的热点。作为支撑这些技术的核心,双目视觉系统通过模仿人类双眼的成像机制,同步获取两路图像数据,并借助图像处理立体匹配算法提取场景深度信息,进而生成点云并实现三维重建。这一技术体系对提高移动终端的智能化程度及优化人机交互体验具有关键作用。 双目视觉系统需对同步采集的两路视频流进行严格的时间同步空间校正,确保图像在时空维度上精确对齐,这是后续深度计算立体匹配的基础。立体匹配旨在建立两幅图像中对应特征点的关联,通常依赖复杂且高效的计算算法以满足实时处理的要求。点云生成则是将匹配后的特征点转换为三维空间坐标集合,以表征物体的立体结构;其质量直接取决于图像处理效率匹配算法的精度。三维重建基于点云数据,运用计算机图形学方法构建物体或场景的三维模型,该技术在增强现实虚拟现实等领域尤为重要,能够为用户创造高度沉浸的交互环境。 双目视觉技术已广泛应用于多个领域:在增强现实虚拟现实中,它可提升场景的真实感沉浸感;在机器人导航自动驾驶辅助系统中,能实时感知环境并完成距离测量,为路径规划决策提供依据;在手势识别物体检测方面,可精准捕捉用户动作物体位置,推动人机交互设计智能识别系统的发展。此外,结合深度计算点云技术,双目系统在精确距离测量方面展现出显著潜力,能为多样化的应用场景提供可靠数据支持。 综上所述,双目视觉技术在图像处理、深度计算、立体匹配、点云生成及三维重建等环节均扮演着不可或缺的角色。其应用跨越多个科技前沿领域,不仅推动了移动设备智能化的发展,也为丰富交互体验提供了坚实的技术基础。随着相关算法的持续优化硬件性能的不断提升,未来双目视觉技术有望在各类智能系统中实现更广泛、更深层次的应用。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值