Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Emmanuel Idun] Encyclopedia CRUD Application #295

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile.lock
Expand Up @@ -233,6 +233,8 @@ GEM
railties (>= 6.0.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
tzinfo-data (1.2023.4)
tzinfo (>= 1.0.0)
web-console (4.2.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
Expand Down
108 changes: 108 additions & 0 deletions app/controllers/articles_controller.rb
@@ -0,0 +1,108 @@
class ArticlesController < ApplicationController
before_action :set_article, only: %i[ show edit update destroy ]

# GET /articles or /articles.json
def index
@articles = Article.all

# Default values
sort_column = params[:sort] || 'title'
sort_order = params[:order] || 'asc'

# Toggle the order if sorting on the same column
sort_order = toggle_order(sort_order) if sort_column == params[:sort]

# Sorting logic based on sort_column and sort_order
case sort_column
when 'title'
@articles = @articles.order(title: sort_order)
when 'author'
@articles = @articles.order(author: sort_order)
when 'date'
@articles = @articles.order(date: sort_order)
end
end

# GET /articles/search
def search
@query = params[:query]
@results = Article.search(@query)

if @query.present?
if @results&.any?
@articles = @results
else
@articles = []
end
else
@articles = Article.all
end
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_url(@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_url(@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

# Toggle between ascending order and descending order
def toggle_order(order)
order == 'asc' ? 'desc' : 'asc'
end

# Only allow a list of trusted parameters through.
def article_params
params.require(:article).permit(:title, :content, :author, :date)
end
end
7 changes: 7 additions & 0 deletions app/controllers/pages_controller.rb
@@ -0,0 +1,7 @@
class PagesController < ApplicationController
def home
end

def about
end
end
2 changes: 2 additions & 0 deletions app/helpers/articles_helper.rb
@@ -0,0 +1,2 @@
module ArticlesHelper
end
2 changes: 2 additions & 0 deletions app/helpers/pages_helper.rb
@@ -0,0 +1,2 @@
module PagesHelper
end
9 changes: 9 additions & 0 deletions app/models/article.rb
@@ -0,0 +1,9 @@
class Article < ApplicationRecord
validates :title, presence: true
validates :content, presence: true

# perform case-insentitive search on title or content of articles
def self.search(query)
where("title LIKE ? OR content LIKE ?", "%#{query}%", "%#{query}%")
end
end
16 changes: 16 additions & 0 deletions app/views/articles/_article.html.erb
@@ -0,0 +1,16 @@
<div id="<%= dom_id article %>">

<div class="card text-center">
<div class="card-header">
By <%= article.author %>
</div>
<div class="card-body">
<h5 class="card-title"><%= article.title %></h5>
<p class="card-text"><%= article.content %></p>
</div>
<div class="card-footer text-body-secondary">
<%= article.date %>
</div>
</div>

</div>
2 changes: 2 additions & 0 deletions app/views/articles/_article.json.jbuilder
@@ -0,0 +1,2 @@
json.extract! article, :id, :title, :content, :author, :date, :created_at, :updated_at
json.url article_url(article, format: :json)
38 changes: 38 additions & 0 deletions app/views/articles/_form.html.erb
@@ -0,0 +1,38 @@
<%= form_with(model: article) do |form| %>
<% if article.errors.any? %>
<div style="color: red">
<h2><%= pluralize(article.errors.count, "error") %> prohibited this article from being saved:</h2>

<ul>
<% article.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>

<div class="field form-group">
<%= form.text_field :author, class:"form-control", placeholder:"Author" %>
</div>

<div class="field form-group">
<%= form.text_field :title, class:"form-control", placeholder:"Title" %>
</div>

<div class="field form-group">
<%= form.text_area :content, class:"form-control", placeholder:"Fill with your content" %>
</div>

<div class="field form-group">
<%= form.date_field :date, id: :article_date, class:"form-control", value:Date.today, type: :hidden %>
</div>

<%# <div class="field form-group"> %>
<%# <%= form.text_field :user_id, id: :article_user_id, class:"form-control", value:current_user.id, type: :hidden %>
<%# %>
<%# </div> %>

<div class="actions">
<%= form.submit "Save", class:"btn btn-primary" %>
</div>
<% end %>
24 changes: 24 additions & 0 deletions app/views/articles/_table.html.erb
@@ -0,0 +1,24 @@
<table id="articles" class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th><%= link_to "Title", articles_path(sort: 'title') %></th>
<th><%= link_to "Author", articles_path(sort: 'author') %></th>
<th><%= link_to "Date Posted", articles_path(sort: 'date') %></th>
</tr>
</thead>

<% if @articles.present? %>
<% @articles.each do |article| %>
<tr>
<td><%= link_to "#{article.title}", article %></td>
<td><%=article.author %></td>
<td><%=article.date %></td>
</tr>
<% end %>
<% else %>
<tr>
<td colspan="2">No articles found.</td>
</tr>
<% end %>

</table>
10 changes: 10 additions & 0 deletions app/views/articles/edit.html.erb
@@ -0,0 +1,10 @@
<h1>Editing article</h1>

<%= render "form", article: @article %>

<br>

<div>
<%= link_to "Details...", @article, class:"btn btn-primary" %>
<%= link_to "Back", articles_path, class:"btn btn-dark" %>
</div>
5 changes: 5 additions & 0 deletions app/views/articles/index.html.erb
@@ -0,0 +1,5 @@
<h1>Articles</h1>

<%= render "table" %>

<%= link_to "New article", new_article_path, class:"btn btn-secondary" %>
1 change: 1 addition & 0 deletions app/views/articles/index.json.jbuilder
@@ -0,0 +1 @@
json.array! @articles, partial: "articles/article", as: :article
9 changes: 9 additions & 0 deletions app/views/articles/new.html.erb
@@ -0,0 +1,9 @@
<h1>New article</h1>

<%= render "form", article: @article %>

<br>

<div>
<%= link_to "Back", articles_path, class:"btn btn-dark" %>
</div>
5 changes: 5 additions & 0 deletions app/views/articles/search.html.erb
@@ -0,0 +1,5 @@
<h1>Articles</h1>

<%= render "table" %>

<%= link_to "New article", new_article_path, class:"btn btn-secondary" %>
8 changes: 8 additions & 0 deletions app/views/articles/show.html.erb
@@ -0,0 +1,8 @@
<%= render @article %>

<div>
<%= link_to "Edit", edit_article_path(@article) , class:"btn btn-secondary" %>
<%= link_to "Back", articles_path, class:"btn btn-dark" %>

<%= button_to "Delete", @article, method: :delete, class:"btn btn-danger" %>
</div>
1 change: 1 addition & 0 deletions app/views/articles/show.json.jbuilder
@@ -0,0 +1 @@
json.partial! "articles/article", article: @article
26 changes: 26 additions & 0 deletions app/views/layouts/_navbar.html.erb
@@ -0,0 +1,26 @@
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<%= link_to "Shopify Encyclopedia", root_path, class:"nav-link" %>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<%= link_to "About Us", about_path, class:"nav-link" %>
</li>

<li class="nav-item">
<%= link_to "Articles", articles_path, class:"nav-link" %>
</li>
<li class="nav-item">
<%= link_to "Add Article", new_article_path, class:"nav-link" %>
</li>
</ul>
<ul class="navbar-nav">
<%= render 'layouts/searchForm' %>
</ul>
</div>
</div>
</nav>

4 changes: 4 additions & 0 deletions app/views/layouts/_searchForm.html.erb
@@ -0,0 +1,4 @@
<%= form_tag(article_search_path, method: 'get', class: "d-flex") do %>
<%= text_field_tag(:query, params[:query], class: "form-control me-2", placeholder: 'Search articles...') %>
<%= submit_tag('Search', class: "btn btn-outline-success") %>
<% end %>
3 changes: 3 additions & 0 deletions app/views/layouts/application.html.erb
Expand Up @@ -8,9 +8,12 @@

<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>

<body>
<%= render 'layouts/navbar' %>
<%= yield %>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
</body>
</html>
4 changes: 4 additions & 0 deletions app/views/pages/about.html.erb
@@ -0,0 +1,4 @@
<div class="container">
<h1>Shopify Encyclopedia</h1>
<p>Shopify Encyclopedia is the place to be for all the gist within Shopify. For non-employees, you wold be able to have some transparency on our company mission and values</p>
</div>
4 changes: 4 additions & 0 deletions app/views/pages/home.html.erb
@@ -0,0 +1,4 @@
<div class="container">
<h1>Welcome to Shopify Encyclopedia</h1>
<p>Feel free to browse</p>
</div>
8 changes: 6 additions & 2 deletions config/routes.rb
@@ -1,10 +1,14 @@
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

resources :articles

get '/about', to: 'pages#about'
get '/articles/search', to: 'articles#search', as: 'article_search'

# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
# Can be used by load balancers and uptime monitors to verify that the app is live.
get "up" => "rails/health#show", as: :rails_health_check

# Defines the root path route ("/")
# root "posts#index"
root "pages#home"
end
12 changes: 12 additions & 0 deletions db/migrate/20240125082905_create_articles.rb
@@ -0,0 +1,12 @@
class CreateArticles < ActiveRecord::Migration[7.1]
def change
create_table :articles do |t|
t.string :title
t.text :content
t.string :author
t.date :date

t.timestamps
end
end
end
23 changes: 23 additions & 0 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.