Вызов метода экземпляра в модели Rails 3 - PullRequest
0 голосов
/ 13 декабря 2011

Я начал читать Rails Antipatterns сегодня и хотел применить некоторые из этих методов в действии.Я рефакторинг экспорта 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>

Как мне вызвать этот метод?

Ответы [ 2 ]

0 голосов
/ 13 декабря 2011

Продолжение ответа Райана Бигга

У вас есть две проблемы:

  1. Чтобы вызвать метод convert, вам нужно указать объект в коллекции. Например. @imagery_requests.first.convert.to_csv или @imagery_requests[i].convert.to_csv и т. Д.

  2. У вас не может быть ссылки на содержимое файла, что пытается сделать ваш код. Вместо этого вам нужно сослаться на новое действие, например download_csv, которое будет возвращать CSV.

Поскольку новое действие (загрузить версию файла в формате csv) не является частью стандартного пакета restful, вам необходимо добавить дополнительные действия к ресурсу. Например, статья

Выбор пользовательского интерфейса (UX): Вы можете создать загрузку как действие csv для каждого члена из коллекции ImageryRequests, это будет означать, что человеку, которому нужна версия csv для 5 запросов, потребуется загрузить 5 различных файлов csv.

Или вы можете создать загрузку для коллекции . Но каждый запрос http имеет один ответ. Обычное решение: вернуть клиенту zip-файл с несколькими файлами.

В любом случае, вы правы, что вам следует переместить код в модель и из контроллера.

Решение EMail UX Это особенно хорошо, если для создания файлов csv потребуется больше доли секунды - поскольку Rails однопоточный, все ответы должны быть очень быстрыми.

Вместо того, чтобы отвечать файлом, форма для загрузки csv должна принимать адрес электронной почты в качестве параметра. Затем используйте DelayJob или другой планировщик для отправки файлов CSV по электронной почте в фоновом режиме.

Вы можете отправить zip-файл в качестве вложения к электронному письму или отправить несколько файлов CSV, поскольку электронное письмо может иметь несколько вложений.

Совет: ваша форма должна обрабатывать несколько адресов электронной почты и позволять пользователю включать сопроводительную записку в электронное письмо. Это позволит запрашивающим отправлять отчет нескольким людям.

0 голосов
/ 13 декабря 2011

Переменная @imagery_requests на самом деле является Relation объектом, который всегда будет набором записей после его вызова.Вы вызываете метод экземпляра для этого объекта, который не будет работать, потому что вы вызываете его для целой коллекции, а не для объекта внутри этой коллекции.

Кроме того, вызывается методв link_to, как вы делаете, просто не будет работать на полную мощность.Ссылка должна перейти к действию контроллера, которое анализирует эти запросы и корректно возвращает CSV.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...