From bea88d4d33bac92fe90b3e40e725cfe658338063 Mon Sep 17 00:00:00 2001 From: Ryan W Date: Sun, 26 Sep 2021 15:22:36 -0700 Subject: [PATCH] ./bin/rails importmap:install --- app/controllers/articles_controller.rb | 69 ++++++++++ app/controllers/welcome_controller.rb | 4 + app/helpers/articles_helper.rb | 2 + app/helpers/welcome_helper.rb | 2 + app/javascript/application.js | 2 - app/models/article.rb | 2 + app/views/articles/_article.html.erb | 15 +++ app/views/articles/_article.json.jbuilder | 2 + app/views/articles/_form.html.erb | 27 ++++ app/views/articles/edit.html.erb | 10 ++ app/views/articles/index.html.erb | 9 ++ app/views/articles/index.json.jbuilder | 1 + app/views/articles/new.html.erb | 9 ++ app/views/articles/show.html.erb | 10 ++ app/views/articles/show.json.jbuilder | 1 + app/views/welcome/index.html.erb | 3 + bin/importmap | 5 +- config/importmap.rb | 8 +- config/routes.rb | 7 +- db/migrate/20210926221100_create_articles.rb | 10 ++ db/schema.rb | 15 ++- spec/helpers/articles_helper_spec.rb | 15 +++ spec/helpers/welcome_helper_spec.rb | 15 +++ spec/models/article_spec.rb | 5 + spec/requests/articles_spec.rb | 130 +++++++++++++++++++ spec/requests/welcome_spec.rb | 7 + spec/routing/articles_routing_spec.rb | 38 ++++++ spec/views/articles/edit.html.erb_spec.rb | 21 +++ spec/views/articles/index.html.erb_spec.rb | 22 ++++ spec/views/articles/new.html.erb_spec.rb | 21 +++ spec/views/articles/show.html.erb_spec.rb | 16 +++ 31 files changed, 484 insertions(+), 19 deletions(-) create mode 100644 app/controllers/articles_controller.rb create mode 100644 app/controllers/welcome_controller.rb create mode 100644 app/helpers/articles_helper.rb create mode 100644 app/helpers/welcome_helper.rb create mode 100644 app/models/article.rb create mode 100644 app/views/articles/_article.html.erb create mode 100644 app/views/articles/_article.json.jbuilder create mode 100644 app/views/articles/_form.html.erb create mode 100644 app/views/articles/edit.html.erb create mode 100644 app/views/articles/index.html.erb create mode 100644 app/views/articles/index.json.jbuilder create mode 100644 app/views/articles/new.html.erb create mode 100644 app/views/articles/show.html.erb create mode 100644 app/views/articles/show.json.jbuilder create mode 100644 app/views/welcome/index.html.erb create mode 100644 db/migrate/20210926221100_create_articles.rb create mode 100644 spec/helpers/articles_helper_spec.rb create mode 100644 spec/helpers/welcome_helper_spec.rb create mode 100644 spec/models/article_spec.rb create mode 100644 spec/requests/articles_spec.rb create mode 100644 spec/requests/welcome_spec.rb create mode 100644 spec/routing/articles_routing_spec.rb create mode 100644 spec/views/articles/edit.html.erb_spec.rb create mode 100644 spec/views/articles/index.html.erb_spec.rb create mode 100644 spec/views/articles/new.html.erb_spec.rb create mode 100644 spec/views/articles/show.html.erb_spec.rb diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb new file mode 100644 index 0000000..587b906 --- /dev/null +++ b/app/controllers/articles_controller.rb @@ -0,0 +1,69 @@ +class ArticlesController < ApplicationController + before_action :set_article, only: %i[ show edit update destroy ] + + # GET /articles or /articles.json + def index + @articles = Article.all + end + + # GET /articles/1 or /articles/1.json + def show + end + + # GET /articles/new + def new + @article = Article.new + end + + # GET /articles/1/edit + def edit + end + + # POST /articles or /articles.json + def create + @article = Article.new(article_params) + + respond_to do |format| + if @article.save + format.html { redirect_to @article, notice: "Article was successfully created." } + format.json { render :show, status: :created, location: @article } + else + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @article.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /articles/1 or /articles/1.json + def update + respond_to do |format| + if @article.update(article_params) + format.html { redirect_to @article, notice: "Article was successfully updated." } + format.json { render :show, status: :ok, location: @article } + else + format.html { render :edit, status: :unprocessable_entity } + format.json { render json: @article.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /articles/1 or /articles/1.json + def destroy + @article.destroy + respond_to do |format| + format.html { redirect_to articles_url, notice: "Article was successfully destroyed." } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_article + @article = Article.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def article_params + params.require(:article).permit(:title, :text) + end +end diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb new file mode 100644 index 0000000..f9b859b --- /dev/null +++ b/app/controllers/welcome_controller.rb @@ -0,0 +1,4 @@ +class WelcomeController < ApplicationController + def index + end +end diff --git a/app/helpers/articles_helper.rb b/app/helpers/articles_helper.rb new file mode 100644 index 0000000..2968277 --- /dev/null +++ b/app/helpers/articles_helper.rb @@ -0,0 +1,2 @@ +module ArticlesHelper +end diff --git a/app/helpers/welcome_helper.rb b/app/helpers/welcome_helper.rb new file mode 100644 index 0000000..eeead45 --- /dev/null +++ b/app/helpers/welcome_helper.rb @@ -0,0 +1,2 @@ +module WelcomeHelper +end diff --git a/app/javascript/application.js b/app/javascript/application.js index 0d7b494..beff742 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -1,3 +1 @@ // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails -import "@hotwired/turbo-rails" -import "controllers" diff --git a/app/models/article.rb b/app/models/article.rb new file mode 100644 index 0000000..b7a72b5 --- /dev/null +++ b/app/models/article.rb @@ -0,0 +1,2 @@ +class Article < ApplicationRecord +end diff --git a/app/views/articles/_article.html.erb b/app/views/articles/_article.html.erb new file mode 100644 index 0000000..3c37f1a --- /dev/null +++ b/app/views/articles/_article.html.erb @@ -0,0 +1,15 @@ +
+

