【问题标题】:Rails routes base on model attributes基于模型属性的 Rails 路由
【发布时间】:2016-01-23 20:29:10
【问题描述】:

关于Rails url options based on model attribute,我有一个建议的解决方案,但我不确定这是否是继续的方法。我还希望根据模型的属性创建路由以用于 seo 目的。就这样吧。

我有一个商业模式,生成的路由是/businesses/id。使用friendlyid gem,变成businesses/slug

但是,例如,我希望路由变为/business-type/business-name-and-address

所以参考Code Connoisseur's blog

# 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 方法以将这条路线重定向回business#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

这样做可以让我实现我想要的,但我不确定这是否是要走的路。一方面,此方法将创建与业务表中的行数一样多的路由。如果有的话,这会对应用程序的性能或其他方面产生不利影响吗?

希望收到大家的来信!

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 routes


    【解决方案1】:

    以及生成的路由(使用friendlyid gem)

    生成的路由仍然和没有friendly_id时一样:

    不同之处在于friendly_id 引入了几个非常酷的方法,这些方法用您的slug 填充路径帮助器和查询 (finders) :)

    所以实际上,您仍然params[:id] 传递给您的控制器。

    只是想澄清一下。


    我希望路由变成/business-type/business-name-business-address

    简单的解决方案是更改数据库中的 slug (custom slugs):

    #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)
    

    关于您的动态路线 - 它们可能有效,但看起来非常糟糕。

    如果你想让我批评自定义代码,我会写一个更新;我认为以上将实现您想要的。

    【讨论】:

    • 嗨,Rich,感谢您的 cmets。对于friendlyId,它不会摆脱业务名称空间吗?它仍然会给出/business/type/name_and_address 而不是/type/name_and_address。我还覆盖了normalize_friendly_id,因为friendlyid 参数化了方法中的斜线。
    • 不,它没有——我试图证明friendlyID 对路线没有影响,除了用slug 属性而不是id 填充你的path_helper
    猜你喜欢
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-05
    相关资源
    最近更新 更多