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



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

绘图

故事

等。。。

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

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

编辑:

我的控制器层次结构是

图纸控制器 <页面控制器>

页面控制器<应用程序控制器>

PagesController 和 DrawingsController 都有所有 7 个 restful 动作。但是,PagesController 上的操作没有任何用途,因为我不希望我的任何用户创建页面。我只希望他们创建继承的 STI 类,如绘图。

您可以在

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

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

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

简短回答: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都会完成繁重的工作。这样,在页面控制器中只能找到常规页面内容,而在各自的具体控制器中找到特定于绘图、文章或故事的内容。

相关内容

最新更新