diff options
| -rw-r--r-- | .ruby-version | 2 | ||||
| -rw-r--r-- | .tool-versions | 1 | ||||
| -rw-r--r-- | app/controllers/api/v1/blog_controller.rb | 29 | ||||
| -rw-r--r-- | app/javascript/components/Blogs.jsx | 66 | ||||
| -rw-r--r-- | app/javascript/components/Home.jsx | 7 | ||||
| -rw-r--r-- | app/javascript/routes/index.jsx | 2 | ||||
| -rw-r--r-- | app/models/blog.rb | 5 | ||||
| -rw-r--r-- | config/routes.rb | 9 | ||||
| -rw-r--r-- | db/migrate/20240409004746_create_blogs.rb | 14 | ||||
| -rw-r--r-- | db/schema.rb | 74 | ||||
| -rw-r--r-- | db/seeds.rb | 8 | ||||
| -rw-r--r-- | test/controllers/api/v1/blog_controller_test.rb | 23 | ||||
| -rw-r--r-- | test/fixtures/blogs.yml | 17 | ||||
| -rw-r--r-- | test/models/blog_test.rb | 7 |
14 files changed, 263 insertions, 1 deletions
diff --git a/.ruby-version b/.ruby-version index 14dbd37..9e79f6c 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -ruby-3.0.6 +ruby-3.2.2 diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..f2a971a --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +ruby 3.2.2 diff --git a/app/controllers/api/v1/blog_controller.rb b/app/controllers/api/v1/blog_controller.rb new file mode 100644 index 0000000..4594645 --- /dev/null +++ b/app/controllers/api/v1/blog_controller.rb @@ -0,0 +1,29 @@ +class Api::V1::BlogController < ApplicationController + before_action :set_blog, only: %i[show destroy] + + def index + blog = Blog.all.order(created_at: :desc) + render json: blog + end + + def create + blog = Blog.Create!(blog_params) + if blog + render json: blog + else + render json: blog.errors + end + end + + def show + end + + def destroy + end + + private + + def blog_params + params.permit(:name, :image, :content, :category, :live_date, :update_date) + end +end diff --git a/app/javascript/components/Blogs.jsx b/app/javascript/components/Blogs.jsx new file mode 100644 index 0000000..f52f286 --- /dev/null +++ b/app/javascript/components/Blogs.jsx @@ -0,0 +1,66 @@ +import React, { useState, useEffect } from "react"; +import { Link, useNavigate } from "react-router-dom"; + +const Blogs = () => { + const navigate = useNavigate(); + const [blogs, setBlogs] = useState([]); + + useEffect(() => { + const url = "/api/v1/blogs/index"; + fetch(url).then((response) => { + if (response.ok) { + return response.json(); + } + throw new Error("Network response was not ok."); + }).then((response) => setBlogs(response)).catch(() => navigate("/")); + }, []); + + const allBlogs = blogs.map((blog, index) => ( + <div key={index} className="col-md-6 col-lg-4"> + <div className="card mb-4"> + <img src={blog.image} className="card-img-top" alt={`${blog.name} image`}/> + <div className="card-body"> + <h5 className="card-title">{blog.name}</h5> + <Link to={`/blog/${blog.id}`} className="btn custom-button"> + View Post + </Link> + </div> + </div> + </div> + )); + const noBlog = ( + <div className="vw-100 vh-50 dflex align-items-center justify-content-center"> + <h4> Nothing Yet! </h4> + </div> + ); + + return ( + <> + <section className="jumbotron jumbotron-fluid text-center"> + <div className="container py-5"> + <h1 className="display-4">Welcome to my Blog</h1> + <p className="lead text-muted"> + Yup, this is my blog and stuff. Enjoy it :) + </p> + </div> + </section> + <div className="py-5"> + <main className="container"> + <div className="text-end mb-3"> + <Link to="/blog" className="btn custom-button"> + Write New Blog + </Link> + </div> + <div className="row"> + {blogs.length > 0 ? allBlogs : noBlog} + </div> + <Link to="/" className="btn btn-link"> + Home + </Link> + </main> + </div> + </> + ); +}; + +export default Blogs; diff --git a/app/javascript/components/Home.jsx b/app/javascript/components/Home.jsx index b6c21e2..563ec88 100644 --- a/app/javascript/components/Home.jsx +++ b/app/javascript/components/Home.jsx @@ -17,6 +17,13 @@ export default () => ( > View Games </Link> + <Link + to="/blogs" + className="btn btn-lg custom-button" + role="button" + > + View Blogs + </Link> </div> </div> </div> diff --git a/app/javascript/routes/index.jsx b/app/javascript/routes/index.jsx index e231cc5..ac0f9ae 100644 --- a/app/javascript/routes/index.jsx +++ b/app/javascript/routes/index.jsx @@ -1,11 +1,13 @@ import React from "react"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import Home from "../components/Home"; +import Blogs from "../components/Blogs"; export default ( <Router> <Routes> <Route path="/" element = {<Home />} /> + <Route path="/blogs" element={<Blogs />} /> </Routes> </Router> ); diff --git a/app/models/blog.rb b/app/models/blog.rb new file mode 100644 index 0000000..5afa227 --- /dev/null +++ b/app/models/blog.rb @@ -0,0 +1,5 @@ +class Blog < ApplicationRecord + validates :name, presence: true + validates :content, presence: true + validates :category, presence: true +end diff --git a/config/routes.rb b/config/routes.rb index 06dda8f..5025b1b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,14 @@ Rails.application.routes.draw do + namespace :api do + namespace :v1 do + get 'blogs/index', to: 'blog#index' + post 'blogs/create', to: 'blog#create' + get '/show/:id', to: 'blog#show' + delete '/destroy/:id', to: 'blog#destroy' + end + end root 'homepage#index' + #get '/*path' => 'homepage#index' # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. diff --git a/db/migrate/20240409004746_create_blogs.rb b/db/migrate/20240409004746_create_blogs.rb new file mode 100644 index 0000000..09b3442 --- /dev/null +++ b/db/migrate/20240409004746_create_blogs.rb @@ -0,0 +1,14 @@ +class CreateBlogs < ActiveRecord::Migration[7.1] + def change + create_table :blogs do |t| + t.string :name, null: false + t.string :category, null: false + t.text :content, null: false + t.string :image, default: 'https://tradam.dev/images/logo.png' + t.date :live_date + t.date :update_date + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000..8ba434e --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,74 @@ +# 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. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[7.1].define(version: 2024_04_09_004746) do + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "active_storage_attachments", force: :cascade do |t| + t.string "name", null: false + t.string "record_type", null: false + t.bigint "record_id", null: false + t.bigint "blob_id", null: false + t.datetime "created_at", null: false + t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" + t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true + end + + create_table "active_storage_blobs", force: :cascade do |t| + t.string "key", null: false + t.string "filename", null: false + t.string "content_type" + t.text "metadata" + t.string "service_name", null: false + t.bigint "byte_size", null: false + t.string "checksum" + t.datetime "created_at", null: false + t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true + end + + create_table "active_storage_variant_records", force: :cascade do |t| + t.bigint "blob_id", null: false + t.string "variation_digest", null: false + t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true + end + + create_table "attachments", force: :cascade do |t| + t.string "filename", null: false + t.binary "data", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "blogs", force: :cascade do |t| + t.string "name", null: false + t.string "category", null: false + t.text "content", null: false + t.string "image", default: "https://tradam.dev/images/logo.png" + t.date "live_date" + t.date "update_date" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "recipes", force: :cascade do |t| + t.string "name", null: false + t.text "ingredients", null: false + t.text "instruction", null: false + t.string "image", default: "https://raw.githubusercontent.com/do-community/react_rails_recipe/master/app/assets/images/Sammy_Meal.jpg" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" + add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" +end diff --git a/db/seeds.rb b/db/seeds.rb index 4fbd6ed..129cf7c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -7,3 +7,11 @@ # ["Action", "Comedy", "Drama", "Horror"].each do |genre_name| # MovieGenre.find_or_create_by!(name: genre_name) # end + +9.times do |i| + Blog.create!( + name: "Blog Post #{i + 1}", + content: "This is just some placeholder blog content :3", + category: "Test Blog", + ) +end diff --git a/test/controllers/api/v1/blog_controller_test.rb b/test/controllers/api/v1/blog_controller_test.rb new file mode 100644 index 0000000..e381f63 --- /dev/null +++ b/test/controllers/api/v1/blog_controller_test.rb @@ -0,0 +1,23 @@ +require "test_helper" + +class Api::V1::BlogControllerTest < ActionDispatch::IntegrationTest + test "should get index" do + get api_v1_blog_index_url + assert_response :success + end + + test "should get create" do + get api_v1_blog_create_url + assert_response :success + end + + test "should get show" do + get api_v1_blog_show_url + assert_response :success + end + + test "should get destroy" do + get api_v1_blog_destroy_url + assert_response :success + end +end diff --git a/test/fixtures/blogs.yml b/test/fixtures/blogs.yml new file mode 100644 index 0000000..3dc1deb --- /dev/null +++ b/test/fixtures/blogs.yml @@ -0,0 +1,17 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + category: MyString + content: MyText + image: MyString + live_date: 2024-04-08 + update_date: 2024-04-08 + +two: + name: MyString + category: MyString + content: MyText + image: MyString + live_date: 2024-04-08 + update_date: 2024-04-08 diff --git a/test/models/blog_test.rb b/test/models/blog_test.rb new file mode 100644 index 0000000..0bef141 --- /dev/null +++ b/test/models/blog_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class BlogTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end |
