Răsfoiți Sursa

Add Submissions model and controller

GroupParticipations are polymorphic and can be used for other purposes
in the future.
Frans Bergman 7 ani în urmă
părinte
comite
934d946756

+ 3 - 0
app/assets/javascripts/submissions.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/submissions.scss

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

+ 94 - 0
app/controllers/submissions_controller.rb

@@ -0,0 +1,94 @@
+class SubmissionsController < ApplicationController
+  before_action :set_assignment, only: [:create, :new, :index]
+  before_action :set_submission, only: [:show, :edit, :update, :destroy]
+  before_action :check_view_permission, only: [:show]
+  before_action :check_group_membership, only: [:update, :edit]
+  before_action :check_assignment_membership, only: [:create]
+
+  # GET /assignments/1/submissions
+  # GET /assignments/1/submissions.json
+  def index
+    @submissions = @assignment.submissions
+  end
+
+  # GET /submissions/1
+  # GET /submissions/1.json
+  def show
+  end
+
+  # GET /assignments/1/submissions/new
+  def new
+    @submission = Submission.new
+  end
+
+  # GET /submissions/1/edit
+  def edit
+  end
+
+  # POST /assignments/1/submissions
+  # POST /assignments/1/submissions.json
+  def create
+    @submission = @assignment.submissions.new(submission_params)
+
+    respond_to do |format|
+      if @submission.save && (@submission.users << current_user)
+        format.html { redirect_to @submission, notice: 'Submission was successfully created.' }
+        format.json { render :show, status: :created, location: @submission }
+      else
+        format.html { render :new }
+        format.json { render json: @submission.errors, status: :unprocessable_entity }
+      end
+    end
+  end
+
+  # PATCH/PUT /submissions/1
+  # PATCH/PUT /submissions/1.json
+  def update
+    respond_to do |format|
+      if @submission.update(submission_params)
+        format.html { redirect_to @submission, notice: 'Submission was successfully updated.' }
+        format.json { render :show, status: :ok, location: @submission }
+      else
+        format.html { render :edit }
+        format.json { render json: @submission.errors, status: :unprocessable_entity }
+      end
+    end
+  end
+
+  # DELETE /submissions/1
+  # DELETE /submissions/1.json
+  def destroy
+    @submission.destroy
+    respond_to do |format|
+      format.html { redirect_to assignment_submissions_url(@submission.assignment), notice: 'Submission was successfully destroyed.' }
+      format.json { head :no_content }
+    end
+  end
+
+  private
+    def set_assignment
+      @assignment = Assignment.find(params[:assignment_id])
+    end
+
+    # Use callbacks to share common setup or constraints between actions.
+    def set_submission
+      @submission = Submission.find(params[:id])
+    end
+
+    # Never trust parameters from the scary internet, only allow the white list through.
+    def submission_params
+      params.require(:submission).permit(:title, :description)
+    end
+
+    def check_view_permission
+      redirect_to root_url unless @submission.users.include?(current_user) || @submission.assignment.course.users.merge(CourseParticipation.teachers).include?(current_user)
+    end
+
+    def check_group_membership
+      redirect_to root_url unless @submission.users.include?(current_user)
+    end
+
+    def check_assignment_membership
+      redirect_to root_url unless current_user.assignments.include?(@assignment)
+    end
+end

+ 2 - 0
app/helpers/submissions_helper.rb

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

+ 2 - 0
app/models/assignment.rb

@@ -7,4 +7,6 @@ class Assignment < ApplicationRecord
   validates :due_at, presence: true
 
   default_scope { order(due_at: :asc) }
+
+  has_many :submissions, dependent: :destroy
 end

+ 7 - 0
app/models/group_participation.rb

@@ -0,0 +1,7 @@
+class GroupParticipation < ApplicationRecord
+  belongs_to :user
+  belongs_to :group, polymorphic: true
+
+  validates :user_id, presence: true
+  validates :group_id, presence: true
+end

+ 8 - 0
app/models/submission.rb

