如何根据rails中的当前作用域修改datagrid上的过滤器

时间:2014-08-08 13:16:42

标签: ruby-on-rails ruby class datagrid module

这是我的众多过滤器之一:

 filter(:item_id, :enum,
         :header => "Category",
         :select => lambda { scope.select(" distinct(category.title), transactions.item_id ").map {|p| [p.title, p.item_id]}},
         :multiple => false,
         :include_blank => true
  ) do |value|
      self.where(:items => { :id => value } )
  end

正如您所看到的那样,它正在调用DB中的类别(所有这些)

在SalesReportController的报告中,我有:

  def index
    user_acls = find_current_user_acls
    @grid = SalesReportsGrid.new(params[:sales_reports_grid]) do |scope|
      scope.where("access_lists.id" => user_acls).page(params[:page])
    end
    @grid.assets

  end

这将为我提供生成Grid并传递给视图的范围。

现在我需要让过滤器仅显示该用户的已售出类别。

我需要做的就是以某种方式将user_acls传递给SalesReportsGrid

如果我可以通过user_acls那么我可以这样做:

 filter(:item_id, :enum,
         :header => "Category",
         :select => lambda { scope.select(" distinct(category.title), transactions.item_id ").where("access_lists.id" => user_acls).map {|p| [p.title, p.item_id]}},
         :multiple => false,
         :include_blank => true
  ) do |value|
      self.where(:items => { :id => value } )
  end

快速解释:

例如:

User1是代理商 她从4个类别中卖出了100件商品。 她进入了报告页面。 目前基于上面的代码,我只向她展示了她自己出售的商品,但是过滤器下拉列表包含了数据库中的所有类别,它们没有任何意义。

不幸的是我的ACL模块有点粒度,当我尝试在SalesReportsGridsales_reports_grid.rb)中扩展它时,我得到一些方法的未定义错误。这是因为我的身份验证模块还有很多来自其他模块的其他方法,比如Devise和Declarative Authorization。所以我不认为延伸将是一个选择。 提前致谢

编辑:

在控制器中:

def index
   # This will return an array of ACL ids for the user
  user_acls = find_current_user_acls 

  @grid = SalesReportsGrid.new(params[:sales_reports_grid].merge(user_acls: user_acls)) do |scope|
      scope.where("access_lists.id" => user_acls).page(params[:page])
  end
  @grid.assets
end

除了我得到的错误:undefined method merge for nil:NilClass

params[:sales_reports_grid]没有任何内容,这就是我收到错误的原因。

当我自己使用这个SalesReportsGrid.new(user_acls: user_acls )时,我得到了结果。

我想这是我的ActiveRecord的限制:(

我已在SalesGrid attr_accessor :user_acls

中添加了此内容

由于

所有工作伙伴:

我能否解释一下这一点,因为我无法理解: 当我添加这个: :select => lambda { scope.select(" distinct(categories.title), transactions.item_id ").where("access_lists.id" => :user_acls).map {|p| [p.title, p.item_id]} }

当我这样做时,

:user_acls值永远不会返回:

 def categories_select
    scope.select(" distinct(category.title), transactions.item_id ").where("access_lists.id" => user_acls).map {|p| [p.title, p.item_id]}

  end

并添加:select => :categories_select一切正常。

干杯。

1 个答案:

答案 0 :(得分:2)

您可以将任何对象传递给Datagrid对象。

例如current_user,ALC对象或可访问的类别。

所以在你的情况下解决方案看起来像:

class SalesReportsGrid
  scope { ... }

  attr_accessor :user_ucls

  filter(:item_id, :enum, select: :categories_select, ...) do
    ...
  end


  def categories_select
    scope.select(" distinct(category.title), transactions.item_id ").where("access_lists.id" => user_acls).map {|p| [p.title, p.item_id]}
  end

end

SalesReportsGrid.new(params.fetch(:sales_reports_grid, {}).merge(user_acls: user_acls))

请注意,要从select选项访问网格对象数据,您需要将其提取到方法中。

您提到的错误是由Nil类限制产生的:nil.merge({})。 为了避免这种情况,请使用fetch方法将默认值添加到哈希,如上例所示。