【问题标题】:How to have a gem controller handle multiple arbitrary models?如何让 gem 控制器处理多个任意模型?
【发布时间】:2011-06-06 19:51:36
【问题描述】:

我有四个模型,我允许四个独立的评论控制器对它们进行评论。这四个评论控制器的作用基本相同,只是略有不同。

为了消除四个基本相同的注释控制器的重复,我创建了一个 Rails 引擎作为 gem 来任意处理对我在 routes.rb 中指定的任意模型的评论。

所以我现在可以在我的 routes.rb 文件中使用:

comments_on :articles, :by => :users

cmets_on 在我的 gem 中实现如下:

def comments_on(*resources)
  options = resources.extract_options!

  [snip of some validation code]

  topic_model = resources.first.to_s
  user_model = options[:by].to_s

  # Insert a nested route
  Rails.application.routes.draw do
    resources topic_model do
      resources "comments"
    end
  end
end

路由显示在“rake routes”中,请求正确地路由到我的 gem 的“CommentsController”,但这就是我的 gem 功能结束的地方。

在我的 gem CommentsController 中检测上下文的最佳方法是什么,以便我可以处理特定于 cmets_on 调用方式的请求?

更具体地说,我将如何实现如下所示的索引操作,使其具有上下文感知能力?

def index
  @article = Article.find(params[:article_id])
  @comments = ArticleComment.find(:all, :conditions => { :article_id => @article.id })
end

感谢您的帮助!

【问题讨论】:

    标签: ruby ruby-on-rails-3 metaprogramming gem


    【解决方案1】:

    您可以将主题指定为路由中的额外参数:

    Rails.application.routes.draw do
      resources topic_model do
        resources "comments", :topic_model => topic_model.to_s
      end
    end
    

    那么你的控制器可以这样写:

    def index
      @topic = topic
      @comments = topic.comments
    end
    
    protected
    def topic
      m = params[:topic_model]
      Kernel.const_get(m).find(params["#{m.underscore}_id"])
    end
    

    您也可以将大量逻辑移出控制器并移入模型。 topic.comments 可以是所有这些模型都应该实现的命名范围。

    我过去做过类似的模式,但通常有一个极端情况会打破这个想法,你最终会做比明智的更多的“元”编程。

    我建议制作一个基本控制器,然后制作从该控制器继承的简单控制器,或者尝试将这些常见行为拆分为模块。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-21
      • 1970-01-01
      • 2014-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多