繁体   English   中英

Rails的路线基于模型属性

[英]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路由相同:

#url.com / businesses /: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.

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