2014-10-14 2 views
1

У меня есть метод export_csv в контроллере.Rails 4 ... Перезагрузка страницы после send_data

def export_csv 
    if params[:from_date].present? && params[:to_date].present? 
    @users = User.where("created_at between ? and ?", params[:from_date], params[:to_date]) 
     if [email protected]? 
      users_csv = User.to_excel(@users) 
      send_data(users_csv, :type => 'text/csv', :filename => 'users.csv') 
      flash.now[:success] = "Successfully downloaded the report!" 
     else 
     flash.now[:notice] = "No records over selected duration!" 
     end 
    else 
    flash.now[:notice] = "Select from and to date.." 
    end 
end 

Файл загружен, но страница не обновляется и не перезагружается. Из-за этого флеш-сообщение остается, как на странице, даже после загрузки файла.

Я прошел через несколько сайтов и обнаружил, что send_data автоматически отображает представление, и поэтому нельзя использовать другую перенаправление или рендеринг.

Есть ли способ перезагрузить страницу после отправки_даты.?

ответ

1

send_data устанавливает весь ответ сервера, поэтому браузер получает только CSV-файл, а не веб-страницу. Вот почему ваше флеш-сообщение не отображается. Альтернативой может быть, чтобы создать временный файл CSV (с произвольным именем) и предоставить обратно ссылку на него:

def export_csv 
    if params[:from_date].present? && params[:to_date].present? 
    @users = User.where("created_at between ? and ?", params[:from_date], params[:to_date]) 
     if [email protected]? 
      #Create temporary CSV report file and get the path to it. 
      csv_file_path = create_csv_file(User.to_excel(@users)) 

      #Change the flash message a bit for requesting the user 
      #to click on a link to download the file.     
      flash.now[:success] = "Your report has been successfully generated! Click <a href='#{csv_file_path}'>here</a> to download".html_safe 
     else 
     flash.now[:notice] = "No records over selected duration!" 
     end 
    else 
    flash.now[:notice] = "Select from and to date.." 
    end 
end 

Конечно, вы должны реализовать функцию create_csv_file. Чтобы избежать хранения старых файлов на вашем сервере, вы можете реализовать новый метод, скажем download_report, который будет читать файл, отправить обратно клиенту с send_data и, наконец, удалить его.

EDIT

псевдокод для функций, упомянутых выше:

require 'tempfile' 

def create_csv_file(data)  
    #Create a temporary file. If you omit the second argument of Tempfile.new 
    #then the OS's temp directory will be used. 
    tmp = Tempfile.new('report', 'my/temp/dir') 
    tmp.write(data) 
    tmp.close 

    return tmp.path 
end 


#Method in controller for downloading the file. I omit checks and/or security issues. 
def download_report 
    #Warning: a mechanism should be implemented to prevent the remote 
    #client from faking the path and download other files. 
    #A possible solution would be providing not only the file path but also a 
    #hash with a secret key to validate the path. Function create_csv_file() 
    #should, then, return a hash in addition of a path. 

    path = params[:report] 
    file = File.open(path, "rb") 
    contents = file.read 
    file.close 

    send_data(contents , :type => 'text/csv', :filename => 'users.csv')  
    file.unlink #Delete file 
end 
+0

Спасибо за ответ. Разве нет другого способа сделать это? Потому что удаление файлов с использованием фоновой задачи будет суете. –

+0

Ну, вы можете создать новый метод 'download_csv', который будет использовать' send_data' (сначала чтение содержимого файла), а затем удалить файл. – Claudix

+0

Можете ли вы помочь с псевдо-кодом того, что нужно написать в файле _ csv _ и загрузить _ report? –

Смежные вопросы