不确定这是否是一个合适的问题,请原谅我。
我在控制器操作中有以下代码
unless @users.empty?
book = Spreadsheet::Workbook.new
sheet1 = book.create_worksheet :name => 'export'
sheet1.row(0).concat ["Label1", "Label2", "Label3"]
@users.each_with_index do |e, i|
sheet1.row(i+1).concat([e.field1, e.field2, e.field3])
end
require 'stringio'
data = StringIO.new ''
book.write data
send_data data.string, :type=>"application/excel", :disposition=>'attachment', :filename => "export_#{l(Date.today)}.xls"
end
这允许我在运行导出的表单上有一个按钮。虽然这非常有用,但我在整个地方使用此代码。实际上,我在应用程序中的各种控制器中有19个此代码实例。有没有办法可以将此代码移动到另一个文件,并将标签和字段的哈希值传递给它,这样我只需要维护一个导出代码实例?
感谢
答案 0 :(得分:0)
MVC
的基础是尽可能多的皮肤控制器,你的情况就是完美的例子,以防止重复你的代码。
解决方案是将代码移至models
M
模式中的MVC
,它负责所有业务逻辑。
将此方法移至module
。
在app/models/concers/
文件夹中创建新文件sheetable.rb
require 'active_support/concern'
module Sheetable
extend ActiveSupport::Concern
module ClassMethods
def new_sheet objects
unless objects.empty?
book = Spreadsheet::Workbook.new
sheet1 = book.create_worksheet :name => 'export'
sheet1.row(0).concat ["Label1", "Label2", "Label3"]
objects.each_with_index do |e, i|
sheet1.row(i+1).concat([e.field1, e.field2, e.field3])
end
require 'stringio'
data = StringIO.new ''
book.write data
end
end
end
end
现在在module
中添加model
,它将会有method
new_sheet
个分组。
class User < ActiveRecord::Base
...
include Sheetable
...
end
或其他模型
class OtherModel < ActiveRecord::Base
...
include Sheetable
...
end
使用此
data = User.new_sheet(@users) # or OtherModel.new_sheet(@other_models)
if data
send_data data.string, :type=>"application/excel", :disposition=>'attachment', :filename => "export_#{l(Date.today)}.xls"
end
现在您已将逻辑移至model
下一步是重构此方法,使其更简单。
答案 1 :(得分:0)
我首先将代码移到责任所在的位置。您似乎正在将某组用户的数据导出到电子表格中。所以我将代码移到User类,例如
def self.export_subset_to_spreadsheet(users)
... your code ...
end
然后使用User.export_subset_to_spreadsheet(@users)
从控制器中调用它。
这是第一步。你当然可以从那里进一步发展,但至少这可以让你摆脱最紧迫的问题:整个代码块的19个重复。