简体   繁体   English

Rails命名为具有动态段的路由从模型生成URL

[英]Rails named route with dynamic segments URL generation from model

Ruby on Rails 4.2+ only, please! 请关注Ruby on Rails 4.2+!

I've been looking all over for tips on how to make URLs pretty in Rails, and I'm struggling to see a solution I like. 我一直在寻找有关如何在Rails中创建URL的技巧,我很难看到我喜欢的解决方案。

What I want: 我想要的是:

Hypothetical example: given Topic, Course, etc. models that have a bunch of fields (including URL-friendly slugs), I want to be able to 假设的例子:给定主题,课程等具有一堆字段(包括URL友好的slu)的模型,我希望能够

# ../routes.rb
# Match urls of the form /edu/material-engineering. These are read-only
# public URLs, not resources.
get 'edu/:slug', to: 'education#topic', as: :learn_topic
get 'edu/course/:id/slug', to: 'education#course', as: :learn_course
...

# I also have admin-only resource-oriented controllers for managing
# the content, but that's separate.
namespace :admin do
  resource :topic
  resource :course
  ...
end

# ../some_view.html.erb
# Generate URLS like this:
<%= link_to topic.name, learn_topic_path(topic) %>
<%= link_to course.name, learn_course_path(course) %>

What I don't want: 我不想要的:

  • Messing with to_param . to_param That's a dirty hack and completely breaks separation of concerns. 这是一个肮脏的黑客,完全打破了关注点的分离。
  • Resource/RESTful routing. 资源/ RESTful路由。 There are no CRUD operations here other than "read." 除了“读取”之外,这里没有CRUD操作。
  • link_to 'text', course_path(id: course.id, slug: course.slug) . link_to 'text', course_path(id: course.id, slug: course.slug) This completely defeats the purpose of not requiring views to know what params are required to generate a URL for a course. 这完全违背了不要求视图知道生成课程URL所需的参数的目的。
  • EDIT : I know FriendlyId exists, but I'm precisely trying to understand how this sort of thing can be done and what the mechanics are, so that's not a solution for now. 编辑 :我知道FriendlyId存在,但我正在努力理解这种事情是如何完成的以及机制是什么,因此现在不是解决方案。

There has to be a way to tell the named route helper topic_path(topic) to take the required parameters in the route (eg, :slug , :id , whatever else) from the topic model object. 必须有一种方法可以告诉命名的路由助手topic_path(topic)在主题模型对象中获取路径中所需的参数(例如:slug:id ,无论如何)。

Anybody know? 有人知道吗? Thanks! 谢谢!

You can use FriendlyId gem to achieve that. 您可以使用FriendlyId gem来实现这一目标。

Here's the link: 这是链接:

https://github.com/norman/friendly_id/blob/master/README.md https://github.com/norman/friendly_id/blob/master/README.md

Let me know if you have questions. 如果您有疑问,请告诉我。

The best I've been able to come up with: just override the *_path helpers with my own implementation. 我能想到的最好的:用我自己的实现覆盖*_path助手。

If you know a way to make the default helpers work, please chime in! 如果您知道如何使默认助手工作,请加入!

This problem boils down to one issue: the auto-generated *_path and *_url helpers don't give me the flexibility I want. 这个问题归结为一个问题:自动生成的*_path*_url助手不能给我我想要的灵活性。 What I want them to do is trivial, so without another option, I can just write my own: 我希望他们做的是微不足道的,所以没有其他选择,我可以自己编写:

module ApplicationHelper
  def learn_topic_path(topic)
    "/edu/#{topic.slug}"
  end

  ...
end

Writing a few _path/_url helper overrides avoids all kinds of complication, and allows you to keep out of to_param, avoid including new plugins, etc. 编写一些_path / _url帮助程序覆盖可避免各种复杂化,并允许您远离to_param,避免包含新插件等。

One could probably go another step forward and generate the static components of the route from known routing rules, as well as infer what attributes one needed to extract from a model if the dynamic segment names line up to the model attribute names, but that starts to break down once you do more complicated things or add multiple models (eg, 'edu/:topic_slug/:course_slug'). 人们可能会向前迈出一步,从已知的路由规则生成路由的静态组件,并推断出如果动态段名称与模型属性名称对齐,则需要从模型中提取哪些属性,但是一旦你做了更复杂的事情或添加多个模型(例如,'edu /:topic_slug /:course_slug'),就会分解。

The big downside to doing this is that you now have to update routes in two places every time you change them: the route definition itself in routes.rb as well as the corresponding route helper in application_helper.rb . 大缺点这样做是你现在在每一个你改变他们的时间两个地更新路线:路线定义本身在routes.rb以及在相应的路由帮手application_helper.rb I can live with that for now. 我现在可以忍受。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM