[英]drying up rails controller code for data export
Not sure if this is an appropriate question so forgive me. 不知道这是否是一个适当的问题,请原谅。
I have the following code in a controller action 我在控制器操作中有以下代码
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
This allows me to have a button on a form that runs an export. 这使我可以在运行导出的表单上有一个按钮。 Whilst this is very useful, I am using this code all over the place.
尽管这非常有用,但我在各处都使用此代码。 In fact, I have 19 instances of this code across various controllers in the app.
实际上,我在应用程序的各个控制器上有19个此代码实例。 Is there a way I can move this code to another file, and pass into it a hash of the labels and fields so that I only have to maintain one instance of the export code?
有没有一种方法可以将这段代码移到另一个文件,然后将标签和字段的哈希值传递给它,这样我只需要维护导出代码的一个实例?
thanks 谢谢
Basic of MVC
is to have as much as skinnier controllers, and your case is perfect example, to prevent to repeat your code. MVC
基础是拥有尽可能多的瘦控制器,您的案例就是一个很好的例子,可以防止重复代码。
Solution for this is to move your code to models
the M
in the MVC
pattern, it is responsible for all the business logic. 解决方案,这是对你的代码移到
models
的M
的MVC
模式,它负责所有的业务逻辑。
Move this method to the module
. 将此方法移至
module
。 In app/models/concers/
folder create new file sheetable.rb
在
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
Now include module
in your model
and it will have class method
new_sheet
. 现在在
model
包含module
,它将具有类method
new_sheet
。
class User < ActiveRecord::Base
...
include Sheetable
...
end
or in other model 或其他型号
class OtherModel < ActiveRecord::Base
...
include Sheetable
...
end
To use this 要使用这个
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
Now you have moved the logic to the model
next step is to refactor this method, make it more simpler. 现在您已将逻辑移至
model
下一步是重构此方法,使其更简单。
I'd begin with moving the code to where the responsibility belongs. 我将从将代码移到职责所属的地方开始。 It seems that you're exporting data of a certain set of users to a spreadsheet.
似乎您正在将一组特定用户的数据导出到电子表格。 So I'd move the code to the User class, eg
所以我将代码移到User类,例如
def self.export_subset_to_spreadsheet(users)
... your code ...
end
and then call it from your controller with User.export_subset_to_spreadsheet(@users)
. 然后使用
User.export_subset_to_spreadsheet(@users)
从您的控制器中调用它。
This is step one. 这是第一步。 You can certainly take it further from there, but at least this allows you to get rid of the most pressing problem: the 19 duplications of that whole block of code.
您当然可以从那里走得更远,但是至少这可以使您摆脱最紧迫的问题:整个代码块的19个重复项。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.