[英]Rails routes base on model attributes
关于基于模型属性的Rails url选项 ,我有一个建议的解决方案,但是我不确定这是否可以继续。 我还希望基于模型的属性为seo创建路线。 来了
我有一个业务模型,生成的路由是/businesses/id
。 有了friendlyid宝石,它就会成为businesses/slug
但是,我希望路由成为例如/business-type/business-name-and-address
。
因此,请参考Code Connoisseur的博客
# app/models/dynamic_router.rb
class DynamicRouter
def self.load
Ttt::Application.routes.draw do
Business.all.each do |biz|
get "/#{biz.slug}", :to => "businesses#show", defaults: { id: biz.id, name: biz.name, type: biz.type, address: biz.address }
end
end
end
def self.reload
Ttt::Application.routes_reloader.reload!
end
end
# config/routes.rb
DynamicRouter.load
resources :businesses # still preserve old routes for 301 redirect in businesses#show
# app/controller/businesses_controller.rb
def show
@business = Business.cached_find(params[:id])
if request.path != @business.slug
redirect_to @business.slug, :status => :moved_permanently
else
...
end
end
end
# app/models/business.rb
after_save :reload_routes
def normalize_friendly_id text
# slug is changed here and works in conjunction with FriendlyID
# and keeps record of old routes (/business/xxx-xxx) for 301 redirects
"/#{self.type.parameterize}/sg/#{self.name.parameterize}-#{self.address.parameterize}"
end
def reload_routes
if slug.blank? || name_changed? || address_changed? || type_changed?
DynamicRouter.reload
end
end
# app/helper/business_helper and application_controller.rb
# to still be able to use business_path just like the defauilt url_helper,
# override it in the relevant files
def business_path business, options={}
path = ""
path = "#{business.slug}"
# this part can be and should be more robust
if options[:some_param]
path += "?some_param=#{options[:some_param]}"
end
path += "##{options[:anchor]}" if options[:anchor]
return path
end
现在,我可以通过/businesses/xxx
或新的/type/name-address
路由访问business#show页面,前者可以301重定向到后者。
每当创建新业务时,路由将通过after_save回调重新加载,并且将创建到该新业务的新路由,而无需重新加载应用程序。
如果业务再次更新,并且其路由从/type1/name1-address1
更改为/type1/name2-address1
,则第一条路由将成为死链接。 为了解决这个问题,我使用了high_voltage gem,并覆盖了invalid_page
方法,将这条路线重定向回了businesss#show
# app/controller/pages_controller
class PagesController < ApplicationController
include HighVoltage::StaticPage
def invalid_page
slug = FriendlyId::Slug.find_by_slug("/" + params[:id])
if slug && slug.sluggable_type == "Business"
redirect_to slug.sluggable.slug, :status => :moved_permanently
else
raise ActionController::RoutingError, "No such page: #{params[:id]}"
end
end
end
end
这样做可以实现我想要的目标,但是我不确定这是否是可行的方法。 首先,此方法将创建与业务表中的行数一样多的路由。 这是否会对应用程序的性能或其他方面产生不利影响?
希望收到大家的来信!
和生成的路线(使用
friendlyid
gem)
生成的路由仍然与没有friendly_id
路由相同:
不同之处在于friendly_id
引入了几种非常酷的方法,这些方法会用您的slug
来填充路径帮助程序和查询( 查找器 ):)
因此,实际上,您仍在将params[:id]
传递给控制器。
只是想清除它。
我希望路线变为
/business-type/business-name-business-address
简单的解决方案是在db(改变塞的情况下自定义蛞蝓 ):
#app/models/business.rb
class Business < ActiveRecord::Base
extend FriendlyId
friendly_id :name_and_address, use: :slugged
def name_and_location
"#{name}-#{address}"
end
end
给出的示例如下:
bob = Person.create! :name => "Bob Smith", :location => "New York City"
bob.friendly_id #=> "bob-smith-from-new-york-city"
如果这样做,则可以通过在cmd
运行以下命令来影响数据库中的更改:
$ rails c
$ Business.find_all(&:save)
关于您的动态路线-它们可能会起作用,但是看起来很hacky。
如果您想让我评论自定义代码,我会写一个更新。 我认为以上将实现您想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.