Joe*_*ith 6 ruby routes ruby-on-rails heroku
所以我正在构建一个需要基于两种不同类型的路由的Rails站点
我有一个语言模型和一个分类模型
因此,我需要能够使用语言路线/红宝石查看顶级红宝石资源,还可以访问/书籍查看所有语言的热门书籍
我试过这样的路线
get '/:language', to: "top_voted#language"
get '/:category', to: "top_voted#category"
Run Code Online (Sandbox Code Playgroud)
问题是逻辑无法弄清楚两者之间的差异,并在后端引起了一些冲突
我也尝试过这个
Language.all.each do |language|
get "#{language.name}", to: "top_voted#language", :language => language.name
end
Category.all.each do |category|
get "#{category.name}", to: "top_voted#category", :category => category.name
end
Run Code Online (Sandbox Code Playgroud)
但问题是我们正在部署它的Heroku不允许在路由中进行数据库调用.有更简单的方法吗?我们需要能够以某种方式动态生成这些路由.
使用路径约束可以很好地解决这个问题.
正如rails路由指南所建议的那样,您可以通过检查路径是否属于某种语言或类别来定义路径约束.
# config/routes.rb
# ...
get ':language', to: 'top_voted#language', constraints: lambda { |request| Language.where(name: request[:language]).any? }
get ':category', to: 'top_voted#category', constraints: lambda { |request| Category.where(name: request[:category]).any? }
Run Code Online (Sandbox Code Playgroud)
订单定义优先级.在上面的示例中,如果语言和类别具有相同的名称,则语言将获胜,因为其路由定义在类别路由之上.
如果您想确保所有路径都是独一无二的,那么一种简单的方法就是定义Permalink
模型并在那里使用验证.
生成数据库表: rails generate model Permalink path:string reference_type:string reference_id:integer && rails db:migrate
并在模型中定义验证:
class Permalink < ApplicationRecord
belongs_to :reference, polymorphic: true
validates :path, presence: true, uniqueness: true
end
Run Code Online (Sandbox Code Playgroud)
并将其与其他对象类型相关联:
class Language < ApplicationRecord
has_many :permalinks, as: :reference, dependent: :destroy
end
Run Code Online (Sandbox Code Playgroud)
这也允许您为记录定义几个永久链接路径.
rails_category.permalinks.create path: 'rails'
rails_category.permalinks.create path: 'ruby-on-rails'
Run Code Online (Sandbox Code Playgroud)
使用此解决方案,routes文件必须如下所示:
# config/routes.rb
# ...
get ':language', to: 'top_voted#language', constraints: lambda { |request| Permalink.where(reference_type: 'Language', path: request[:language]).any? }
get ':category', to: 'top_voted#category', constraints: lambda { |request| Permalink.where(reference_type: 'Category', path: request[:category]).any? }
Run Code Online (Sandbox Code Playgroud)
并且,作为使用cancan gem和load_and_authorize_resource
控制器的其他用户的旁注:您必须在调用之前通过永久加载来加载记录load_and_authorize_resource
:
class Category < ApplicationRecord
before_action :find_resource_by_permalink, only: :show
load_and_authorize_resource
private
def find_resource_by_permalink
@category ||= Permalink.find_by(path: params[:category]).try(:reference)
end
end
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3097 次 |
最近记录: |