2
votes

I have the following model setup: assignments belong to a user and assignments have many submissions

submissions belong to users and also belong to assignments

submissions have attached files (using paperclip).

I want the assignment user (creator) to be able to download the files (submissions) that belong to the particular assignment.

My routes are structured as follows:

resources :assignments do
  resources :submissions
end 

So, I think I need to define a download action in my assignments controller, which creates a zip archive of all the submissions belonging to an assignment and then redirects directly to that file url for a download.

def download
  @submissions = @assignment.submissions.all
  input_filenames = @submissions.file_file_name.all

    Zip::File.open(assignment.file.url+"/archive.zip", Zip::File::CREATE) do |zipfile|
    input_filenames.each do |filename|
      zipfile.add(filename, assignment_submission_file_path(@assignment.id, @submission.id)+ '/' + filename)
    end
  end

  respond_to do |format|
    format.html { redirect_to assignment.file.url }
    format.json { head :no_content }
  end
end

Then in my assignment show page, I have the following:

  <%= link_to 'Download', @assignment.file.url(:original, false)  %>

But when clicked I get an error returning that the file is missing:

No route matches [GET] "/files/original/missing.png"

So the zip archive file is not being created, and thus my routing to the file doesn't work. It's possible I've done something wrong that is very basic, or that the whole thing needs to be structured differently.

Or my other thought was: do I need to create an empty zip archive in the create action of the assignment controller, so that there is an empty zip archive with a viable path to refer to when I want to add stuff into it? If so, how can I do that with the rubyzip gem?

Thanks!

1

1 Answers

2
votes

Here's the answer to my own questions:

create an action in the controller called download and then refer to it properly in the show page:

  def download
    @assignment = Assignment.find(params[:assignment])
    @submissions = @assignment.submissions.all

    file = @assignment.file.url(:original, false)

    Zip::ZipFile.open(file, create=nil) do |zipfile|
      @submissions.each do |filename|
        zipfile.add(filename.file_file_name, filename.file.url(:original, false))
      end
    end

And this is the call to that download action in the show page:

<%= link_to "Download", {:controller => "assignments", :action => "download", :assignment => @assignment.id }%>