实施数据网格 gem 和会话辅助方法
Implementing datagrid gem & session helper methods
我是一个尝试实现 datagrid gem
(https://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) %>
这个 DataGrid 的设置似乎或多或少像一个模型 class,我认为这是一个重要的暗示,表明他们认真对待面向对象和封装:[=47= 的内部结构] 不会自动访问外部世界,您需要手动指定您需要的信息。
一种叫做 依赖注入 的技术在这里可能会有用,幸运的是 DataGrid 似乎对它有很好的支持。引自 this wiki page:
To pass an object to the Grid instance, simply merge it to the params hash on initialization:
grid = TheGrid.new(params[:the_grid].merge(current_user: current_user))
You can then access it in the Grid object by declaring the corresponding getter
def TheGrid
...
attr_accessor :current_user
...
end
因此,当您 new
创建 UserGrid 对象时,将 current_user: current_user
指定为散列的一部分,那么网格应该可以访问它。
然后你会遇到另一个问题:UserGrid 对象将有权访问 current_user
,但 UserGrid class 不会,并且您已经在 class 级别编写了条件。 wiki 再次对此有一个答案,它称为 dynamic columns,您可以单击 link 查看几个示例。
一个简短的动态列示例:在控制器(或您创建 UserGrid 的任何地方)中,尝试类似以下的操作(同样,上面的更多示例 link):
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 class 中的
current_user
方法定义,以及引用它的所有代码。
- 这是一个糟糕的面向对象编程的例子,因为控制器的任务是管理另一个对象的内部状态(即在某些特定的情况下手动在 UsersGrid 上定义更多列)状况)。我喜欢这种方法,因为它直接且更容易理解,但请注意,有更好的方法来组织此代码,以便所有 UserGrid“列定义内容”都保存在同一位置,而不是分散在不同的文件中。
我是一个尝试实现 datagrid gem
(https://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) %>
这个 DataGrid 的设置似乎或多或少像一个模型 class,我认为这是一个重要的暗示,表明他们认真对待面向对象和封装:[=47= 的内部结构] 不会自动访问外部世界,您需要手动指定您需要的信息。
一种叫做 依赖注入 的技术在这里可能会有用,幸运的是 DataGrid 似乎对它有很好的支持。引自 this wiki page:
To pass an object to the Grid instance, simply merge it to the params hash on initialization:
grid = TheGrid.new(params[:the_grid].merge(current_user: current_user))
You can then access it in the Grid object by declaring the corresponding getter
def TheGrid ... attr_accessor :current_user ... end
因此,当您 new
创建 UserGrid 对象时,将 current_user: current_user
指定为散列的一部分,那么网格应该可以访问它。
然后你会遇到另一个问题:UserGrid 对象将有权访问 current_user
,但 UserGrid class 不会,并且您已经在 class 级别编写了条件。 wiki 再次对此有一个答案,它称为 dynamic columns,您可以单击 link 查看几个示例。
一个简短的动态列示例:在控制器(或您创建 UserGrid 的任何地方)中,尝试类似以下的操作(同样,上面的更多示例 link):
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 class 中的
current_user
方法定义,以及引用它的所有代码。 - 这是一个糟糕的面向对象编程的例子,因为控制器的任务是管理另一个对象的内部状态(即在某些特定的情况下手动在 UsersGrid 上定义更多列)状况)。我喜欢这种方法,因为它直接且更容易理解,但请注意,有更好的方法来组织此代码,以便所有 UserGrid“列定义内容”都保存在同一位置,而不是分散在不同的文件中。