@@ -0,0 +1,8 @@
+class Submission < ApplicationRecord
+  belongs_to :assignment
+
+  validates :title, presence: true, length: { maximum: 255 }
+
+  has_many :group_participations, as: :group, dependent: :destroy
+  has_many :users, through: :group_participations
+end

+ 12 - 1
app/views/assignments/_assignment.html.erb

@@ -6,11 +6,22 @@
     <p>
       Course: <%= link_to assignment.course.name, assignment.course %>
     </p>
+    <p>
+      Due at: <%= assignment.due_at %>
+    </p>
     <p>
       <%= format_content(assignment.description) %>
     </p>
   </div>
   <div class="panel-footer">
-    Due at: <%= assignment.due_at %>
+    <% if current_user.assignments.include?(assignment) %>
+      <%= link_to new_assignment_submission_url(assignment), class: 'btn btn-primary' do %>
+        <%= fa_icon 'file', text: "New Submission" %>
+      <% end %>
+    <% elsif assignment.course.users.merge(CourseParticipation.teachers).include?(current_user) %>
+      <%= link_to assignment_submissions_url(assignment), class: 'btn btn-primary' do %>
+        <%= fa_icon 'list', text: "View Submissions" %>
+      <% end %>
+    <% end %>
   </div>
 </div>

+ 8 - 0
app/views/submissions/_form.html.erb

@@ -0,0 +1,8 @@
+<%= bootstrap_form_for [@assignment, @submission] do |f| %>
+  <%= render 'shared/error_messages', object: f.object %>
+
+  <%= f.text_field :title %>
+  <%= f.text_area :description %>
+
+  <%= f.submit yield(:button_text), class: "btn btn-primary" %>
+<% end %>

+ 13 - 0
app/views/submissions/_submission.html.erb

@@ -0,0 +1,13 @@
+<div class="panel panel-primary">
+  <div class="panel-heading">
+    <%= submission.title %>
+  </div>
+  <div class="panel-body">
+    <p>
+      Assignment: <%= link_to submission.assignment.name, submission.assignment %>
+    </p>
+    <p>
+      <%= format_content(submission.description) %>
+    </p>
+  </div>
+</div>

+ 2 - 0
app/views/submissions/_submission.json.jbuilder

@@ -0,0 +1,2 @@
+json.extract! submission, :id, :title, :description, :assignment_id, :created_at, :updated_at
+json.url submission_url(submission, format: :json)

+ 5 - 0
app/views/submissions/edit.html.erb

@@ -0,0 +1,5 @@
+<% provide(:title, 'Edit Submission') %>
+<% provide(:button_text, 'Save changes') %>
+<h1>Editing Submission</h1>
+
+<%= render 'form'%>

+ 5 - 0
app/views/submissions/index.html.erb

@@ -0,0 +1,5 @@
+<h1>Submissions</h1>
+
+<% @submissions.each do |submission| %>
+  <%= render submission %>
+<% end %>

+ 1 - 0
app/views/submissions/index.json.jbuilder

@@ -0,0 +1 @@
+json.array! @submissions, partial: 'submissions/submission', as: :submission

+ 3 - 0
app/views/submissions/new.html.erb

@@ -0,0 +1,3 @@
+<h1>New Submission</h1>
+<% provide(:button_text, "Create") %>
+<%= render 'form' %>

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

@@ -0,0 +1 @@
+<%= render @submission %>

+ 1 - 0
app/views/submissions/show.json.jbuilder

@@ -0,0 +1 @@
+json.partial! "submissions/submission", submission: @submission

+ 3 - 1
config/routes.rb

@@ -20,5 +20,7 @@ Rails.application.routes.draw do
   resources :courses
   resources :course_participations
   resources :lectures
-  resources :assignments
+  resources :assignments do
+    resources :submissions, shallow: true
+  end
 end

+ 11 - 0
db/migrate/20180403104728_create_submissions.rb

@@ -0,0 +1,11 @@
+class CreateSubmissions < ActiveRecord::Migration[5.1]
+  def change
+    create_table :submissions do |t|
+      t.string :title
+      t.string :description
+      t.belongs_to :assignment, foreign_key: true
+
+      t.timestamps
+    end
+  end
+end

