diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7e9ace1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM ruby:2.3.1 + +RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs +RUN mkdir /app +WORKDIR /app + +# Cache Dependency Install +ADD Gemfile /app/Gemfile +ADD Gemfile.lock /app/Gemfile.lock +RUN bundle install + +# Add Repository +ADD . /app + +# Run Server +EXPOSE 3000 +CMD rake db:migrate && rails server -b 0.0.0.0 diff --git a/Gemfile b/Gemfile index 6f350ef..315908f 100644 --- a/Gemfile +++ b/Gemfile @@ -3,8 +3,7 @@ source 'https://rubygems.org' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.0.0', '>= 5.0.0.1' -# Use sqlite3 as the database for Active Record -gem 'sqlite3' +gem 'pg' # Use Puma as the app server gem 'puma', '~> 3.0' # Use SCSS for stylesheets @@ -15,7 +14,7 @@ gem 'uglifier', '>= 1.3.0' gem 'coffee-rails', '~> 4.2' # See https://github.com/rails/execjs#readme for more supported runtimes # gem 'therubyracer', platforms: :ruby -# Bulma CSS +gem 'haml' gem "bulma-rails", "~> 0.2.3" # Use jquery as the JavaScript library gem 'jquery-rails' diff --git a/Gemfile.lock b/Gemfile.lock index da9c73e..c23f570 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -57,6 +57,8 @@ GEM ffi (1.9.14) globalid (0.3.7) activesupport (>= 4.1.0) + haml (4.0.7) + tilt i18n (0.7.0) jbuilder (2.6.0) activesupport (>= 3.0.0, < 5.1) @@ -82,6 +84,7 @@ GEM nio4r (1.2.1) nokogiri (1.6.8.1) mini_portile2 (~> 2.1.0) + pg (0.19.0) puma (3.6.0) rack (2.0.1) rack-test (0.6.3) @@ -132,7 +135,6 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - sqlite3 (1.3.12) thor (0.19.1) thread_safe (0.3.5) tilt (2.0.5) @@ -159,19 +161,20 @@ DEPENDENCIES bulma-rails (~> 0.2.3) byebug coffee-rails (~> 4.2) + haml jbuilder (~> 2.5) jquery-rails listen (~> 3.0.5) + pg puma (~> 3.0) rails (~> 5.0.0, >= 5.0.0.1) sass-rails (~> 5.0) spring spring-watcher-listen (~> 2.0.0) - sqlite3 turbolinks (~> 5) tzinfo-data uglifier (>= 1.3.0) web-console BUNDLED WITH - 1.12.5 + 1.13.6 diff --git a/app/assets/images/favicon.png b/app/assets/images/favicon.png new file mode 100644 index 0000000..8e248bf Binary files /dev/null and b/app/assets/images/favicon.png differ diff --git a/app/assets/javascripts/todos.coffee b/app/assets/javascripts/todos.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/todos.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/ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.scss similarity index 73% rename from app/assets/stylesheets/application.css rename to app/assets/stylesheets/application.scss index 0ebd7fe..81bd2b2 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.scss @@ -13,3 +13,28 @@ *= require_tree . *= require_self */ +@import "bulma"; + +.hero { + margin-bottom: 30px; +} + +.todo-list { + padding: 30px; +} + +.addTodo { + margin-top: 30px; +} + +.addTodo input { + width: 100%; + height: 50px; + padding: 10px; + resize: vertical; + font-size: 18px; +} + +.addTodo label { + display: none; +} diff --git a/app/assets/stylesheets/scaffolds.scss b/app/assets/stylesheets/scaffolds.scss new file mode 100644 index 0000000..443728e --- /dev/null +++ b/app/assets/stylesheets/scaffolds.scss @@ -0,0 +1,34 @@ +#notice { + color: red; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; + + h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0; + background-color: #c00; + color: #fff; + } + + ul li { + font-size: 12px; + list-style: square; + } +} diff --git a/app/assets/stylesheets/todos.scss b/app/assets/stylesheets/todos.scss new file mode 100644 index 0000000..e69de29 diff --git a/app/controllers/todos_controller.rb b/app/controllers/todos_controller.rb new file mode 100644 index 0000000..91f174f --- /dev/null +++ b/app/controllers/todos_controller.rb @@ -0,0 +1,78 @@ +class TodosController < ApplicationController + before_action :set_todo, only: [:show, :edit, :update, :destroy] + + # GET /todos + # GET /todos.json + def index + @todos = Todo.all + @todo = Todo.new + end + + # GET /todos/1 + # GET /todos/1.json + def show + end + + # GET /todos/new + def new + @todo = Todo.new + end + + # GET /todos/1/edit + def edit + end + + # POST /todos + # POST /todos.json + def create + @todo = Todo.new(todo_params) + + respond_to do |format| + if @todo.content == "" + format.html { redirect_to todos_path, notice: 'Todo was blank!'} + format.json { render json: { error: 'Blank Todo!' }, status: :unprocessable_entity } + elsif @todo.save + format.html { redirect_to todos_path } + format.json { render :show, status: :created, location: @todo } + else + format.html { render todos_path } + format.json { render json: @todo.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /todos/1 + # PATCH/PUT /todos/1.json + def update + respond_to do |format| + if @todo.update(todo_params) + format.html { redirect_to todos_path } + format.json { render :show, status: :ok, location: @todo } + else + format.html { render :edit } + format.json { render json: @todo.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /todos/1 + # DELETE /todos/1.json + def destroy + @todo.destroy + respond_to do |format| + format.html { redirect_to todos_url, notice: 'Todo was successfully destroyed.' } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_todo + @todo = Todo.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def todo_params + params.require(:todo).permit(:content) + end +end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb new file mode 100644 index 0000000..65ab195 --- /dev/null +++ b/app/helpers/todos_helper.rb @@ -0,0 +1,2 @@ +module TodosHelper +end diff --git a/app/models/todo.rb b/app/models/todo.rb new file mode 100644 index 0000000..e7adee6 --- /dev/null +++ b/app/models/todo.rb @@ -0,0 +1,2 @@ +class Todo < ApplicationRecord +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb deleted file mode 100644 index 0e51ed4..0000000 --- a/app/views/layouts/application.html.erb +++ /dev/null @@ -1,14 +0,0 @@ - - - - RailsStarter - <%= csrf_meta_tags %> - - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> - <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> - - - - <%= yield %> - - diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml new file mode 100644 index 0000000..f805997 --- /dev/null +++ b/app/views/layouts/application.html.haml @@ -0,0 +1,15 @@ +!!! +%html + %head + %title ToDo List + = favicon_link_tag "favicon.png", rel: 'shortcut icon', type: 'image/png' + = stylesheet_link_tag "application", media: "all" + = javascript_include_tag "application" + = csrf_meta_tags + %body + %section.hero.is-dark + .hero-body + .container + %h1.title Todo List + %h2.subtitle Submit a new Todo to get started! + = yield diff --git a/app/views/todos/_form.html.erb b/app/views/todos/_form.html.erb new file mode 100644 index 0000000..5378b98 --- /dev/null +++ b/app/views/todos/_form.html.erb @@ -0,0 +1,16 @@ +<%= form_for(todo, :html => {:class => 'addTodo'}) do |f| %> + <% if todo.errors.any? %> +
+

