Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby Rails元编程/重构/干燥控制器_Ruby_Ruby On Rails 4_Metaprogramming - Fatal编程技术网

Ruby Rails元编程/重构/干燥控制器

Ruby Rails元编程/重构/干燥控制器,ruby,ruby-on-rails-4,metaprogramming,Ruby,Ruby On Rails 4,Metaprogramming,我有一个控制器,有几个动作。许多人遵循这一模式: def favorites @favorites = Favorite.where(organization_id: @resource.id).page(params[:page]).per(50) end 它不仅是收藏夹,还有下载、搜索、列表等,它们都非常相似,我想创建一个方法,可以在before_过滤器中调用。大概是这样的: def set_instance_variable subject = __method__ clas

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

def favorites
  @favorites = Favorite.where(organization_id: @resource.id).page(params[:page]).per(50)
end
它不仅是收藏夹,还有下载、搜索、列表等,它们都非常相似,我想创建一个方法,可以在before_过滤器中调用。大概是这样的:

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
class FavoritesController
  load_resource
  paginate_resource only: [:index]

  def show
    # @favorite loaded here
  end

  def index
    # @favorites loaded and paginated here
  end
end
def favorites
  @favorites = load_resource Favorite
end


private

def load_resource(klass)
  klass.where(organization_id: @resource.id).page(params[:page]).per(50)
end
这里的语法可能有点不对劲,但我知道这不起作用,因为
\uuuuuuuuuuuuuuuuuuuuuuu方法
总是设置为\u instance\u变量,而不是调用它的父方法


有没有一种方法可以根据定义实例变量的方法动态设置它们?上面的例子正确吗?

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

load_resource
坎坎接着看:

  • 用于确定是否需要集合或单一资源的操作

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

  • 用于添加范围的授权规则,如您的组织\u id限制(cancan也是定义这些范围的库)

我认为分页和资源加载是分开的,不应该将它们放在同一个方法中。我想要一个这样的界面:

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
class FavoritesController
  load_resource
  paginate_resource only: [:index]

  def show
    # @favorite loaded here
  end

  def index
    # @favorites loaded and paginated here
  end
end
def favorites
  @favorites = load_resource Favorite
end


private

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

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

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
class FavoritesController
  load_resource
  paginate_resource only: [:index]

  def show
    # @favorite loaded here
  end

  def index
    # @favorites loaded and paginated here
  end
end
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资源。谢谢。这是一个很好的妥协。我必须为每个操作设置实例变量,但至少它看起来更像是一个较小的行。也许基于动作猜测类名并将其放入before过滤器过于复杂了。我可以接受这个解决方案。看起来
与我有很多关联(特别是你在下面提到的
组织控制器
)。如果您定义了它,您将能够在筛选之前在
中设置
@resource
@organization
),然后调用
@resource.favorites
@resource.downloads
等。