+ 10 - 0
db/migrate/20180403104959_create_group_participations.rb

@@ -0,0 +1,10 @@
+class CreateGroupParticipations < ActiveRecord::Migration[5.1]
+  def change
+    create_table :group_participations do |t|
+      t.references :user, foreign_key: true, index: true
+      t.references :group, polymorphic: true, index: true
+
+      t.timestamps
+    end
+  end
+end

+ 20 - 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: 20180321081841) do
+ActiveRecord::Schema.define(version: 20180403104959) do
 
   create_table "administrations", force: :cascade do |t|
     t.integer "user_id"
@@ -68,6 +68,16 @@ ActiveRecord::Schema.define(version: 20180321081841) do
     t.index ["school_id"], name: "index_courses_on_school_id"
   end
 
+  create_table "group_participations", force: :cascade do |t|
+    t.integer "user_id"
+    t.string "group_type"
+    t.integer "group_id"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["group_type", "group_id"], name: "index_group_participations_on_group_type_and_group_id"
+    t.index ["user_id"], name: "index_group_participations_on_user_id"
+  end
+
   create_table "lectures", force: :cascade do |t|
     t.integer "course_id"
     t.datetime "starts_at"
@@ -96,6 +106,15 @@ ActiveRecord::Schema.define(version: 20180321081841) do
     t.datetime "updated_at", null: false
   end
 
+  create_table "submissions", force: :cascade do |t|
+    t.string "title"
+    t.string "description"
+    t.integer "assignment_id"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["assignment_id"], name: "index_submissions_on_assignment_id"
+  end
+
   create_table "users", force: :cascade do |t|
     t.string "name"
     t.string "login"

+ 55 - 0
test/controllers/submissions_controller_test.rb

@@ -0,0 +1,55 @@
+require 'test_helper'
+
+class SubmissionsControllerTest < ActionDispatch::IntegrationTest
+  setup do
+    @teacher = users(:daniel)
+    @student = users(:billy)
+    @assignment = assignments(:one)
+    @submission = submissions(:one)
+    log_in_as @teacher
+  end
+
+  test "should get index" do
+    get assignment_submissions_url(@assignment)
+    assert_response :success
+  end
+
+  test "should get new" do
+    get new_assignment_submission_url(@assignment)
+    assert_response :success
+  end
+
+  test "student should create submission" do
+    log_in_as @student
+    assert_difference('Submission.count') do
+      post assignment_submissions_url(@assignment), params: { submission: { description: @submission.description, title: @submission.title } }
+    end
+
+    assert_redirected_to submission_url(Submission.last)
+  end
+
+  test "should show submission" do
+    get submission_url(@submission)
+    assert_response :success
+  end
+
+  test "student should get edit" do
+    log_in_as @student
+    get edit_submission_url(@submission)
+    assert_response :success
+  end
+
+  test "student should update submission" do
+    log_in_as @student
+    patch submission_url(@submission), params: { submission: { description: @submission.description, title: @submission.title } }
+    assert_redirected_to submission_url(@submission)
+  end
+
+  test "should destroy submission" do
+    assert_difference('Submission.count', -1) do
+      delete submission_url(@submission)
+    end
+
+    assert_redirected_to assignment_submissions_url(@assignment)
+  end
+end

+ 5 - 0
test/fixtures/group_participations.yml

@@ -0,0 +1,5 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+  user: billy
+  group: one (Submission)

+ 11 - 0
test/fixtures/submissions.yml

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

+ 7 - 0
test/models/group_participation_test.rb

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

+ 7 - 0
test/models/submission_test.rb

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

+ 9 - 0
test/system/submissions_test.rb

@@ -0,0 +1,9 @@
+require "application_system_test_case"
+
+class SubmissionsTest < ApplicationSystemTestCase
+  # test "visiting the index" do
+  #   visit submissions_url
+  #
+  #   assert_selector "h1", text: "Submission"
+  # end
+end