<%= pluralize(todo.errors.count, "error") %> prohibited this todo from being saved:

+ + +
+ <% end %> + + <%= f.text_field :content, autofocus: true, placeholder: 'Add a Todo!' %> + <%= f.submit 'Submit', :class => 'button is-dark is-fullwidth' %> +<% end %> diff --git a/app/views/todos/_todo.json.jbuilder b/app/views/todos/_todo.json.jbuilder new file mode 100644 index 0000000..41019dd --- /dev/null +++ b/app/views/todos/_todo.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! todo, :id, :title, :description, :created_at, :updated_at +json.url todo_url(todo, format: :json) \ No newline at end of file diff --git a/app/views/todos/edit.html.erb b/app/views/todos/edit.html.erb new file mode 100644 index 0000000..97f0ce9 --- /dev/null +++ b/app/views/todos/edit.html.erb @@ -0,0 +1,6 @@ +

Editing Todo

+ +<%= render 'form', todo: @todo %> + +<%= link_to 'Show', @todo %> | +<%= link_to 'Back', todos_path %> diff --git a/app/views/todos/index.html.haml b/app/views/todos/index.html.haml new file mode 100644 index 0000000..fe39347 --- /dev/null +++ b/app/views/todos/index.html.haml @@ -0,0 +1,13 @@ +.container.todo-list + - if @todos.empty? + %p There are no todos! + - else + - @todos.each do |todo| + %article.media + .media-content + .content + %p= todo.content + .media-right + %a= link_to 'Delete', todo, method: :delete, class: 'button is-danger' + =render 'form', todo: @todo + %p#notice= notice diff --git a/app/views/todos/index.json.jbuilder b/app/views/todos/index.json.jbuilder new file mode 100644 index 0000000..83ef1b0 --- /dev/null +++ b/app/views/todos/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @todos, partial: 'todos/todo', as: :todo \ No newline at end of file diff --git a/app/views/todos/show.html.haml b/app/views/todos/show.html.haml new file mode 100644 index 0000000..e22fbbb --- /dev/null +++ b/app/views/todos/show.html.haml @@ -0,0 +1,7 @@ +.container + %p#notice= notice + %br + .box + %p= @todo.content + = link_to 'Edit', edit_todo_path(@todo), class: 'button' + = link_to 'Back', todos_path, class: 'button' diff --git a/app/views/todos/show.json.jbuilder b/app/views/todos/show.json.jbuilder new file mode 100644 index 0000000..ddfec4b --- /dev/null +++ b/app/views/todos/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "todos/todo", todo: @todo \ No newline at end of file diff --git a/config/database.yml b/config/database.yml index 1c1a37c..b96c8ba 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,25 +1,12 @@ -# SQLite version 3.x -# gem install sqlite3 -# -# Ensure the SQLite 3 gem is defined in your Gemfile -# gem 'sqlite3' -# -default: &default - adapter: sqlite3 +development: &default + adapter: postgresql + encoding: unicode + database: postgres pool: 5 - timeout: 5000 + username: postgres + password: + host: db -development: - <<: *default - database: db/development.sqlite3 - -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. test: <<: *default - database: db/test.sqlite3 - -production: - <<: *default - database: db/production.sqlite3 + database: myapp_test diff --git a/config/routes.rb b/config/routes.rb index 787824f..54274a5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,5 @@ Rails.application.routes.draw do + root to: "todos#index" + resources :todos # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/db/migrate/20161119011946_create_tasks.rb b/db/migrate/20161119011946_create_tasks.rb deleted file mode 100644 index 4e49038..0000000 --- a/db/migrate/20161119011946_create_tasks.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateTasks < ActiveRecord::Migration[5.0] - def change - create_table :tasks do |t| - t.string :title - t.text :note - t.date :completed - - t.timestamps - end - end -end diff --git a/db/migrate/20161122050054_create_todos.rb b/db/migrate/20161122050054_create_todos.rb new file mode 100644 index 0000000..616cad2 --- /dev/null +++ b/db/migrate/20161122050054_create_todos.rb @@ -0,0 +1,8 @@ +class CreateTodos < ActiveRecord::Migration[5.0] + def change + create_table :todos do |t| + t.string :content + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 8a0ca3c..729ce8a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,12 +10,13 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161119011946) do +ActiveRecord::Schema.define(version: 20161122050054) do - create_table "tasks", force: :cascade do |t| - t.string "title" - t.text "note" - t.date "completed" + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "todos", force: :cascade do |t| + t.string "content" t.datetime "created_at", null: false t.datetime "updated_at", null: false end diff --git a/db/seeds.rb b/db/seeds.rb index 1beea2a..0afa7eb 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,3 +5,5 @@ # # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) # Character.create(name: 'Luke', movie: movies.first) + +Todo.create(content: 'This is a sample todo.') diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..0d8ca90 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: '2' +services: + db: + image: postgres + web: + build: . + volumes: + - .:/app + ports: + - "3000:3000" + depends_on: + - db \ No newline at end of file diff --git a/test/controllers/todos_controller_test.rb b/test/controllers/todos_controller_test.rb new file mode 100644 index 0000000..720e84c --- /dev/null +++ b/test/controllers/todos_controller_test.rb @@ -0,0 +1,48 @@ +require 'test_helper' + +class TodosControllerTest < ActionDispatch::IntegrationTest + setup do + @todo = todos(:one) + end + + test "should get index" do + get todos_url + assert_response :success + end + + test "should get new" do + get new_todo_url + assert_response :success + end + + test "should create todo" do + assert_difference('Todo.count') do + post todos_url, params: { todo: { description: @todo.description, title: @todo.title } } + end + + assert_redirected_to todo_url(Todo.last) + end + + test "should show todo" do + get todo_url(@todo) + assert_response :success + end + + test "should get edit" do + get edit_todo_url(@todo) + assert_response :success + end + + test "should update todo" do + patch todo_url(@todo), params: { todo: { description: @todo.description, title: @todo.title } } + assert_redirected_to todo_url(@todo) + end + + test "should destroy todo" do + assert_difference('Todo.count', -1) do + delete todo_url(@todo) + end + + assert_redirected_to todos_url + end +end diff --git a/test/fixtures/todos.yml b/test/fixtures/todos.yml new file mode 100644 index 0000000..97fbfc4 --- /dev/null +++ b/test/fixtures/todos.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + title: MyString + description: MyText + +two: + title: MyString + description: MyText diff --git a/test/models/todo_test.rb b/test/models/todo_test.rb new file mode 100644 index 0000000..243607e --- /dev/null +++ b/test/models/todo_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class TodoTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end