+ Title: + <%= article.title %> +

+ +

+ Text: + <%= article.text %> +

+ +

+ <%= link_to "Show this article", article %> +

+
diff --git a/app/views/articles/_article.json.jbuilder b/app/views/articles/_article.json.jbuilder new file mode 100644 index 0000000..8f4e2e8 --- /dev/null +++ b/app/views/articles/_article.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! article, :id, :title, :text, :created_at, :updated_at +json.url article_url(article, format: :json) diff --git a/app/views/articles/_form.html.erb b/app/views/articles/_form.html.erb new file mode 100644 index 0000000..ea47967 --- /dev/null +++ b/app/views/articles/_form.html.erb @@ -0,0 +1,27 @@ +<%= form_with(model: article) do |form| %> + <% if article.errors.any? %> +
+

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

+ + +
+ <% end %> + +
+ <%= form.label :title %> + <%= form.text_field :title %> +
+ +
+ <%= form.label :text %> + <%= form.text_area :text %> +
+ +
+ <%= form.submit %> +
+<% end %> diff --git a/app/views/articles/edit.html.erb b/app/views/articles/edit.html.erb new file mode 100644 index 0000000..4252d7a --- /dev/null +++ b/app/views/articles/edit.html.erb @@ -0,0 +1,10 @@ +

Editing article

+ +<%= render "form", article: @article %> + +
+ +
+ <%= link_to "Show this article", @article %> | + <%= link_to "Back to articles", articles_path %> +
diff --git a/app/views/articles/index.html.erb b/app/views/articles/index.html.erb new file mode 100644 index 0000000..f109472 --- /dev/null +++ b/app/views/articles/index.html.erb @@ -0,0 +1,9 @@ +

<%= notice %>

+ +

Article

+ +
+ <%= render @articles %> +
+ +<%= link_to "New article", new_article_path %> diff --git a/app/views/articles/index.json.jbuilder b/app/views/articles/index.json.jbuilder new file mode 100644 index 0000000..09a21f3 --- /dev/null +++ b/app/views/articles/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @articles, partial: "articles/article", as: :article diff --git a/app/views/articles/new.html.erb b/app/views/articles/new.html.erb new file mode 100644 index 0000000..ff360e1 --- /dev/null +++ b/app/views/articles/new.html.erb @@ -0,0 +1,9 @@ +

New article

+ +<%= render "form", article: @article %> + +
+ +
+ <%= link_to "Back to articles", articles_path %> +
diff --git a/app/views/articles/show.html.erb b/app/views/articles/show.html.erb new file mode 100644 index 0000000..75923cb --- /dev/null +++ b/app/views/articles/show.html.erb @@ -0,0 +1,10 @@ +

<%= notice %>

+ +<%= render @article %> + +
+ <%= link_to "Edit this article", edit_article_path(@article) %> | + <%= link_to "Back to articles", articles_path %> + + <%= button_to "Destroy this article", article_path(@article), method: :delete %> +
diff --git a/app/views/articles/show.json.jbuilder b/app/views/articles/show.json.jbuilder new file mode 100644 index 0000000..dd1fbb4 --- /dev/null +++ b/app/views/articles/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "articles/article", article: @article diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb new file mode 100644 index 0000000..30e0a75 --- /dev/null +++ b/app/views/welcome/index.html.erb @@ -0,0 +1,3 @@ +

Welcome

+ +<%= link_to "Articles", articles_path %> diff --git a/bin/importmap b/bin/importmap index d423864..36502ab 100755 --- a/bin/importmap +++ b/bin/importmap @@ -1,5 +1,4 @@ #!/usr/bin/env ruby -# frozen_string_literal: true -require_relative '../config/application' -require 'importmap/commands' +require_relative "../config/application" +require "importmap/commands" diff --git a/config/importmap.rb b/config/importmap.rb index ee7ddf7..f0e4a1c 100644 --- a/config/importmap.rb +++ b/config/importmap.rb @@ -1,12 +1,6 @@ -# frozen_string_literal: true - # Use direct uploads for Active Storage (remember to import "@rails/activestorage" in your application.js) # pin "@rails/activestorage", to: "activestorage.esm.js" # Use node modules from a JavaScript CDN by running ./bin/importmap -pin 'application' -pin '@hotwired/turbo-rails', to: 'turbo.js' -pin '@hotwired/stimulus', to: 'stimulus.js' -pin '@hotwired/stimulus-importmap-autoloader', to: 'stimulus-importmap-autoloader.js' -pin_all_from 'app/javascript/controllers', under: 'controllers' +pin "application" diff --git a/config/routes.rb b/config/routes.rb index 9d06ca2..13e9914 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true Rails.application.routes.draw do - # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html + get 'welcome/index' - # Almost every application defines a route for the root path ("/") at the top of this file. - # root "articles#index" + resources :articles + + root 'welcome#index' end diff --git a/db/migrate/20210926221100_create_articles.rb b/db/migrate/20210926221100_create_articles.rb new file mode 100644 index 0000000..b3c7ea3 --- /dev/null +++ b/db/migrate/20210926221100_create_articles.rb @@ -0,0 +1,10 @@ +class CreateArticles < ActiveRecord::Migration[7.0] + def change + create_table :articles do |t| + t.string :title + t.text :text + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index eb3e335..e036ec3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -12,7 +10,16 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 0) do +ActiveRecord::Schema.define(version: 2021_09_26_221100) do + # These are extensions that must be enabled in order to support this database - enable_extension 'plpgsql' + enable_extension "plpgsql" + + create_table "articles", force: :cascade do |t| + t.string "title" + t.text "text" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + end diff --git a/spec/helpers/articles_helper_spec.rb b/spec/helpers/articles_helper_spec.rb new file mode 100644 index 0000000..eac039d --- /dev/null +++ b/spec/helpers/articles_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the ArticlesHelper. For example: +# +# describe ArticlesHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe ArticlesHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/helpers/welcome_helper_spec.rb b/spec/helpers/welcome_helper_spec.rb new file mode 100644 index 0000000..a899852 --- /dev/null +++ b/spec/helpers/welcome_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the WelcomeHelper. For example: +# +# describe WelcomeHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe WelcomeHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb new file mode 100644 index 0000000..632e856 --- /dev/null +++ b/spec/models/article_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Article, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/requests/articles_spec.rb b/spec/requests/articles_spec.rb new file mode 100644 index 0000000..70398b7 --- /dev/null +++ b/spec/requests/articles_spec.rb @@ -0,0 +1,130 @@ + require 'rails_helper' + +# This spec was generated by rspec-rails when you ran the scaffold generator. +# It demonstrates how one might use RSpec to test the controller code that +# was generated by Rails when you ran the scaffold generator. +# +# It assumes that the implementation code is generated by the rails scaffold +# generator. If you are using any extension libraries to generate different +# controller code, this generated spec may or may not pass. +# +# It only uses APIs available in rails and/or rspec-rails. There are a number +# of tools you can use to make these specs even more expressive, but we're +# sticking to rails and rspec-rails APIs to keep things simple and stable. + +RSpec.describe "/articles", type: :request do + + # Article. As you add validations to Article, be sure to + # adjust the attributes here as well. + let(:valid_attributes) { + skip("Add a hash of attributes valid for your model") + } + + let(:invalid_attributes) { + skip("Add a hash of attributes invalid for your model") + } + + describe "GET /index" do + it "renders a successful response" do + Article.create! valid_attributes + get articles_url + expect(response).to be_successful + end + end + + describe "GET /show" do + it "renders a successful response" do + article = Article.create! valid_attributes + get article_url(article) + expect(response).to be_successful + end + end + + describe "GET /new" do + it "renders a successful response" do + get new_article_url + expect(response).to be_successful + end + end + + describe "GET /edit" do + it "render a successful response" do + article = Article.create! valid_attributes + get edit_article_url(article) + expect(response).to be_successful + end + end + + describe "POST /create" do + context "with valid parameters" do + it "creates a new Article" do + expect { + post articles_url, params: { article: valid_attributes } + }.to change(Article, :count).by(1) + end + + it "redirects to the created article" do + post articles_url, params: { article: valid_attributes } + expect(response).to redirect_to(article_url(Article.last)) + end + end + + context "with invalid parameters" do + it "does not create a new Article" do + expect { + post articles_url, params: { article: invalid_attributes } + }.to change(Article, :count).by(0) + end + + it "renders a successful response (i.e. to display the 'new' template)" do + post articles_url, params: { article: invalid_attributes } + expect(response).to be_successful + end + end + end + + describe "PATCH /update" do + context "with valid parameters" do + let(:new_attributes) { + skip("Add a hash of attributes valid for your model") + } + + it "updates the requested article" do + article = Article.create! valid_attributes + patch article_url(article), params: { article: new_attributes } + article.reload + skip("Add assertions for updated state") + end + + it "redirects to the article" do + article = Article.create! valid_attributes + patch article_url(article), params: { article: new_attributes } + article.reload + expect(response).to redirect_to(article_url(article)) + end + end + + context "with invalid parameters" do + it "renders a successful response (i.e. to display the 'edit' template)" do + article = Article.create! valid_attributes + patch article_url(article), params: { article: invalid_attributes } + expect(response).to be_successful + end + end + end + + describe "DELETE /destroy" do + it "destroys the requested article" do + article = Article.create! valid_attributes + expect { + delete article_url(article) + }.to change(Article, :count).by(-1) + end + + it "redirects to the articles list" do + article = Article.create! valid_attributes + delete article_url(article) + expect(response).to redirect_to(articles_url) + end + end +end diff --git a/spec/requests/welcome_spec.rb b/spec/requests/welcome_spec.rb new file mode 100644 index 0000000..36343d0 --- /dev/null +++ b/spec/requests/welcome_spec.rb @@ -0,0 +1,7 @@ +require 'rails_helper' + +RSpec.describe "Welcomes", type: :request do + describe "GET /index" do + pending "add some examples (or delete) #{__FILE__}" + end +end diff --git a/spec/routing/articles_routing_spec.rb b/spec/routing/articles_routing_spec.rb new file mode 100644 index 0000000..a258c95 --- /dev/null +++ b/spec/routing/articles_routing_spec.rb @@ -0,0 +1,38 @@ +require "rails_helper" + +RSpec.describe ArticlesController, type: :routing do + describe "routing" do + it "routes to #index" do + expect(get: "/articles").to route_to("articles#index") + end + + it "routes to #new" do + expect(get: "/articles/new").to route_to("articles#new") + end + + it "routes to #show" do + expect(get: "/articles/1").to route_to("articles#show", id: "1") + end + + it "routes to #edit" do + expect(get: "/articles/1/edit").to route_to("articles#edit", id: "1") + end + + + it "routes to #create" do + expect(post: "/articles").to route_to("articles#create") + end + + it "routes to #update via PUT" do + expect(put: "/articles/1").to route_to("articles#update", id: "1") + end + + it "routes to #update via PATCH" do + expect(patch: "/articles/1").to route_to("articles#update", id: "1") + end + + it "routes to #destroy" do + expect(delete: "/articles/1").to route_to("articles#destroy", id: "1") + end + end +end diff --git a/spec/views/articles/edit.html.erb_spec.rb b/spec/views/articles/edit.html.erb_spec.rb new file mode 100644 index 0000000..57d1cac --- /dev/null +++ b/spec/views/articles/edit.html.erb_spec.rb @@ -0,0 +1,21 @@ +require 'rails_helper' + +RSpec.describe "articles/edit", type: :view do + before(:each) do + @article = assign(:article, Article.create!( + title: "MyString", + text: "MyText" + )) + end + + it "renders the edit article form" do + render + + assert_select "form[action=?][method=?]", article_path(@article), "post" do + + assert_select "input[name=?]", "article[title]" + + assert_select "textarea[name=?]", "article[text]" + end + end +end diff --git a/spec/views/articles/index.html.erb_spec.rb b/spec/views/articles/index.html.erb_spec.rb new file mode 100644 index 0000000..a0acc23 --- /dev/null +++ b/spec/views/articles/index.html.erb_spec.rb @@ -0,0 +1,22 @@ +require 'rails_helper' + +RSpec.describe "articles/index", type: :view do + before(:each) do + assign(:articles, [ + Article.create!( + title: "Title", + text: "MyText" + ), + Article.create!( + title: "Title", + text: "MyText" + ) + ]) + end + + it "renders a list of articles" do + render + assert_select "tr>td", text: "Title".to_s, count: 2 + assert_select "tr>td", text: "MyText".to_s, count: 2 + end +end diff --git a/spec/views/articles/new.html.erb_spec.rb b/spec/views/articles/new.html.erb_spec.rb new file mode 100644 index 0000000..50a809c --- /dev/null +++ b/spec/views/articles/new.html.erb_spec.rb @@ -0,0 +1,21 @@ +require 'rails_helper' + +RSpec.describe "articles/new", type: :view do + before(:each) do + assign(:article, Article.new( + title: "MyString", + text: "MyText" + )) + end + + it "renders new article form" do + render + + assert_select "form[action=?][method=?]", articles_path, "post" do + + assert_select "input[name=?]", "article[title]" + + assert_select "textarea[name=?]", "article[text]" + end + end +end diff --git a/spec/views/articles/show.html.erb_spec.rb b/spec/views/articles/show.html.erb_spec.rb new file mode 100644 index 0000000..090619c --- /dev/null +++ b/spec/views/articles/show.html.erb_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +RSpec.describe "articles/show", type: :view do + before(:each) do + @article = assign(:article, Article.create!( + title: "Title", + text: "MyText" + )) + end + + it "renders attributes in

" do + render + expect(rendered).to match(/Title/) + expect(rendered).to match(/MyText/) + end +end