Browse Source

Add DataFile model and controller

Frans Bergman 7 years ago
parent
commit
a93cc8746b

+ 3 - 0
app/assets/javascripts/data_files.coffee

@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/

+ 3 - 0
app/assets/stylesheets/data_files.scss

@@ -0,0 +1,3 @@
+// Place all the styles related to the files controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/

+ 57 - 0
app/controllers/data_files_controller.rb

@@ -0,0 +1,57 @@
+class DataFilesController < ApplicationController
+  before_action :set_file, only: [:download, :destroy]
+  before_action :check_can_download, only: [:download]
+  before_action :check_can_destroy, only: [:destroy]
+
+  def create
+    uploaded_io = params[:data_file][:data]
+    @file = DataFile.new(file_params)
+    @file.uuid = SecureRandom.uuid
+    @file.name = uploaded_io.original_filename
+
+    if uploaded_io.size > 100.megabytes
+      flash[:danger] = "File too large (>100MB)"
+      redirect_to @file.repository
+      return
+    end
+
+    unless @file.repository.can_upload_files?(current_user)
+      redirect_to root_url
+      return
+    end
+
+    Dir.mkdir Rails.root.join('public', 'uploads', @file.uuid)
+    File.open(Rails.root.join('public', 'uploads', @file.uuid, uploaded_io.original_filename), 'wb') do |file|
+      file.write(uploaded_io.read)
+    end
+
+    flash[:danger] = "Error creating file" unless @file.save
+    redirect_to @file.repository
+  end
+
+  def download
+    send_file @file.file_path
+  end
+
+  def destroy
+    @file.destroy
+    redirect_to @file.repository
+  end
+
+  private
+    def set_file
+      @file = DataFile.find(params[:id])
+    end
+
+    def file_params
+      params.require(:data_file).permit(:repository_id, :repository_type)
+    end
+
+    def check_can_download
+      redirect_to root_url unless @file.repository.can_download_files?(current_user)
+    end
+
+    def check_can_destroy
+      redirect_to root_url unless @file.repository.can_upload_files?(current_user)
+    end
+end

+ 2 - 0
app/helpers/files_helper.rb

@@ -0,0 +1,2 @@
+module FilesHelper
+end

+ 10 - 0
app/models/course.rb

@@ -14,6 +14,16 @@ class Course < ApplicationRecord
   has_many :lectures
   has_many :assignments
 
+  has_many :data_files, as: :repository
+
+  def can_download_files?(user)
+    self.users.include?(user)
+  end
+
+  def can_upload_files?(user)
+    self.users.merge(CourseParticipation.teachers).include?(user)
+  end
+
   private
     def date_order
       if ends_on < starts_on

+ 19 - 0
app/models/data_file.rb

@@ -0,0 +1,19 @@
+class DataFile < ApplicationRecord
+  require 'fileutils'
+  before_destroy :delete_file
+
+  belongs_to :repository, polymorphic: true
+
+  def dir_path
+    Rails.root.join('public', 'uploads', self.uuid)
+  end
+
+  def file_path
+    Rails.root.join('public', 'uploads', self.uuid, self.name)
+  end
+
+  private
+    def delete_file
+      FileUtils.rm_rf(self.dir_path)
+    end
+end

+ 10 - 0
app/models/school.rb

@@ -8,4 +8,14 @@ class School < ApplicationRecord
   has_many :courses
 
   has_many :users
+
+  has_many :data_files, as: :repository
+
+  def can_download_files?(user)
+    self.users.include?(user) || self.administrators.include?(user)
+  end
+
+  def can_upload_files?(user)
+    self.administrators.include?(user)
+  end
 end

+ 10 - 0
app/models/submission.rb

@@ -5,4 +5,14 @@ class Submission < ApplicationRecord
 
   has_many :group_participations, as: :group, dependent: :destroy
   has_many :users, through: :group_participations
+
+  has_many :data_files, as: :repository
+
+  def can_download_files?(user)
+    users.include?(user) || self.assignment.course.users.merge(CourseParticipation.teachers).include?(user)
+  end
+
+  def can_upload_files?(user)
+    users.include?(user)
+  end
 end

+ 3 - 0
app/views/courses/show.html.erb

@@ -37,4 +37,7 @@
       </table>
     </div>
   </div>
+  <div class="col-md-6">
+    <%= render partial: 'data_files/file_panel', locals: { repository: @course } %>
+  </div>
 </div>

