Rails源代码分析(30):ActionController::Routing(1)

本文深入解析了Rails中的路由机制,介绍了如何使用Rails路由实现URL重写,包括路由的优先级、默认参数设置、命名路由、生成美观的URL等内容,并探讨了路由条件及重新加载路由的方法。
这个Module穿插在整个ActionPack里面的各个地方,
routing 在启动Rails的同时就会加载:
  1.     def initialize_routing
  2.       # 确认包含action_controller
  3.       return unless configuration.frameworks.include?(:action_controller)
  4.       # 加入config加入的controller路径
  5.       ActionController::Routing.controller_paths = configuration.controller_paths 
  6.       # 加入config加入的route路径
  7.       ActionController::Routing::Routes.configuration_file = configuration.routes_configuration_file
  8.       ActionController::Routing::Routes.reload
  9.     end
Routing分析思路:
1) map.connect (RouteSet, Mapper)
2) add_route (RouteBuilder Route Segment)

类的组合:
Routing
  Helper { include PolymorphicRoutes }
  Routes = RouteSet.new # 主要使用的入口对象

RouteSet
  Mapper
  NamedRouteCollection
  builder = RouteBuilder
  add_route(path, options)
        route = builder.build(path, options)
        routes << route
        route
  
RouteBuilder
  build(path, options)
        route = Route.new
        route.segments = segments
        route.requirements = requirements
        route.conditions = conditions
        ...
        route



