瞎扯淡 关于 Rails 的 routes.rb 中路由的两种写法

mukewells · 2016年07月14日 · 最后由 mukewells 回复于 2016年07月17日 · 4193 次阅读

最新购买安道翻译的最新的Ruby on Rails 教程(原书第 4 版)中关于路由的写法:


Rails Guides

这个和我一开始学习 Rails 时购买的 Ruby on Rails 教程(第 3 版。涵盖 4.2, 安道翻译)中的写法:

个人是比较偏向下面 (第 3 版) 的写法;但是疑惑的是这种写法的变化会带来什么好处么?还是仅仅只是提供多一种不同的写法而已

as 有额外的功能,设置别名,比如 users/index 是 users_path,你 as: 'xxx' ,你就可以用 xxx_path 了。不是写法的问题,这是个功能。

@catherine 是我问题没描述好! 其实想知道:

# Rails4.2

get  'help'    => 'static_pages#help'
# Ralis5

get  '/help', to: 'static_pages#help'

上面的写法过渡到下面的写法的这种变化有什么好处?还是仅仅只是提供多一种不同的写法而已?

#2 楼 @mukewells 其实我也有过这个疑问,后来慢慢看到 Rails 有很多这样的用法。

单对于这个,一般这么操作: 如果一个路由我只想指定一个 path,就直接

get  'path'    => 'controller#action'

如果还想指定其他参数,如将 path 别名与路径分开(不想默认),就用这种

get  'path', to: 'controller#action', as: 'name'

总结:多参数使用 to,一个参数可以考虑=>代替(更方便,少写点代码)

#3 楼 @pinewong 明白了!谢谢啊😄

keyword arguments 从 ruby 2 开始就是被推荐的参数表风格. 好处来讲,keyword arguments 更方便的定义长可选参数表。另外在调用的时候也更具有可读性,这一点适合用来做 DSL.

PS: 能尽量避免写 rocket syntax 就尽量避免。既不好看也不简洁。1.9 的风格指导开始就尽量淘汰这种写法。2.2 以后更是支持

{'@a#complex%whatever.long___string__': true}

这种方式写 literal hash. 对于 string 和 symbol 区分不敏感的 kv 对都建议用新字面量定义方式。

#5 楼 @karloku 原来还有这层原因存在; 学到东西了,谢谢你的回答!

看看get的源码:

# https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/routing/mapper.rb#L650

def get(*args, &block)
  map_method(:get, args, &block)
end

你说的两种写法传递的参数是不同的

get 'path', to: "controller#action"
# args = ["path", {:to => "controller#action"}]

get 'path' => 'controller#action'
# args = [{"path" => "controller#action"}]

往深一步看:

# https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/routing/mapper.rb#L687

def map_method(method, args, &block)
  options = args.extract_options!
  options[:via] = method
  match(*args, options, &block)
  self
end

# https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/routing/mapper.rb#L1470

# match 'path' => 'controller#action'
# match 'path', to: 'controller#action'
# match 'path', 'otherpath', on: :member, via: :get
def match(path, *rest)
    ......
end

match方法太长就不贴了,extract_options!是 rails 给 Array 扩展的方法,若数组对象最后一个元素是 hash 对象,就对这个数组调用pop并返回pop的返回值。实际上get是在match方法上做了一层封装。这样的话这两种写法传到match方法的参数是这样的:

get 'path', to: "controller#action"
# path = "path"
# rest = [ { :to => "controller#action", :via => :get } ]
# 等于调用了 match "path", to: "controller#action", via: :get

get 'path' => 'controller#action'
# path = {"path" => "controller#action", :via => :get}
# rest = []
# 等于调用了 match "path" => "controller#action", via: :get

然后match方法对这两张情况都做了处理,在这一段。实际上这两张写法都是一样的。不过正如 5 楼说的,ruby 从 1.9 后加入了{ key: 'value' }这样的写法并推荐这样写,所以推荐上面那种写法

#7 楼 @aczero 原来底层是这么实现的,多谢了!

mukewells 关闭了讨论。 11月10日 16:13
mukewells 重新开启了讨论。 11月10日 16:13
需要 登录 后方可回复, 如果你还没有账号请 注册新账号