2015-11-02 32 views
1

我在构建使用Article模型的博客,以支持具有自己的索引页的两种不同的文章类型。我试图按照Hubspot为管理目的使用单一模型的方式进行设置(类型之间的唯一区别是目标受众,因此它是表单中的下拉列表)。在Rails中通过基于属性的子目录进行路由

我希望url别名路由到/foo/:article_id/bar/:article_id,具体取决于@article.type属性的值。

这可以通过导轨路线和单个模型/控制器实现吗?

我曾尝试:

resources :articles, :path => "foo" 
resources :articles, :path => "bar" 

其工作原理,但:

  1. 我卡检查中展现动作的URL和article.type,以确定它是否是一个foobar这没有按看起来并不理想。

  2. 我不希望能够发布foo文章,并能够通过访问/bar/:foo_article_id来查看它,这可以在这里完成。

  3. 它使用一个单一的索引操作,这意味着视图格式化将有一堆基于类型感觉hacky的条件。

是否有其他解决方案没有这些缺点?

回答

0

首先,什么你指的是一种叫Single Table Inheritance:(!对于任何谷歌搜索的引用)

#app/models/article.rb 
class Article < ActiveRecord::Base 
    # needs a "type" column 
end 

#app/models/foo.rb 
class Foo < Article 
end 

#app/models/bar.rb 
class Bar < Article 
end 

都将使用文章表。


对此有几种修复方法。

您的主要问题是控制器

你一直在试图确定使用哪种控制器结构。如果您使用上述设置(,那么您的不需要更改模型中的任何内容),您将能够明确区分这两种模型。唯一剩下的就是确定使用哪条路线。

要简洁,我会用我自己的模块找到ArticlePost,并发送请求到控制器:

#config/routes.rb 
%w(foo bar).each do |o| 
    get "/#{o}/:id", to: Dispatcher.new(self), as: o.to_sym #-> url.com/foo/1 & url.com/bar/2 
end 

#lib/dispatcher.rb 
class Dispatcher 

    #http://blog.arkency.com/2014/01/short-urls-for-every-route-in-your-rails-app/ 
    ########################################## 

    #Init 
    def initialize(router) 
    @router = router 
    end 

    #Env 
    def call(env) 
    id  = env["action_dispatch.request.path_parameters"][:id] 
    model = env["action_dispatch.request.path"].gsub("/", "") #-> /foo 
    record = model.titleize.constantize.find id #-> looks up in the specific model (foo/bar) 

    if record 
     ArticlesController.action("show").call(env) 
    else 
     raise ActiveRecord::RecordNotFound 
    end 
    end 

end 

最后,你就可以通过以下为articles#show操作:

#app/controllers/articles_controller.rb 
class ArticlesController < ApplicationController 
    def show 
     model = request.path.gsub("/", "") #-> "foo" 
     @article = model.titleize.constantize.find params[:id] 
    end 
end 
+0

感谢您的支持。尽管您引用的文件位于'lib'文件夹中,我还是得到了一个“未初始化的常量Dispatcher”。它是否需要位于其他地方与项目一起加载? – UserDuser

+0

您可能需要将此添加到'config/application.rb' - 'config.autoload_paths + = Dir [“#{config.root}/lib”]':) –

0

有三个ActiveRecord的模式,而不是一个: ArticleFooArticleBarArticle

Article模式应该包含所有的属性和代码是常见的两种,它不应该有任何的控制器或意见

FooArticle模型和BarArticle模型都应参考Article,has_one关系,并使用delegate关键字将Article的功能映射到更具体的版本。然后,您可以为Foo和Bar分别设置控制器和视图,但在一个模型中具有所有功能和代码。

有可能有一个Foo和一个酒吧都参考相同的文章,所以你可能不得不小心。

相关问题