【问题标题】:Descriptive URL, different pages, but same controller ( domain.com/cars/wheels)描述性 URL,不同的页面,但相同的控制器 (domain.com/cars/wheels)
【发布时间】:2016-05-08 05:12:28
【问题描述】:

同一控制器的自定义路由。我的应用程序中有许多半静态页面(实际上存储在我的数据库中,带有组和页面名称字段),它们按产品分组,然后按主题分组,例如 汽车:轮胎、车轮、收音机、挡风玻璃 住宅:门、窗、屋顶 产品和服务:数据服务

我不希望为每个组创建一个新控制器。但是,我正在尝试获取描述性的不同 URL 路径。例如:

domain.com/cars/tires_and_spokes
domain.com/cars/wheels
domain.com/homes/doors_and_knobs
domain.com/homes/windows
domain.com/products_and_services/data_service

目前,我只有

domain.com/pages/cars_tires_and_spokes
etc.

但我更喜欢前者。

路线:

   pages_from_DB =[ 
           {group:"cars", name:"tires and spokes"}
           {group:"cars", name:"wheels"}
           {group:"homes", name:"tires and spokes"}
           {group:"homes", name:"windows"}
           ]
   pages = %w[
               cars_tires_and_spokes
               cars_wheels
               homes_doors_and_knobs
               homes_windows
               products_and_services_data_service
             ]

   pages.each do |page|          
     get page, controller: "pages", action: page
   end

控制器:

class PagesController < ApplicationController

   pages_from_DB =[ 
       {group:"cars", name:"tires and spokes"}
       {group:"cars", name:"wheels"}
       {group:"homes", name:"tires and spokes"}
       {group:"homes", name:"windows"}
       ]
   pages = %w[
               cars_tires_and_spokes
               cars_wheels
               homes_doors_and_knobs
               homes_windows
               products_and_services_data_service
             ]

  pages.each do |page|          
    define_method(page) do 

    end
  end
end

【问题讨论】:

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


    【解决方案1】:

    看来你错过了nested resources 的意思:

    #config/routes.rb
    resources :groups, path: "", only: [] do
       resources :pages, path: "" #-> url.com/:group_id/:id
    end
    

    这会将任何用户定向到pages 控制器,他们可以将GroupID 从各自的模型中拉到该控制器:

    #app/controllers/pages_controller.rb
    class PagesController < ApplicationController
       def show
          @group = Group.find params[:group_id]
          @page  = @group.pages.find params[:id]
       end
    end
    

    --

    这应该伴随以下模型:

    #app/models/group.rb
    class Group < ActiveRecord::Base
       has_many :pages
    end
    
    #app/models/page.rb
    class Page < ActiveRecord::Base
       belongs_to :group
    end
    

    如果您想用slug(而不是id)处理路线,您需要查看friendly_id

    #Gemfile
    gem "friendly_id"
    
    $ rails generate friendly_id
    $ rails generate scaffold group title:string slug:string:uniq
    $ rails generate scaffold page title:string slug:string:uniq 
    $ rake db:migrate
    
    #app/models/group.rb
    class Group < ActiveRecord::Base
       has_many :pages
    
       extend FriendlyId
       friendly_id :title, use: [:slugged, :finders]
    end
    
    #app/models/page.rb
    class Page < ActiveRecord::Base
       belongs_to :group
    
       extend FriendlyId
       friendly_id :title, use: [:slugged, :finders]
    end
    

    这将允许您使用:

    <%= link_to group_pages_path(@group, @page) %>
    # -> url.com/group-name/page-title
    

    更新

    上面的代码是基于您可以将pages 放入数据库的想法(您应该这样做)。如果你不想这样做,有一个wildcard route可能可以使用:

    #config/routes.rb
    get "*group/:page", to: "pages#show"
    

    如果页面是“半静态的”(仍然不知道这意味着什么),那么您就可以根据需要呈现各种视图:

    #app/controllers/pages_controller.rb
    class PagesController < ApplicationController
       def show
          group = params[:group]
          render "#{params[:group]}/#{params[:page]"
       end
    end
    

    以上将为您提供以下链接:

     url.com/path/to/your/group/this-is-the-page-id
    

    根据您的组/子组结构,它应该使您能够调用各种视图。我不同意,但这显然是你想要的。

    --

    自定义中间件

    我们还创建了具有一些功能的自定义中间件:

    #config/routes.rb
    get "*group/:page", to: PageDispatcher.new
    
    #app/controllers/pages_controller.rb
    class PagesController < ApplicationController
       cattr_accessor :pages #-> PagesController.pages
       @@pages = %w[
                   cars_tires_and_spokes
                   cars_wheels
                   homes_doors_and_knobs
                   homes_windows
                   products_and_services_data_service
                 ]
    end
    
    #lib/page_dispatcher.rb
    class PageDispatcher
    
      #Init
      def initialize(router)
        @router = router
      end
    
      #Env
      def call(env)
        group    = env["action_dispatch.request.path_parameters"][:group]
        page     = env["action_dispatch.request.path_parameters"][:page]
        if PagesController.pages.include? page
          strategy(slug).call(@router, env)
        else
          raise ActiveRecord::RecordNotFound
        end
      end
    
      ##########################################
    
      private
    
      #Strategy
      def strategy(url)
        Render.new(url)
      end
    
      ####################
    
      #Render
      class Render
    
        def initialize(url)
          @url = url
        end
    
        def call(router, env)
          controller  = PagesController 
          action      = "show"
          controller.action(action).call(env)
        end
    
      end
    
      ####################
    
    end
    

    【讨论】:

    • 我有半静态页面,它们不会从数据库中提取出来。嵌套资源部分很有用,但我需要弄清楚如何适应静态页面。
    • 你说的“半静态”是什么意思?
    • 您的意思是它们填充了控制器中的数据集(未绑定到模型)?
    • 为了简化事情,将所有页面视为完全静态的。如果您查看我的控制器,我会引用与视图名称对应的方法。至于组和类别,它们可以像上面一样列在哈希中,不需要数据库。我希望这会有所帮助
    • 当然,我只是想如果它们完全是静态的,最好将它们放入pages db 中,这样您只需调用show 操作即可。这就是我发布我所做的事情的原因。我现在为你添加一个重构
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 2021-10-31
    • 2017-04-05
    • 2017-01-18
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    相关资源
    最近更新 更多