【问题标题】:Rails Metaprograming/Refactoring/DRYing the controllerRails 元编程/重构/干燥控制器
【发布时间】:2014-08-12 15:47:18
【问题描述】:

我有一个有几个动作的控制器。许多人遵循这种模式:

def favorites
  @favorites = Favorite.where(organization_id: @resource.id).page(params[:page]).per(50)
end

不仅仅是收藏夹,还有下载、搜索、列表等,它们都非常相似,以至于我想创建一个可以在 before_filter 中调用的方法。像这样的:

def set_instance_variable
  subject = __method__
  class = __method__.singularize.constantize
  instance_variable = self.class.instance_variable_set("@#{subject}", "#{class}.where(organization_id: @resource.id).page(params[:page]).per(50)")
end

这里的语法可能有点偏离,但我知道这不会起作用,因为__method__ 将始终是 set_instance_variable 而不是调用它的父方法。

有没有办法根据定义实例变量的方法动态设置实例变量?上面的这个例子是否在正确的轨道上?

【问题讨论】:

  • 在我看来像has_many 关联(尤其是您在下面提到的OrganizationsController)。如果您定义了它,您将能够在before_filter 中设置@resource (@organization),然后调用@resource.favorites、@resource.downloads 等。

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


【解决方案1】:

我喜欢 CanCan 库处理这个问题的方式。使用 CanCan,您可以在控制器顶部调用类方法:

load_resource

CanCan接着看:

  • 您正在采取的行动来确定您想要一个集合还是单一资源,

  • 确定要加载的类的控制器名称

  • 添加范围的授权规则,例如您的 organization_id 限制(cancan 也是用于定义这些范围的库)

我认为分页和资源加载是分开的事情,你不应该把它们放在同一个方法中。我会为这样的界面拍摄:

class FavoritesController
  load_resource
  paginate_resource only: [:index]

  def show
    # @favorite loaded here
  end

  def index
    # @favorites loaded and paginated here
  end
end

https://github.com/CanCanCommunity/cancancan/blob/develop/lib/cancan/controller_resource.rb#L29

如果在您的应用程序中拥有非 RESTful 资源更有意义,那么您就不能重用基于约定的东西 cancan 而是必须定义自己的函数。考虑这样的事情:

def favorites
  @favorites = load_resource Favorite
end


private

def load_resource(klass)
  klass.where(organization_id: @resource.id).page(params[:page]).per(50)
end

【讨论】:

  • 嗯,很有趣。我会调查一下。一个直接的担忧是所有这些操作都在 OrganizationsController 中,而不是在 FavoritesController 中。这不是一个典型的脚手架控制器,也许这会增加问题。也许与康康无关?
  • 好吧,如果您遵循标准约定,那么最容易干燥并重新使用东西。收藏夹资源通常是收藏夹控制器的索引操作,而不是另一个控制器中的单独非 RESTful 资源。
  • 谢谢。这是一个很好的妥协。我必须为每个动作设置实例变量,但至少它作为一条更小的线看起来会更好。也许根据动作猜测类名并将其放入前置过滤器会使事情变得过于复杂。我可以接受这个解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-24
  • 2019-03-09
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多