Skip to content

Instantly share code, notes, and snippets.

@penguoir
Created March 3, 2021 10:31
Show Gist options
  • Save penguoir/6ea0d7957e052b4a8433ac2a7f02fa89 to your computer and use it in GitHub Desktop.
Save penguoir/6ea0d7957e052b4a8433ac2a7f02fa89 to your computer and use it in GitHub Desktop.
commit 327539e89ec754d610cf5f584a929d10a589f63d
Author: Ori Marash <ori@marash.net>
Date: Sun Oct 18 20:00:02 2020 +0100
Add resources
diff --git a/app/assets/stylesheets/typography.sass b/app/assets/stylesheets/typography.sass
index 69a2bdd..ea47423 100644
--- a/app/assets/stylesheets/typography.sass
+++ b/app/assets/stylesheets/typography.sass
@@ -1,3 +1,5 @@
+$border-color: #515961
+
.page-title
font-weight: 700
text-align: center
@@ -7,5 +9,20 @@
line-height: 1.2
color: #343a40
- border-bottom: 2px solid #515961
+ border-bottom: 2px solid $border-color
+
+.subpage-title
+ font-weight: 700
+ font-size: 1.5rem
+
+ display: grid
+ grid-gap: 1rem
+ grid-template-columns: minmax(20px, 1fr) auto minmax(20px, 1fr)
+ text-align: center
+ align-items: center
+
+ &:after, &:before
+ content: ""
+ border-top: 2px solid $border-color
+
diff --git a/app/controllers/resources_controller.rb b/app/controllers/resources_controller.rb
new file mode 100644
index 0000000..2849e74
--- /dev/null
+++ b/app/controllers/resources_controller.rb
@@ -0,0 +1,70 @@
+class ResourcesController < ApplicationController
+ before_action :set_resource, only: [:show, :edit, :update, :destroy]
+ before_action :set_project
+
+ # GET /resources
+ # GET /resources.json
+ def index
+ @resources = Resource.all
+ end
+
+ # GET /resources/1
+ # GET /resources/1.json
+ def show
+ end
+
+ # GET /resources/new
+ def new
+ @resource = @project.resources.new
+ end
+
+ # GET /resources/1/edit
+ def edit
+ end
+
+ # POST /resources
+ # POST /resources.json
+ def create
+ @resource = Resource.new(resource_params)
+ @resource.user = current_user
+ @resource.project = @project
+
+ if @resource.save
+ redirect_to @resource, notice: 'Resource was successfully created.'
+ else
+ render :new
+ end
+ end
+
+ # PATCH/PUT /resources/1
+ # PATCH/PUT /resources/1.json
+ def update
+ if @resource.update(resource_params)
+ redirect_to @resource, notice: 'Resource was successfully updated.'
+ else
+ render :edit
+ end
+ end
+
+ # DELETE /resources/1
+ # DELETE /resources/1.json
+ def destroy
+ @resource.destroy
+ redirect_to resources_url, notice: 'Resource was successfully destroyed.'
+ end
+
+ private
+
+ def set_resource
+ @resource = Resource.find(params[:id])
+ end
+
+ def set_project
+ @project = @resource ? @resource.project : Project.find(params[:project_id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def resource_params
+ params.require(:resource).permit(:title, :user_id, :project_id)
+ end
+end
diff --git a/app/helpers/resources_helper.rb b/app/helpers/resources_helper.rb
new file mode 100644
index 0000000..bbdde9a
--- /dev/null
+++ b/app/helpers/resources_helper.rb
@@ -0,0 +1,2 @@
+module ResourcesHelper
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 9c7fe3f..10f1191 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1,2 +1,3 @@
class Project < ApplicationRecord
+ has_many :resources
end
diff --git a/app/models/resource.rb b/app/models/resource.rb
new file mode 100644
index 0000000..e780cbc
--- /dev/null
+++ b/app/models/resource.rb
@@ -0,0 +1,4 @@
+class Resource < ApplicationRecord
+ belongs_to :user
+ belongs_to :project
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 4756799..beaf5cc 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -3,4 +3,6 @@ class User < ApplicationRecord
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
+
+ has_many :resources
end
diff --git a/app/views/projects/edit.html.slim b/app/views/projects/edit.html.slim
index 70828b6..7a3b2df 100644
--- a/app/views/projects/edit.html.slim
+++ b/app/views/projects/edit.html.slim
@@ -1,8 +1,9 @@
= render "shared/container" do
- p.text-center
- = link_to @project do
- = octicon "arrow-left"
- | Back to project
+
+ = breadcrumbs do |b|
+ - b.item "Your projects", projects_path
+ - b.item @project.title, project_path(@project)
+ - b.item "Edit project details"
h1.page-title Edit details for this project
diff --git a/app/views/projects/index.html.slim b/app/views/projects/index.html.slim
index 924f503..8246093 100644
--- a/app/views/projects/index.html.slim
+++ b/app/views/projects/index.html.slim
@@ -1,14 +1,20 @@
-.container.mt-5
- .row.justify-content-center
- .col-12.col-md-8
- h1.display-5.text-center.mb-4 Your projects
+= render "shared/container" do
+ h1.h4.text-center.mb-4.mt-4 Your projects
- .list-group
- - @projects.each do |project|
- = link_to project.title, project, class: "list-group-item list-group-item-action font-weight-bold"
+ - @projects.each do |project|
+ = link_to project, class: "text-dark card mb-2" do
+ .card-body.d-flex.flex-column.justify-content-center
+ b= project.title
+
+ = link_to new_project_path, class: "text-dark bg-light card" do
+ .card-body.d-flex.flex-column.text-center
+ .new-project-icon
+ = octicon "plus", width: 32
+ b Create a new project
+/
= link_to new_project_path, class: "list-group-item"
- .font-weight-bold
- = octicon "plus"
- | Create a new project
+ .font-weight-bold
+ = octicon "plus"
+ | Create a new project
diff --git a/app/views/projects/new.html.slim b/app/views/projects/new.html.slim
index 996d571..bd4e1a1 100644
--- a/app/views/projects/new.html.slim
+++ b/app/views/projects/new.html.slim
@@ -1,4 +1,9 @@
= render "shared/container" do
+
+ = breadcrumbs do |b|
+ - b.item "Your projects", projects_path
+ - b.item "New project"
+
h1.page-title Enter details for the new project
= render "form", project: @project
diff --git a/app/views/projects/show.html.slim b/app/views/projects/show.html.slim
index 73a14fc..bcc5a0e 100644
--- a/app/views/projects/show.html.slim
+++ b/app/views/projects/show.html.slim
@@ -2,10 +2,33 @@
- if notice
.alert.alert-info= notice
+ = breadcrumbs do |b|
+ - b.item "Your projects", projects_path
+ - b.item @project.title
+
.row.justify-content-center
- .col-auto
- = link_to edit_project_path(@project) do
- = octicon "pencil"
- | Edit project details
+ = link_to edit_project_path(@project), class: "text-dark" do
+ = octicon "pencil"
+ | Edit project details
h1.page-title.mt-3= @project.title
+
+ .card
+ .card-header
+ .row.justify-content-between.align-items-center
+ .col
+ | Resources
+ .col-auto
+ = link_to new_project_resource_path(@project), class: "text-primary" do
+ = octicon "plus"
+ | Add a resource
+
+ ul.list-group.list-group-flush
+ - if @project.resources.any?
+ = render @project.resources
+
+ = link_to project_resources_path(@project), class: "list-group-item" do
+ | View all project resources
+ - else
+ .list-group-item.list-group-item-info There are no resources in this project
+
diff --git a/app/views/resources/_form.html.slim b/app/views/resources/_form.html.slim
new file mode 100644
index 0000000..9f5bd45
--- /dev/null
+++ b/app/views/resources/_form.html.slim
@@ -0,0 +1,22 @@
+= form_with model: resource, local: true do |f|
+ - if resource.errors.any?
+ .alert.alert-danger
+ h2.h5
+ => pluralize(resource.errors.count, "error")
+ | prohibited this project from being saved:
+
+ ul.mb-0
+ - resource.errors.full_messages.each do |message|
+ li= message
+
+ .form-group
+ = f.label :title, "Resource title"
+ = f.text_field :title, placeholder: "Type the resource title here...", class: "form-control"
+
+ .form-text.text-muted
+ | This resource is in the project
+ em= ' ' + @project.title
+
+ .row.justify-content-end
+ .col-auto
+ = f.submit class: "btn btn-primary"
diff --git a/app/views/resources/_resource.html.slim b/app/views/resources/_resource.html.slim
new file mode 100644
index 0000000..2af6fcd
--- /dev/null
+++ b/app/views/resources/_resource.html.slim
@@ -0,0 +1,3 @@
+= link_to resource, class: "list-group-item list-group-item-action" do
+ b= resource.title
+ .text-muted= resource.user.email
diff --git a/app/views/resources/edit.html.slim b/app/views/resources/edit.html.slim
new file mode 100644
index 0000000..5a32af7
--- /dev/null
+++ b/app/views/resources/edit.html.slim
@@ -0,0 +1,16 @@
+= render "shared/container" do
+
+ = breadcrumbs do |b|
+ - b.item "Your projects", projects_path
+ - b.item @project.title, project_path(@project)
+ - b.item "Resources", project_resources_path(@project)
+ - b.item @resource.title, resource_path(@resource)
+ - b.item "Edit resource details"
+
+
+ h1.page-title
+ | Editing resource
+ em= ' ' + @resource.title
+
+ = render 'form', resource: @resource
+
diff --git a/app/views/resources/index.html.slim b/app/views/resources/index.html.slim
new file mode 100644
index 0000000..7280884
--- /dev/null
+++ b/app/views/resources/index.html.slim
@@ -0,0 +1,29 @@
+= render "shared/container"
+ = breadcrumbs do |b|
+ - b.item "Your projects", projects_path
+ - b.item @project.title, project_path(@project)
+ - b.item "Resources"
+
+ - if notice
+ .alert.alert-info= notice
+
+ h1.subpage-title.mb-4
+ | Resources of
+ = ' ' + @project.title
+
+ - unless @resources.any?
+ .alert.alert-info No resources
+
+ .list-group.mb-3
+ = render @resources
+ /
+ = link_to resource, class: "list-group-item list-group-item-action" do
+ b= resource.title
+ .text-muted= resource.user.email
+
+ = link_to new_project_resource_path do
+ .card.bg-light
+ .card-body
+ = octicon "plus"
+ | Add a new resource
+
diff --git a/app/views/resources/new.html.slim b/app/views/resources/new.html.slim
new file mode 100644
index 0000000..358aac4
--- /dev/null
+++ b/app/views/resources/new.html.slim
@@ -0,0 +1,13 @@
+= render "shared/container" do
+
+ = breadcrumbs do |b|
+ - b.item "Your projects", projects_path
+ - b.item @project.title, project_path(@project)
+ - b.item "Resources", project_resources_path
+ - b.item "Add a new resource"
+
+ h1.page-title
+ | Add a new resource to
+ em= ' ' + @project.title
+
+ = render 'form', resource: @resource
diff --git a/app/views/resources/show.html.slim b/app/views/resources/show.html.slim
new file mode 100644
index 0000000..c55d644
--- /dev/null
+++ b/app/views/resources/show.html.slim
@@ -0,0 +1,18 @@
+= render "shared/container" do
+
+ = breadcrumbs do |b|
+ - b.item "Your projects", projects_path
+ - b.item @project.title, project_path(@project)
+ - b.item "Resources", project_resources_path(@project)
+ - b.item @resource.title
+
+ - if notice
+ .alert.alert-info= notice
+
+
+ .row.justify-content-center.mb-3
+ = link_to edit_resource_path(@project), class: "text-dark" do
+ = octicon "pencil"
+ | Edit resource details
+
+ h1.subpage-title= @resource.title
diff --git a/config/routes.rb b/config/routes.rb
index 081581a..ad5aa44 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,8 @@
Rails.application.routes.draw do
- resources :projects
+ resources :projects, shallow: true do
+ resources :resources
+ end
+
devise_for :users
authenticated do
diff --git a/db/migrate/20201018160830_create_resources.rb b/db/migrate/20201018160830_create_resources.rb
new file mode 100644
index 0000000..08d133e
--- /dev/null
+++ b/db/migrate/20201018160830_create_resources.rb
@@ -0,0 +1,11 @@
+class CreateResources < ActiveRecord::Migration[6.0]
+ def change
+ create_table :resources do |t|
+ t.string :title
+ t.references :user, null: false, foreign_key: true
+ t.references :project, null: false, foreign_key: true
+
+ t.timestamps
+ end
+ end
+end
diff --git a/test/controllers/resources_controller_test.rb b/test/controllers/resources_controller_test.rb
new file mode 100644
index 0000000..ab967e3
--- /dev/null
+++ b/test/controllers/resources_controller_test.rb
@@ -0,0 +1,48 @@
+require 'test_helper'
+
+class ResourcesControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @resource = resources(:one)
+ end
+
+ test "should get index" do
+ get resources_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_resource_url
+ assert_response :success
+ end
+
+ test "should create resource" do
+ assert_difference('Resource.count') do
+ post resources_url, params: { resource: { project_id: @resource.project_id, title: @resource.title, user_id: @resource.user_id } }
+ end
+
+ assert_redirected_to resource_url(Resource.last)
+ end
+
+ test "should show resource" do
+ get resource_url(@resource)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_resource_url(@resource)
+ assert_response :success
+ end
+
+ test "should update resource" do
+ patch resource_url(@resource), params: { resource: { project_id: @resource.project_id, title: @resource.title, user_id: @resource.user_id } }
+ assert_redirected_to resource_url(@resource)
+ end
+
+ test "should destroy resource" do
+ assert_difference('Resource.count', -1) do
+ delete resource_url(@resource)
+ end
+
+ assert_redirected_to resources_url
+ end
+end
diff --git a/test/fixtures/resources.yml b/test/fixtures/resources.yml
new file mode 100644
index 0000000..370af03
--- /dev/null
+++ b/test/fixtures/resources.yml
@@ -0,0 +1,11 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ title: MyString
+ user: one
+ project: one
+
+two:
+ title: MyString
+ user: two
+ project: two
diff --git a/test/models/resource_test.rb b/test/models/resource_test.rb
new file mode 100644
index 0000000..142db32
--- /dev/null
+++ b/test/models/resource_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class ResourceTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/system/resources_test.rb b/test/system/resources_test.rb
new file mode 100644
index 0000000..d6335a9
--- /dev/null
+++ b/test/system/resources_test.rb
@@ -0,0 +1,47 @@
+require "application_system_test_case"
+
+class ResourcesTest < ApplicationSystemTestCase
+ setup do
+ @resource = resources(:one)
+ end
+
+ test "visiting the index" do
+ visit resources_url
+ assert_selector "h1", text: "Resources"
+ end
+
+ test "creating a Resource" do
+ visit resources_url
+ click_on "New Resource"
+
+ fill_in "Project", with: @resource.project_id
+ fill_in "Title", with: @resource.title
+ fill_in "User", with: @resource.user_id
+ click_on "Create Resource"
+
+ assert_text "Resource was successfully created"
+ click_on "Back"
+ end
+
+ test "updating a Resource" do
+ visit resources_url
+ click_on "Edit", match: :first
+
+ fill_in "Project", with: @resource.project_id
+ fill_in "Title", with: @resource.title
+ fill_in "User", with: @resource.user_id
+ click_on "Update Resource"
+
+ assert_text "Resource was successfully updated"
+ click_on "Back"
+ end
+
+ test "destroying a Resource" do
+ visit resources_url
+ page.accept_confirm do
+ click_on "Destroy", match: :first
+ end
+
+ assert_text "Resource was successfully destroyed"
+ end
+end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment