Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/54.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在Rails 3模型中调用实例方法_Ruby On Rails_Activerecord_Csv - Fatal编程技术网

Ruby on rails 在Rails 3模型中调用实例方法

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)

我今天开始阅读Rails反模式,我想将其中一些实践付诸实践。我正在重构最初在控制器中构建的CSV导出。因为这是一个不好的实践,我在模型中考虑了它。。。然后是它自己的模式。通过这种方式,我可以将该方法用于其他目的

我有一个采用以下方法的模型:

#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。