实现datagrid gem&会话助手方法

时间:2015-05-25 14:52:12

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

我是一个尝试实施datagrid gemhttps://github.com/bogdan/datagrid)的新手。不幸的是,我收到三条错误消息:

Error 1: undefined method 'filter' for #<UsersGrid:0x000000044e9400>
Referring to: line `@grid.filter` in def index

Error 2: undefined local variable or method 'user' for #<UsersController:0x007f821f434808>
Referring to: line `link_to view_context.image_tag("delete.gif",...` in the controller.

Error 3: undefined method `image_tag' for UsersGrid:Class
Referring to: line `link_to image_tag(user.avatar.url,` in users_grid.rb
Placing `view_context` in front of link_to in users_grid.rb doesn't work either: undefined local variable or method 'view_context' for UsersGrid:Class.
Also tried `ActionController::Base.helpers.image_tag`. Although that seems to solve the image_tag issue, I then get the error message: `undefined method 'user_path' for #<ActionView::Base:0x007f821d3115b8>` referring to that same line.

删除上面的所有行,表单有效: - )

有关如何更改以下代码以调整这些错误的任何建议吗?

我的代码:安装完gem后我创建了/app/grids/users_grid.rb:

class UsersGrid
  include Datagrid

  scope do
    User.order("users.created_at desc")
  end

  filter(:id, :integer)
  filter(:email, :string) { |value| where('email like ?', "%#{value}%") }
  filter(:organization, :string) { |value| where('organization like ?', "%#{value}%") }
  filter(:verified, :xboolean)
  filter(:created_at, :date, :range => true, :default => proc { [1.month.ago.to_date, Date.today]})

  column(:id)
  column(:avatar) do |user|
    if user.avatar?
      link_to image_tag(user.avatar.url, alt: "Profile"), user_path(user)       #Error3
    else
      link_to image_tag("profile.gif", alt: "Profile"), user_path(user)
    end
  end
  column(:organization)
  column(:verified) do |user|
    image_tag("verifiedaccount.gif", title: "verified") if user.verified
  end
  column(:created_at) do |model|
    model.created_at.to_date
  end
end

用户控制器:

def index
  @grid = UsersGrid.new(params[:users_grid]) do |scope|
    scope.where(admin: false).page(params[:page]).per_page(30)
  end
  @grid.assets
  if (current_user && current_user.admin?)        # This is a Sessions helper method.
    @grid.filter(:activated, :xboolean, :default => true)                    #Error1
    @grid.column(:myadmin, :header => "My admin?") do |user|
      view_context.image_tag("adminamina.png", title: "admin") if user.myadmin
    end
    @grid.column(:activated) do |user|
      user.activated_at.strftime('%v') if user.activated
    end
    @grid.column(:remove) do |user|
      link_to view_context.image_tag("delete.gif", title: "remove"), user, method: :delete,
                                    data: { confirm: "Please confirm" }       #Error2
    end
  end
end

观点:

<%= datagrid_form_for @grid, :method => :get, :url => users_path %>
<%= will_paginate(@grid.assets) %>
<%= datagrid_table(@grid) %>
<%= will_paginate(@grid.assets) %>

1 个答案:

答案 0 :(得分:2)

这个DataGrid似乎或多或少像一个Model类,我认为这是一个重要的提示,他们认真对待面向对象和封装:这个类的内部获胜&#39 ; t自动访问外部世界,您需要手动指定所需的信息。

一种称为依赖注入的技术在这里可能很有用,幸运的是DataGrid似乎对它有很好的支持。引自this wiki page

  

要将对象传递给Grid实例,只需在初始化时将其合并到params散列:

grid = TheGrid.new(params[:the_grid].merge(current_user: current_user))
     

然后,您可以通过声明相应的getter

在Grid对象中访问它
def TheGrid
   ...
   attr_accessor :current_user
   ...
end

因此,当您new向上移动UserGrid对象时,请指定current_user: current_user作为哈希的一部分,然后网格应该可以访问它。

然后您还会遇到另外一个问题:UserGrid对象可以访问current_user,但UserGrid 会赢得,并且您已经拥有了在课堂上写下你的条件。 wiki再次为此提供了答案,它被称为dynamic columns,您可以点击该链接查看几个示例。

一个简短的动态列示例:在控制器中(或者在您创建UserGrid的任何地方),尝试类似下面的内容(再次,在上面的链接中有更多示例):

user_grid = UserGrid.new(same_params_as_before)

# The Grid object has been created, but we can still add columns to it after-the-fact
if current_user && current_user.admin?
  # This block will only execute if the above condition is met. We can
  # define as many extra columns as we feel like here (or change the 
  # user_grid object in any other way we want)
  user_grid.column(:myadmin, header: "My admin?") do |user|
    image_tag("adminamina.png", title: "admin") if user.myadmin
  end

  ...
end

关于这个例子的一些注释:

  • UserGrid对象甚至不需要了解current_user。它并不关心您是管理员;控制器只是决定你是否是管理员,如果是,则对UserGrid对象进行一些更改。
  • 因此,您可以删除UserGrid类中的current_user方法定义,以及引用它的所有代码。
  • 这是错误的面向对象编程的一个示例,因为控制器的任务是管理另一个对象的内部状态(即在某些条件下手动在UsersGrid上定义更多列)。我喜欢这种方法,因为它直接且易于理解,但要注意有更好的方法来组织这些代码,以便所有UserGrid&#34;列定义内容&#34;保存在同一个地方,而不是分散在不同的文件周围。