所以我正在构建一个需要基于两种不同类型的路由的Rails站点
我有一个语言模型和一个分类模型
因此,我需要能够使用语言路线/ruby查看顶级ruby资源,还可以访问/书籍查看所有语言的热门书籍
我试过这样的路线
get '/:language',to: "top_voted#language" get '/:category',to: "top_voted#category"
问题是逻辑无法弄清楚两者之间的差异,并在后端引起了一些冲突
我也尝试过这个
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
但问题是我们正在部署它的Heroku不允许在路由中进行数据库调用.有更简单的方法吗?我们需要能够以某种方式动态生成这些路由.
解决方法
使用路径约束可以很好地解决这个问题.
使用路线约束
正如rails routing guide建议的那样,您可以通过检查路径是属于某种语言还是类别来定义路径约束.
# 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? }
订单定义优先级.在上面的示例中,如果语言和类别具有相同的名称,则语言将获胜,因为其路由定义在类别路由之上.
使用永久链接模型
如果你想确保所有路径都是独一无二的,一个简单的方法就是定义一个永久链接模型并在那里使用验证.
生成数据库表:rails generate model永久链接路径: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
并将其与其他对象类型相关联:
class Language < ApplicationRecord has_many :permalinks,as: :reference,dependent: :destroy end
这也允许您为记录定义几个永久链接路径.
rails_category.permalinks.create path: 'rails' rails_category.permalinks.create path: 'ruby-on-rails'
# config/routes.rb # ... get ':language',constraints: lambda { |request| Permalink.where(reference_type: 'Language',path: request[:language]).any? } get ':category',constraints: lambda { |request| Permalink.where(reference_type: 'Category',path: request[:category]).any? }
并且,作为在控制器中使用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