Ruby on rails 在Rails 3模型中调用实例方法
我今天开始阅读Rails反模式,我想将其中一些实践付诸实践。我正在重构最初在控制器中构建的CSV导出。因为这是一个不好的实践,我在模型中考虑了它。。。然后是它自己的模式。通过这种方式,我可以将该方法用于其他目的 我有一个采用以下方法的模型:Ruby on rails 在Rails 3模型中调用实例方法,ruby-on-rails,activerecord,csv,Ruby On Rails,Activerecord,Csv,我今天开始阅读Rails反模式,我想将其中一些实践付诸实践。我正在重构最初在控制器中构建的CSV导出。因为这是一个不好的实践,我在模型中考虑了它。。。然后是它自己的模式。通过这种方式,我可以将该方法用于其他目的 我有一个采用以下方法的模型: #app/models/imagery_request.rb class ImageryRequest < ActiveRecord::Base def convert ImageryRequestConverter.new(self)
#app/models/imagery_request.rb
class ImageryRequest < ActiveRecord::Base
def convert
ImageryRequestConverter.new(self)
end
end
我有另一个这样的模型:
#app/models/imagery_request_converter.rb
class ImageryRequestConverter
attr_reader :imagery_requests
def initialize(imagery_requests)
@imagery_requests = imagery_requests
end
def to_csv
csv_string = FasterCSV.generate do |csv|
# header row
csv << ["id", "service_name", "description", "first_name", "last_name", "email", "phone_contact", "region",
"imagery_type", "file_type", "pixel_type", "total_images",
"tile_size", "progress", "expected_date", "high_priority", "priority_justification",
"raw_data_location", "service_overviews", "is_def",
"isc_def", "special_instructions", "navigational_path", "FY Queue",
"created_at", "updated_at"]
# data rows
@imagery_requests.each do |ir|
csv << [ir.id, ir.service_name, ir.description, ir.first_name, ir.last_name, ir.email,
ir.phone_contact, ir.region, ir.imagery_type, ir.file_type, ir.pixel_type,
ir.total_images, ir.tile_size, ir.progress, ir.expected_date, ir.high_priority,
ir.priority_justification, ir.raw_data_location, ir.service_overviews,
ir.is_def, ir.isc_def, ir.special_instructions, ir.navigational_path,
ir.fyqueue, ir.created_at, ir.updated_at
]
end
# send it to the browser with proper headers
send_data csv_string,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename=Imagery_Requests-#{Time.now.strftime("%Y%m%d")}.csv"
end
end
end
当我试图在我的观点中引用这一点时:
<%= link_to @imagery_requests.convert.to_csv %>
我得到一个错误:
undefined method `convert' for #<ActiveRecord::Relation:0x21f966d0>
如何调用此方法?@images\u requests变量实际上是一个关系对象,一旦调用它,它将始终是记录的集合。您正在调用此对象上的实例方法,这将不起作用,因为您在整个集合上调用它,而不是在此集合中调用对象
除此之外,在link_中调用这个方法就像你在那里做的一样,也不会完全起作用。该链接应指向一个控制器操作,该操作解析这些请求并正确返回CSV。继续Ryan Bigg的回答
你有两个问题:
要调用convert方法,需要在集合中指定一个对象。例如@images\u requests.first.convert.to\u csv或@images\u requests[i].convert.to\u csv等
您不能有指向文件内容的链接,这正是您的代码所要做的。相反,您需要链接到一个新操作,例如下载将返回csv的csv
由于新操作下载csv版本的文件不是标准restful套件的一部分,因此需要向资源中添加其他操作
用户体验用户体验选择:
您可以为ImageryRequests集合的每个成员创建一个下载为csv操作,这意味着想要5个请求的csv版本的人需要下载5个不同的csv文件
或者您可以为该收藏创建下载。但是每个http请求都有一个响应。通常的解决方案是:向客户端返回一个包含多个文件的zip文件
在任何情况下,您都应该将代码移入模型并移出控制器
电子邮件用户体验解决方案这一个特别好,如果创建csv文件需要一秒钟以上的时间,因为Rails是单线程的,所有响应都应该非常快
csv下载的表单应该以电子邮件地址作为参数,而不是使用文件进行响应。然后使用DelayJob或其他调度程序在后台通过电子邮件发送csv文件
您可以将zip文件作为电子邮件附件发送,也可以发送多个csv文件,因为电子邮件可以有多个附件
提示:您的表单应该处理多个电子邮件地址,并允许用户在电子邮件中包含封面说明。这将使请求者能够向多人发送报告 所以我基本上必须把所有CSV创建代码放在一个控制器动作中?必须有一种更优雅/可重用的方式。对,我理解关于链接到的视图问题。至于我的UX选择,我希望所有行都在一个CSV中返回。将来,我将有一个高级搜索,它将根据日期范围返回CSV。