Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@

# Ignore master key for decrypting credentials and more.
/config/master.key
Gemfile
Gemfile.lock
4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
source "https://rubygems.org"

ruby "3.2.3"
ruby "3.3.0"

# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.1.2"
Expand Down Expand Up @@ -66,3 +66,5 @@ group :test do
gem "selenium-webdriver"
gem "webdrivers"
end

gem 'bootstrap', '~> 5.0.1'
21 changes: 20 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,17 @@ GEM
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
autoprefixer-rails (10.4.16.0)
execjs (~> 2)
base64 (0.2.0)
bigdecimal (3.1.6)
bindex (0.8.1)
bootsnap (1.17.1)
msgpack (~> 1.2)
bootstrap (5.0.2)
autoprefixer-rails (>= 9.1.0)
popper_js (>= 2.9.2, < 3)
sassc-rails (>= 2.0.0)
builder (3.2.4)
capybara (3.39.2)
addressable
Expand All @@ -102,6 +108,8 @@ GEM
drb (2.2.0)
ruby2_keywords
erubi (1.12.0)
execjs (2.9.1)
ffi (1.16.3)
globalid (1.2.1)
activesupport (>= 6.1)
i18n (1.14.1)
Expand Down Expand Up @@ -153,6 +161,7 @@ GEM
racc (~> 1.4)
nokogiri (1.16.0-x86_64-linux)
racc (~> 1.4)
popper_js (2.11.8)
psych (5.1.2)
stringio
public_suffix (5.0.4)
Expand Down Expand Up @@ -205,6 +214,14 @@ GEM
rexml (3.2.6)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
sassc (2.4.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
selenium-webdriver (4.10.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
Expand All @@ -226,6 +243,7 @@ GEM
railties (>= 6.0.0)
stringio (3.1.0)
thor (1.3.0)
tilt (2.3.0)
timeout (0.4.1)
turbo-rails (1.5.0)
actionpack (>= 6.0.0)
Expand Down Expand Up @@ -260,6 +278,7 @@ PLATFORMS

DEPENDENCIES
bootsnap
bootstrap (~> 5.0.1)
capybara
debug
importmap-rails
Expand All @@ -276,7 +295,7 @@ DEPENDENCIES
webdrivers

RUBY VERSION
ruby 3.2.3p157
ruby 3.3.0p0

BUNDLED WITH
2.5.5
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,12 @@
*= require_tree .
*= require_self
*/


//Import Bootstrap styles
@import "bootstrap";


body {
background-color: #333;
}
70 changes: 70 additions & 0 deletions app/controllers/articles_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# The ArticlesController is responsible for managing the lifecycle of articles in the application.
# It handles the standard CRUD operations: create, read, update, and delete.

class ArticlesController < ApplicationController
# The 'index' action is responsible for listing all articles in the application.
def index
@articles = Article.search(params[:term])
end

# The 'show' action retrieves a single article by its ID and displays it.
def show
@article = Article.find(params[:id])
end

# The `new` action initializes a new, unsaved article for the form.
def new
@article = Article.new
end

# The `create` action attempts to save a new article to the database from the form data.
def create
@article = Article.new(article_params)

# Set the article's date to the current time if it is not provided. This is to ensure that the article's date is always accurate.
if @article.date.nil?
@article.date = Time.current
end

# If the article is successfully saved, redirect to the article's page. Otherwise, render the `new` template with the provided errors.
if @article.save
redirect_to articles_path, notice: "Article was successfully created."
else
render :new, status: :unprocessable_entity
end
end

# The 'edit' action retrieves an existing article by its ID for the form.
def edit
@article = Article.find(params[:id])
end

# The `update` action attempts to save changes to an existing article to the database from the form data.
def update
@article = Article.find(params[:id])

# Set the article's date to the current time if it is not provided. This is to ensure that the article's date is always accurate.
if @article.update(article_params)
@article.update(date: Time.current)
# If the article is successfully saved, redirect to the article's page. Otherwise, render the `edit` template with the provided errors.
redirect_to @article, notice: "Article was successfully updated."
else
render :edit, status: :unprocessable_entity
end
end

# The `destroy` action deletes an existing article by its ID from the database.
def destroy
@article = Article.find(params[:id])
@article.destroy

redirect_to root_path, status: :see_other
end

private

# Strong Parameters: only allow the whitelisted parameters to be used to create/update an article.
def article_params
params.require(:article).permit(:title, :content, :author, :date)
end
end
2 changes: 2 additions & 0 deletions app/helpers/articles_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module ArticlesHelper
end
8 changes: 6 additions & 2 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//= require bootstrap

// Added bootstrap to style

// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"
import "@hotwired/turbo-rails";
import "controllers";
15 changes: 15 additions & 0 deletions app/models/article.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Article < ApplicationRecord
# Validate rules checking to see the presence of the title and content.
validates :title, :content, presence: true

# The `search` class method allows for searching articles by title, content, or author.
# If a search term is provided, it returns all articles where the title, content, or author matches the term.
# If no term is provided, it returns all articles.
def self.search(term)
if term
where('title LIKE ? OR content LIKE ? OR author LIKE ?' , "%#{term}%", "%#{term}%", "%#{term}%")
else
all
end
end
end
45 changes: 45 additions & 0 deletions app/views/articles/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<%# This is a form partial for articles. It's used in the new and edit views. %>

<div class="d-flex justify-content-center mt-4">
<div class="card" style="width: 30rem;">
<div class="card-body">

<h2 class="card-title text-center"> <%= @article.persisted? ? 'Edit Article' : 'New Article' %> </h2>
<%# Use the form_with helper to start the form. If @article is a new record, this will post to the create action.
If @article is an existing record, this will patch to the update action. %>
<%= form_with model: article, class: 'needs-validation', novalidate: true do |form| %>

<%# A form group for the author %>
<div class="form-group mb-3">
<%= form.label :author, class: 'form-label' %>
<%= form.text_field :author, value: @article.author, class: 'form-control', style: 'color: black;' %>
</div>

<%# A form group for the article title %>
<div class="form-group mb-3">
<%= form.label :title, class: 'form-label' %>
<%= form.text_field :title, value: @article.title, class: 'form-control', style: 'color: black;' %>
<% article.errors.full_messages_for(:title).each do |message| %>
<div class="invalid-feedback"><%= message %></div>
<% end %>
</div>

<%# A form group for the article content %>
<div class="form-group mb-3 ">
<%= form.label :content, class: 'form-label' %>
<%= form.text_area :content, value: @article.content, class: 'form-control', style: 'color: black;' %>
<% article.errors.full_messages_for(:content).each do |message| %>
<div class="invalid-feedback"><%= message %></div>
<% end %>
</div>


<%# The form submit button. The button text will be "Create Article" or "Update Article" based on
whether @article is a new record or an existing record. %>
<div class="form-group mt-3">
<%= form.submit class: 'btn btn-primary' %>
</div>
<% end %>
</div>
</div>
</div>
4 changes: 4 additions & 0 deletions app/views/articles/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<%# Render the _form partial, passing in the @article instance variable.
The _form partial uses this variable to display the form and populate the fields with the existing article data. %>

<%= render "form", article: @article %>
49 changes: 49 additions & 0 deletions app/views/articles/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<%# This is the index view for the articles. It displays a list of all articles. %>

<header class="py-3 bg-dark text-white text-center">
<h1>Shopify Encyclopedia</h1>
</header>

<%# Creates a div class for a container for a search bar%>
<div class="containe mt-4">
<div class="row justify-content-center">
<div class="col-lg-6">
<%= form_with(url: articles_path, method: "get", local: true, class: "mb-3") do %>
<div class="input-group">
<%= text_field_tag(:term, params[:term], class: "form-control", placeholder: "Search", style: "margin-right: 20px;") %>
<%= submit_tag("Search", class: "btn btn-primary") %>
</div>
<% end %>
</div>
</div>
</div>

<div class="d-flex justify-content-center mb-4">
<%# Display a link to the new article form %>
<%= link_to 'New Article', new_article_path, class: 'btn btn-success' %>
</div>

<div class="row mt-4">
<%# Loop over each article in the @articles array %>
<% @articles.each do |article| %>
<%# Creates a bootstrap card class that displays each article in the view separately %>
<div class="col-md-4 mb-4">
<div class="card">
<div class="card-body">
<h2 class="card-title"><%= article.title %></h2>
<h3 class="card-subtitle mb-2 text-muted">Author: <%= article.author %></h3>
<p class="card-text"> <%= article.content %> </p>
<%# Link to the article's show page with a 'Read' button %>
<%= link_to 'Read', article, class: 'btn btn-primary' %>
<%# Link to the article's edit page with an 'Edit' button %>
<%= link_to 'Edit', edit_article_path(article), class: 'btn btn-primary' %>
<%# Link to delete the article with a 'Delete' button.
This will trigger a DELETE HTTP request to /articles/:id.
A confirmation dialog will be displayed before the article is deleted. %>
<%= link_to 'Delete', article_path(article), data: { turbo_method: :delete, turbo_confirm: 'Are you sure?' }, class: 'btn btn-danger' %>
</div>
</div>
</div>
<% end %>
</div>

3 changes: 3 additions & 0 deletions app/views/articles/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%# Render the _form partial, passing in the @article instance variable.
The _form partial uses this variable to display the form and populate the fields with the existing article data. %>
<%= render "form", article: @article %>
22 changes: 22 additions & 0 deletions app/views/articles/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<%# This is the show view for the articles. It displays the details of a single article. %>

<div class="d-flex justify-content-center mt-4">
<div class="card" style="width: 30rem;">
<div class="card-body">
<%# Display the title of the article %>
<h2 class="card-title"><%= @article.title %></h2>
<%# Display the author of the article %>
<h3 class="card-subtitle mb-2 text-muted">Author: <%= @article.author %></h3>
<%# Display the date the article was published %>
<p class="card-text"><strong>Publishing Date:</strong> <%= @article.date %></p>
<%# Display the content of the article %>
<p class="card-text"> <%= @article.content %> </p>
<%= link_to 'Edit', edit_article_path(@article), class: 'btn btn-primary' %>
<%# Display a link to delete the article. This will trigger a DELETE HTTP request to /articles/:id.
A confirmation dialog will be displayed before the article is deleted. %>
<%= link_to 'Delete', article_path(@article), data: { turbo_method: :delete, turbo_confirm: 'Are you sure?' }, class: 'btn btn-danger' %>
<%# Display a link to the articles index page %>
<%= link_to 'Back', articles_path, class: 'btn btn-secondary' %>
</div>
</div>
</div>
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@

# Defines the root path route ("/")
# root "posts#index"
root "articles#index"

# Defines the routes for the articles controller
resources :articles
end
10 changes: 10 additions & 0 deletions db/migrate/20240129213444_create_articles.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CreateArticles < ActiveRecord::Migration[7.1]
def change
create_table :articles do |t|
t.string :title
t.text :body

t.timestamps
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class RenameBodyToContentInArticles < ActiveRecord::Migration[7.1]
def change
rename_column :articles, :body, :content

end
end
5 changes: 5 additions & 0 deletions db/migrate/20240130010108_add_author_to_articles.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddAuthorToArticles < ActiveRecord::Migration[7.1]
def change
add_column :articles, :author, :string
end
end
5 changes: 5 additions & 0 deletions db/migrate/20240130012020_add_date_to_articles.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddDateToArticles < ActiveRecord::Migration[7.1]
def change
add_column :articles, :date, :datetime
end
end
9 changes: 9 additions & 0 deletions db/migrate/20240130014508_change_date_default_in_articles.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class ChangeDateDefaultInArticles < ActiveRecord::Migration[7.1]
def up
change_column :articles, :date, :datetime, default: -> { 'CURRENT_TIMESTAMP' }
end

def down
change_column :articles, :date, :datetime, default: nil
end
end
6 changes: 6 additions & 0 deletions db/migrate/20240130020815_remove_timestamps_from_articles.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class RemoveTimestampsFromArticles < ActiveRecord::Migration[6.0]
def change
remove_column :articles, :created_at, :datetime
remove_column :articles, :updated_at, :datetime
end
end
Loading