这里调用了一个Routes实例,在这里,先看看Routing这个module:
  1) Routing的基本用法
  #
  # The routing module provides URL rewriting in native Ruby. It's a way to
  # redirect incoming requests to controllers and actions. This replaces
  # mod_rewrite rules. Best of all, Rails' Routing works with any web server.
  # Routes are defined in <tt>config/routes.rb</tt>.
  #
  # Consider the following route, installed by Rails when you generate your
  # application:
  #
  #   map.connect ':controller/:action/:id'
  #
  # This route states that it expects requests to consist of a
  # <tt>:controller</tt> followed by an <tt>:action</tt> that in turn is fed
  # some <tt>:id</tt>.
  #
  # Suppose you get an incoming request for <tt>/blog/edit/22</tt>, you'll end up
  # with:
  #
  #   params = { :controller => 'blog',
  #              :action     => 'edit',
  #              :id         => '22'
  #           }
  #
  # Think of creating routes as drawing a map for your requests. The map tells
  # them where to go based on some predefined pattern:
  #
  #   ActionController::Routing::Routes.draw do |map|
  #     Pattern 1 tells some request to go to one place
  #     Pattern 2 tell them to go to another
  #     ...
  #   end
  #
  # The following symbols are special:
  #
  #   :controller maps to your controller name
  #   :action     maps to an action with your controllers
  #
  # Other names simply map to a parameter as in the case of <tt>:id</tt>.
  #
  2) Route 优先级
  #
  # Not all routes are created equally. Routes have priority defined by the
  # order of appearance of the routes in the <tt>config/routes.rb</tt> file. The priority goes
  # from top to bottom. The last route in that file is at the lowest priority
  # and will be applied last. If no route matches, 404 is returned.
  #
  # Within blocks, the empty pattern is at the highest priority.
  # In practice this works out nicely:
  #
  #   ActionController::Routing::Routes.draw do |map|
  #     map.with_options :controller => 'blog' do |blog|
  #       blog.show '',  :action => 'list'
  #     end
  #     map.connect ':controller/:action/:view'
  #   end
  #
  # In this case, invoking blog controller (with an URL like '/blog/')
  # without parameters will activate the 'list' action by default.
  #
  3) 默认的routes和默认的参数
  #
  # Setting a default route is straightforward in Rails - you simply append a
  # Hash at the end of your mapping to set any default parameters.
  #
  # Example:
  #
  #   ActionController::Routing:Routes.draw do |map|
  #     map.connect ':controller/:action/:id', :controller => 'blog'
  #   end
  #
  # This sets up +blog+ as the default controller if no other is specified.
  # This means visiting '/' would invoke the blog controller.
  #
  # More formally, you can define defaults in a route with the <tt>:defaults</tt> key.
  #
  #   map.connect ':controller/:action/:id', :action => 'show', :defaults => { :page => 'Dashboard' }
  #
  # Note: The default routes, as provided by the Rails generator, make all actions in every
  # controller accessible via GET requests. You should consider removing them or commenting
  # them out if you're using named routes and resources.
  #
  4) 命名的 routes
  #
  # Routes can be named with the syntax <tt>map.name_of_route options</tt>,
  # allowing for easy reference within your source as +name_of_route_url+
  # for the full URL and +name_of_route_path+ for the URI path.
  #
  # Example:
  #
  #   # In routes.rb
  #   map.login 'login', :controller => 'accounts', :action => 'login'
  #
  #   # With render, redirect_to, tests, etc.
  #   redirect_to login_url
  #
  # Arguments can be passed as well.
  #
  #   redirect_to show_item_path(:id => 25)
  #
  # Use <tt>map.root</tt> as a shorthand to name a route for the root path "".
  #
  #   # In routes.rb
  #   map.root :controller => 'blogs'
  #
  #   # would recognize http://www.example.com/ as
  #   params = { :controller => 'blogs', :action => 'index' }
  #
  #   # and provide these named routes
  #   root_url   # => 'http://www.example.com/'
  #   root_path  # => ''
  #
  # You can also specify an already-defined named route in your <tt>map.root</tt> call:
  #
  #   # In routes.rb
  #   map.new_session :controller => 'sessions', :action => 'new'
  #   map.root :new_session
  #
  # Note: when using +with_options+, the route is simply named after the
  # method you call on the block parameter rather than map.
  #
  #   # In routes.rb
  #   map.with_options :controller => 'blog' do |blog|
  #     blog.show    '',            :action  => 'list'
  #     blog.delete  'delete/:id',  :action  => 'delete',
  #     blog.edit    'edit/:id',    :action  => 'edit'
  #   end
  #
  #   # provides named routes for show, delete, and edit
  #   link_to @article.title, show_path(:id => @article.id)
  #
  5) 漂亮的 URLs
  #
  # Routes can generate pretty URLs. For example:
  #
  #   map.connect 'articles/:year/:month/:day',
  #               :controller => 'articles',
  #               :action     => 'find_by_date',
  #               :year       => //d{4}/,
  #               :month      => //d{1,2}/,
  #               :day        => //d{1,2}/
  #
  # Using the route above, the URL "http://localhost:3000/articles/2005/11/06"
  # maps to
  #
  #   params = {:year => '2005', :month => '11', :day => '06'}
  #
  6) 参数和正则表达式
  # You can specify a regular expression to define a format for a parameter.
  #
  #   map.geocode 'geocode/:postalcode', :controller => 'geocode',
  #               :action => 'show', :postalcode => //d{5}(-/d{4})?/
  #
  # or, more formally:
  #
  #   map.geocode 'geocode/:postalcode', :controller => 'geocode',
  #               :action => 'show', :requirements => { :postalcode => //d{5}(-/d{4})?/ }
  #
  # Formats can include the 'ignorecase' and 'extended syntax' regular
  # expression modifiers:
  #
  #   map.geocode 'geocode/:postalcode', :controller => 'geocode',
  #               :action => 'show', :postalcode => /hx/d/d/s/d[a-z]{2}/i
  #
  #   map.geocode 'geocode/:postalcode', :controller => 'geocode',
  #               :action => 'show',:requirements => {
  #                 :postalcode => /# Postcode format
  #                                 /d{5} #Prefix
  #                                 (-/d{4})? #Suffix
  #                                 /x
  #               }
  #
  # Using the multiline match modifier will raise an ArgumentError.
  # Encoding regular expression modifiers are silently ignored. The
  # match will always use the default encoding or ASCII.
  #
  7) Route globbing
  #
  # Specifying <tt>*[string]</tt> as part of a rule like:
  #
  #   map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?'
  #
  # will glob all remaining parts of the route that were not recognized earlier. This idiom
  # must appear at the end of the path. The globbed values are in <tt>params[:path]</tt> in
  # this case.
  #
  8) Route conditions
  #
  # With conditions you can define restrictions on routes. Currently the only valid condition is <tt>:method</tt>.
  #
  # * <tt>:method</tt> - Allows you to specify which method can access the route. Possible values are <tt>:post</tt>,
  #   <tt>:get</tt>, <tt>:put</tt>, <tt>:delete</tt> and <tt>:any</tt>. The default value is <tt>:any</tt>, 
  #   <tt>:any</tt> means that any method can access the route.
  #
  # Example:
  #
  #   map.connect 'post/:id', :controller => 'posts', :action => 'show',
  #               :conditions => { :method => :get }
  #   map.connect 'post/:id', :controller => 'posts', :action => 'create_comment',
  #               :conditions => { :method => :post }
  #
  # Now, if you POST to <tt>/posts/:id</tt>, it will route to the <tt>create_comment</tt> action. A GET on the same
  # URL will route to the <tt>show</tt> action.
  # 
  9) Reloading routes
  #
  # You can reload routes if you feel you must:
  #
  #   ActionController::Routing::Routes.reload
  #
  # This will clear all named routes and reload routes.rb if the file has been modified from
  # last load. To absolutely force reloading, use <tt>reload!</tt>.
  #
  10) Testing Routes
  #
  # The two main methods for testing your routes:
  #
  # === +assert_routing+
  #
  #   def test_movie_route_properly_splits
  #    opts = {:controller => "plugin", :action => "checkout", :id => "2"}
  #    assert_routing "plugin/checkout/2", opts
  #   end
  #
  # +assert_routing+ lets you test whether or not the route properly resolves into options.
  #
  # === +assert_recognizes+
  #
  #   def test_route_has_options
  #    opts = {:controller => "plugin", :action => "show", :id => "12"}
  #    assert_recognizes opts, "/plugins/show/12"
  #   end
  #
  # Note the subtle difference between the two: +assert_routing+ tests that
  # a URL fits options while +assert_recognizes+ tests that a URL
  # breaks into parameters properly.
  #
  # In tests you can simply pass the URL or named route to +get+ or +post+.
  #
  #   def send_to_jail
  #     get '/jail'
  #     assert_response :success
  #     assert_template "jail/front"
  #   end
  #
  #   def goes_to_login
  #     get login_url
  #     #...
  #   end
  #
  # == View a list of all your routes
  #
  # Run <tt>rake routes</tt>.
  #
  1. require 'cgi'
  2. require 'uri'
  3. require 'action_controller/polymorphic_routes'
  4. require 'action_controller/routing/optimisations'
  5. require 'action_controller/routing/routing_ext'
  6. require 'action_controller/routing/route'
  7. require 'action_controller/routing/segments'
  8. require 'action_controller/routing/builder'
  9. require 'action_controller/routing/route_set'
  10. require 'action_controller/routing/recognition_optimisation'
  11. module ActionController
  12.   
  13.   module Routing
  14.     SEPARATORS = %w( / . ? )
  15.     HTTP_METHODS = [:get:head:post:put:delete]
  16.     ALLOWED_REQUIREMENTS_FOR_OPTIMISATION = [:controller:action].to_set
  17.     # The root paths which may contain controller files
  18.     mattr_accessor :controller_paths
  19.     self.controller_paths = []
  20.     # A helper module to hold URL related helpers.
  21.     module Helpers
  22.       include PolymorphicRoutes
  23.     end
  24.     class << self
  25.       # Expects an array of controller names as the first argument.  
  26.       # Executes the passed block with only the named controllers named available.
  27.       This method is used in internal Rails testing.
  28.       def with_controllers(names)
  29.         prior_controllers = @possible_controllers
  30.         use_controllers! names
  31.         yield
  32.       ensure
  33.         use_controllers! prior_controllers
  34.       end
  35.       # Returns an array of paths, cleaned of double-slashes and relative path references.
  36.       # * "///" and "//"  become "//" or "/". 
  37.       # * "/foo/bar/../config" becomes "/foo/config".
  38.       # The returned array is sorted by length, descending.
  39.       def normalize_paths(paths) # 正则化路径
  40.         # do the hokey-pokey of path normalization...
  41.         paths = paths.collect do |path|
  42.           path = path.
  43.             gsub("//""/").           # replace double / chars with a single
  44.             gsub("////", "//").        # replace double / chars with a single
  45.             gsub(%r{(.)[///]$}, '/1')  # drop final / or / if path ends with it
  46.           # eliminate .. paths where possible
  47.           re = %r{[^///]+[///]/./.[///]}
  48.           path.gsub!(re, ""while path.match(re)
  49.           path
  50.         end
  51.         # start with longest path, first
  52.         paths = paths.uniq.sort_by { |path| - path.length }
  53.       end
  54.       # Returns the array of controller names currently available to ActionController::Routing.
  55.       def possible_controllers
  56.         unless @possible_controllers
  57.           @possible_controllers = []
  58.           paths = controller_paths.select { |path| File.directory?(path) && path != "." }
  59.           seen_paths = Hash.new {|h, k| h[k] = truefalse
  60.           # 这个初始化Hash用法很特别,等于定义一个proc,
  61.           # 每次调用后会如果为空根据这个proc创建一个默认的值
  62.           normalize_paths(paths).each do |load_path|
  63.             Dir["#{load_path}/**/*_controller.rb"].collect do |path|
  64.               next if seen_paths[path.gsub(%r{^/.[///]}, "")] # 如果重复加载 那么忽略
  65.               controller_name = path[(load_path.length + 1)..-1] # 获得controller名字
  66.               controller_name.gsub!(/_controller/.rb/Z/, '')
  67.               @possible_controllers << controller_name
  68.             end
  69.           end
  70.           # remove duplicates
  71.           @possible_controllers.uniq!
  72.         end
  73.         @possible_controllers
  74.       end
  75.       # Replaces the internal list of controllers available to ActionController::Routing with the passed argument.
  76.       #   ActionController::Routing.use_controllers!([ "posts", "comments", "admin/comments" ])
  77.       def use_controllers!(controller_names)
  78.         @possible_controllers = controller_names
  79.       end
  80.       # Returns a controller path for a new +controller+ based on a +previous+ controller path.
  81.       # Handles 4 scenarios:
  82.       #
  83.       # * stay in the previous controller:
  84.       #     controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion"
  85.       #
  86.       # * stay in the previous namespace:
  87.       #     controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts"
  88.       #
  89.       # * forced move to the root namespace:
  90.       #     controller_relative_to( "/posts", "groups/discussion" ) # => "posts"
  91.       #
  92.       # * previous namespace is root:
  93.       #     controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts"
  94.       #
  95.       
  96.       def controller_relative_to(controller, previous)
  97.         if controller.nil?           then previous
  98.         elsif controller[0] == ?/    then controller[1..-1]
  99.         elsif %r{^(.*)/} =~ previous then "#{$1}/#{controller}"
  100.         else controller
  101.         end
  102.       end
  103.     end
  104.     
  105.     Routes = RouteSet.new
  106.     ::Inflector.module_eval do
  107.       # Ensures that routes are reloaded when Rails inflections are updated.
  108.       def inflections_with_route_reloading(&block)
  109.         returning(inflections_without_route_reloading(&block)) {
  110.           ActionController::Routing::Routes.reload! if block_given?
  111.         }
  112.       end
  113.       alias_method_chain :inflections:route_reloading
  114.     end
  115.   end
  116. end






【SCI一区复现】基于配电网韧性提升的应急移动电源预配置和动态调度()—MPS动态调度(Matlab代码实现)内容概要:本文档围绕“基于配电网韧性提升的应急移动电源预配置和动态调度”主题,重点介绍MPS(Mobile Power Sources)动态调度的Matlab代码实现,是SCI一区论文复现的技术资料。内容涵盖在灾害或故障等极端场景下,如何通过优化算法对应急移动电源进行科学调度,以提升配电网在突发事件中的恢复能力与供电可靠性。文档强调采用先进的智能优化算法进行建模求解,并结合IEEE标准测试系统(如IEEE33节点)进行仿真验证,具有较强的学术前沿性和工程应用价值。; 适合人群:具备电力系统基础知识和Matlab编程能力,从事电力系统优化、配电网韧性、应急电源调度等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①用于复现高水平期刊(SCI一区、IEEE顶刊)中关于配电网韧性与移动电源调度的研究成果;②支撑科研项目中的模型构建与算法开发,提升配电网在故障后的快速恢复能力;③为电力系统应急调度策略提供仿真工具与技术参考。; 阅读建议:建议结合前篇“MPS预配置”内容系统学习,重点关注动态调度模型的数学建模、目标函数设计与Matlab代码实现细节,建议配合YALMIP等优化工具包进行仿真实验,并参考文中提供的网盘资源获取完整代码与数据。
一款AI短视频生成工具,只需输入一句产品卖点或内容主题,软件便能自动生成脚本、配音、字幕和特效,并在30秒内渲染出成片。 支持批量自动剪辑,能够实现无人值守的循环生产。 一键生成产品营销与泛内容短视频,AI批量自动剪辑,高颜值跨平台桌面端工具。 AI视频生成工具是一个桌面端应用,旨在通过AI技术简化短视频的制作流程。用户可以通过简单的提示词文本+视频分镜素材,快速且自动的剪辑出高质量的产品营销和泛内容短视频。该项目集成了AI驱动的文案生成、语音合成、视频剪辑、字幕特效等功能,旨在为用户提供开箱即用的短视频制作体验。 核心功能 AI驱动:集成了最新的AI技术,提升视频制作效率和质量 文案生成:基于提示词生成高质量的短视频文案 自动剪辑:支持多种视频格式,自动化批量处理视频剪辑任务 语音合成:将生成的文案转换为自然流畅的语音 字幕特效:自动添加字幕和特效,提升视频质量 批量处理:支持批量任务,按预设自动持续合成视频 多语言支持:支持中文、英文等多种语言,满足不同用户需求 开箱即用:无需复杂配置,用户可以快速上手 持续更新:定期发布新版本,修复bug并添加新功能 安全可靠:完全本地本地化运行,确保用户数据安全 用户友好:简洁直观的用户界面,易于操作 多平台支持:支持Windows、macOS和Linux等多个操作系统
源码来自:https://pan.quark.cn/s/2bb27108fef8 **MetaTrader 5的智能交易系统(EA)**MetaTrader 5(MT5)是由MetaQuotes Software Corp公司研发的一款广受欢迎的外汇交易及金融市场分析软件。 该平台具备高级图表、技术分析工具、自动化交易(借助EA,即Expert Advisor)以及算法交易等多项功能,使交易参与者能够高效且智能化地开展市场活动。 **抛物线SAR(Parabolic SAR)技术指标**抛物线SAR(Stop and Reverse)是由技术分析专家Wells Wilder所设计的一种趋势追踪工具,其目的在于识别价格走势的变动并设定止损及止盈界限。 SAR值的计算依赖于当前价格与前一个周期的SAR数值,随着价格的上扬或下滑,SAR会以一定的加速系数逐渐靠近价格轨迹,一旦价格走势发生逆转,SAR也会迅速调整方向,从而发出交易提示。 **Parabolic SAR EA的操作原理**在MetaTrader 5环境中,Parabolic SAR EA借助内嵌的iSAR工具来执行交易决策。 iSAR工具通过计算得出的SAR位置,辅助EA判断入市与离市时机。 当市场价位触及SAR点时,EA将产生开仓指令,倘若价格持续朝同一方向变动,SAR将同步移动,形成动态止损与止盈参考点。 当价格反向突破SAR时,EA会结束当前仓位并可能建立反向仓位。 **智能交易系统(EA)的优越性**1. **自动化交易**:EA能够持续监控市场,依据既定策略自动完成买卖操作,减少人为情感对交易的影响。 2. **精确操作**:EA依照预设规则操作,无任何迟疑,从而提升交易成效。 3. **风险管控**:借助SA...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值