ruby-on-rails – 基于数据库模型的动态Rails路由

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 基于数据库模型的动态Rails路由前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
所以我正在构建一个需要基于两种不同类型的路由的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'

使用此解决方案,routes文件必须如下所示:

# 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

猜你在找的Ruby相关文章