在STI模型上设置作者字段的最佳方法是什么

时间:2013-11-06 17:48:44

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

我有一个名为Page的基本模型,并且有很多基于页面的STI模型,例如

绘图

故事

等...

我为每个STI模型都有单独的控制器和视图,因为我需要根据模型类型自定义视图层,并为控制器和独立的控制器设置不同的逻辑。但是,我需要将所有模型的作者字段设置为当前用户。我如何在一个地方做到这一点?

例如,如果我在Page控制器上使用before_action并设置作者,它会影响@page实例变量,而我的DrawingsController正在使用@drawing,所以它不会保存我@drawing的作者,除非我在DrawingsController中重复相同的代码

修改

我的控制器层次结构是

DrawingsController< PagesController

PagesController< ApplicationController中

PagesController和DrawingsController都有7个restful动作。但是,PagesController上的操作没有任何用途,因为我不想让任何用户创建Pages。我只希望他们创建像Drawings这样的继承的STI类。

2 个答案:

答案 0 :(得分:0)

您可以使用控制器层次结构中的一些约定和元编程来执行此操作:

def add_author
  model = instance_variable_get(:"@#{controller_name.singularize}")
  model.author = current_user
end

答案 1 :(得分:0)

我说实话,我不保证这个答案的最佳实践" - 但是如果它在某种程度上有所帮助,我会建议它。还要注意,在重新思考问题后,我意识到我在评论中的第一个建议的解决方案是错误的,第二个也不是很正确。所以我只发布了第二个建议的修改版本:

简答:PagesController处理大部分工作,并根据需要委托给特定于模型的东西的子控制器。正如phoet所说,你可以使用一些元编程(以不同的方式)来实现这一点。

class PagesController < ApplicationController
    # pages controller stuff here
    def create
        @page = controller_name.classify.constantize.new(params[:page_params]) # I love Rails, don't you?
        @page.author = current_user
        handle_additional_create_actions 

        # For completeness of this example...
        if @page.save
            # render / redirect on success
        else
            # render errors
        end
    end
protected

    # This method should be overwritten by sub controllers if needed
    # Also, name this whatever you like, this is merely a verbose example for illustration purposes
    def handle_additional_create_actions
        # in the pages controller, this method does nothing
    end
end

并且,如果特定于模型的控制器需要执行其他操作:

class DrawingsController < PagesController
    # drawing controller stuff here

protected
    def handle_additional_create_actions
        @page.some_other_field = some_other_data
    end
end

快速说明:请注意,在我的建议中,您要删除特定于模型的变量名称,这意味着我们没有@drawing@article等,了。您的模型基本上都是Page个对象的类型,因此我们将通过其通用名称作为约定来调用它。这样,当您要求DrawingsControllerDrawing类执行特定操作时,它知道可以通过我们通常命名的@page对象访问实例。

所以最终,PagesController完成了繁重的任务,无论你处理哪种具体的模型类型。这样,在页面控制器中只能找到一般页面内容,并且在各自的具体控制器中可以找到绘图,文章或故事特定的内容。