+ 12 - 0
app/views/data_files/_data_file.html.erb

@@ -0,0 +1,12 @@
+<tr>
+  <td>
+    <%= link_to data_file.name, download_data_file_url(data_file) %>
+  </td>
+  <% if data_file.repository.can_upload_files?(current_user) %>
+    <td>
+      <%= form_for data_file, html: { method: :delete } do |f| %>
+        <%= f.submit "Remove", class: "btn btn-danger" %>
+      <% end %>
+    </td>
+  <% end %>
+</tr>

+ 17 - 0
app/views/data_files/_file_panel.html.erb

@@ -0,0 +1,17 @@
+<div class="panel panel-primary">
+  <div class="panel-heading">
+    Files
+  </div>
+  <table class="panel-body table table-striped table-bordered table-hover">
+    <tbody>
+      <% for file in repository.data_files %>
+        <%= render file %>
+      <% end %>
+    </tbody>
+  </table>
+  <% if repository.can_upload_files?(current_user) %>
+    <div class="panel-footer">
+      <%= render 'data_files/form', repository: repository %>
+    </div>
+  <% end %>
+</div>

+ 6 - 0
app/views/data_files/_form.html.erb

@@ -0,0 +1,6 @@
+<%= bootstrap_form_for(DataFile.new) do |f| %>
+  <%= f.file_field :data, hide_label: true %>
+  <%= f.hidden_field :repository_id, value: repository.id %>
+  <%= f.hidden_field :repository_type, value: repository.class.name %>
+  <%= f.submit 'Upload file', class: 'btn btn-primary' %>
+<% end %>

+ 5 - 0
app/views/schools/show.html.erb

@@ -4,3 +4,8 @@
     <h1><%= @school.name %></h1>
   </div>
 </div>
+<div class="row">
+  <div class="col-md-6">
+    <%= render partial: 'data_files/file_panel', locals: { repository: @school } %>
+  </div>
+</div>

+ 8 - 1
app/views/submissions/show.html.erb

@@ -1 +1,8 @@
-<%= render @submission %>
+<div class="row">
+  <div class="col-md-6">
+    <%= render @submission %>
+  </div>
+  <div class="col-md-6">
+    <%= render partial: 'data_files/file_panel', locals: { repository: @submission } %>
+  </div>
+</div>

+ 5 - 0
config/routes.rb

@@ -23,4 +23,9 @@ Rails.application.routes.draw do
   resources :assignments do
     resources :submissions, shallow: true
   end
+  resources :data_files do
+    member do
+      get :download
+    end
+  end
 end

+ 11 - 0
db/migrate/20180404090939_create_data_files.rb

@@ -0,0 +1,11 @@
+class CreateDataFiles < ActiveRecord::Migration[5.1]
+  def change
+    create_table :data_files do |t|
+      t.string :name
+      t.references :repository, index: true, polymorphic: true
+      t.string :uuid
+
+      t.timestamps
+    end
+  end
+end

+ 11 - 1
db/schema.rb

@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20180403104959) do
+ActiveRecord::Schema.define(version: 20180404090939) do
 
   create_table "administrations", force: :cascade do |t|
     t.integer "user_id"
@@ -68,6 +68,16 @@ ActiveRecord::Schema.define(version: 20180403104959) do
     t.index ["school_id"], name: "index_courses_on_school_id"
   end
 
+  create_table "data_files", force: :cascade do |t|
+    t.string "name"
+    t.string "repository_type"
+    t.integer "repository_id"
+    t.string "uuid"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["repository_type", "repository_id"], name: "index_data_files_on_repository_type_and_repository_id"
+  end
+
   create_table "group_participations", force: :cascade do |t|
     t.integer "user_id"
     t.string "group_type"

+ 7 - 0
test/controllers/files_controller_test.rb

@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class FilesControllerTest < ActionDispatch::IntegrationTest
+  # test "the truth" do
+  #   assert true
+  # end
+end

+ 11 - 0
test/fixtures/data_files.yml

@@ -0,0 +1,11 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+  name: MyString
+  repository: one
+  uuid: MyString
+
+two:
+  name: MyString
+  repository: two
+  uuid: MyString

+ 7 - 0
test/models/data_file_test.rb

@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class DataFileTest < ActiveSupport::TestCase
+  # test "the truth" do
+  #   assert true
+  # end
+end