Compare commits
10 Commits
b75f9277cc
...
6f32112b2a
Author | SHA1 | Date |
---|---|---|
Trevor Vallender | 6f32112b2a | |
Trevor Vallender | 5d0a1b1612 | |
Trevor Vallender | e0c12a9760 | |
Trevor Vallender | fe197ebe9a | |
Trevor Vallender | 059d59e437 | |
Trevor Vallender | b7bbd85c7e | |
Trevor Vallender | 1d9efa6cab | |
Trevor Vallender | d5b587499c | |
Trevor Vallender | 6358e2a61e | |
Trevor Vallender | ad03410a65 |
|
@ -12,3 +12,4 @@
|
||||||
# KAMAL_RUNTIME
|
# KAMAL_RUNTIME
|
||||||
|
|
||||||
echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds"
|
echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds"
|
||||||
|
kamal app exec --reuse "bin/rails db:migrate"
|
1
Gemfile
1
Gemfile
|
@ -15,6 +15,7 @@ gem "bcrypt", "~> 3.1.7"
|
||||||
gem "bootsnap", require: false
|
gem "bootsnap", require: false
|
||||||
|
|
||||||
gem "kaminari" # Pagination
|
gem "kaminari" # Pagination
|
||||||
|
gem "solid_cache"
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem "debug", platforms: %i[ mri mingw x64_mingw ]
|
gem "debug", platforms: %i[ mri mingw x64_mingw ]
|
||||||
|
|
|
@ -229,6 +229,8 @@ GEM
|
||||||
rexml (~> 3.2, >= 3.2.5)
|
rexml (~> 3.2, >= 3.2.5)
|
||||||
rubyzip (>= 1.2.2, < 3.0)
|
rubyzip (>= 1.2.2, < 3.0)
|
||||||
websocket (~> 1.0)
|
websocket (~> 1.0)
|
||||||
|
solid_cache (0.1.0)
|
||||||
|
rails (>= 7)
|
||||||
sprockets (4.2.1)
|
sprockets (4.2.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
rack (>= 2.2.4, < 4)
|
rack (>= 2.2.4, < 4)
|
||||||
|
@ -281,6 +283,7 @@ DEPENDENCIES
|
||||||
puma
|
puma
|
||||||
rails (~> 7.1)
|
rails (~> 7.1)
|
||||||
selenium-webdriver
|
selenium-webdriver
|
||||||
|
solid_cache
|
||||||
sprockets-rails
|
sprockets-rails
|
||||||
stimulus-rails
|
stimulus-rails
|
||||||
turbo-rails
|
turbo-rails
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
:root {
|
:root {
|
||||||
--border-color: gray;
|
--border-color: #282828;
|
||||||
--highlight-color: #D36200;
|
--highlight-color: #d65d0e;
|
||||||
--background-color: #CCC;
|
--background-color: #928374;
|
||||||
--dark-background-color: #333;
|
--dark-background-color: #1d2021;
|
||||||
--inset-background-color: #FFFFFF;
|
--inset-background-color: #fbf1c7;
|
||||||
--alert-border-color: #800000;
|
--alert-border-color: #98971a;
|
||||||
--form-error-color: #FF0000;
|
--form-error-color: #cc241d;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
|
@ -23,6 +23,10 @@ form#micropost_form {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul#microposts {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
.micropost {
|
.micropost {
|
||||||
margin: 1em auto;
|
margin: 1em auto;
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
|
@ -33,4 +37,16 @@ form#micropost_form {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font-size: .8em;
|
font-size: .8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.micropost-tags {
|
||||||
|
list-style-type: none;
|
||||||
|
display: inline;
|
||||||
|
li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ class MicropostsController < ApplicationController
|
||||||
def create
|
def create
|
||||||
micropost = Micropost.new(micropost_params)
|
micropost = Micropost.new(micropost_params)
|
||||||
micropost.user = helpers.current_user
|
micropost.user = helpers.current_user
|
||||||
|
micropost.set_tags(*parse_tags(params[:tags])) if params[:tags]
|
||||||
if micropost.save
|
if micropost.save
|
||||||
redirect_to micropost, notice: t(".created")
|
redirect_to micropost, notice: t(".created")
|
||||||
else
|
else
|
||||||
|
@ -29,6 +30,7 @@ class MicropostsController < ApplicationController
|
||||||
def edit; end
|
def edit; end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
@micropost.set_tags(*parse_tags(params[:tags])) if params[:tags]
|
||||||
if @micropost.update(micropost_params)
|
if @micropost.update(micropost_params)
|
||||||
redirect_to @micropost, notice: t(".updated")
|
redirect_to @micropost, notice: t(".updated")
|
||||||
else
|
else
|
||||||
|
@ -46,6 +48,10 @@ class MicropostsController < ApplicationController
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def parse_tags(tags)
|
||||||
|
tags.split
|
||||||
|
end
|
||||||
|
|
||||||
def micropost_params
|
def micropost_params
|
||||||
params.require(:micropost).permit(
|
params.require(:micropost).permit(
|
||||||
:content,
|
:content,
|
||||||
|
|
|
@ -9,7 +9,8 @@ class SessionsController < ApplicationController
|
||||||
def new; end
|
def new; end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
if @user.present? && @user.authenticate(params[:password])
|
@user = User.authenticate_by(username: params[:username], password: params[:password])
|
||||||
|
if @user
|
||||||
session[:user_id] = @user.id
|
session[:user_id] = @user.id
|
||||||
redirect_to root_path, notice: t(".logged_in")
|
redirect_to root_path, notice: t(".logged_in")
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class TagsController < ApplicationController
|
||||||
|
skip_before_action :require_login, only: [:index, :show]
|
||||||
|
before_action :set_tag, only: [:show]
|
||||||
|
|
||||||
|
def index
|
||||||
|
@tags = Tag.all
|
||||||
|
.page(params[:page])
|
||||||
|
end
|
||||||
|
|
||||||
|
def show; end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_tag
|
||||||
|
@tag = Tag.find_by(name: params[:id])
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module MicropostsHelper
|
||||||
|
def tag_string(micropost)
|
||||||
|
micropost.tags.map(&:name).join(" ")
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,4 +10,11 @@ class Micropost < ApplicationRecord
|
||||||
|
|
||||||
has_many :microposts_tags
|
has_many :microposts_tags
|
||||||
has_many :tags, through: :microposts_tags
|
has_many :tags, through: :microposts_tags
|
||||||
|
|
||||||
|
def set_tags(*tag_names)
|
||||||
|
tag_names.each do |tag_name|
|
||||||
|
tag = Tag.find_or_create_by(name: tag_name)
|
||||||
|
tags << tag unless tags.include?(tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,4 +4,8 @@ class Tag < ApplicationRecord
|
||||||
validates :name, presence: true
|
validates :name, presence: true
|
||||||
has_many :microposts_tags
|
has_many :microposts_tags
|
||||||
has_many :microposts, through: :microposts_tags
|
has_many :microposts, through: :microposts_tags
|
||||||
|
|
||||||
|
def to_param
|
||||||
|
name
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,5 +3,7 @@
|
||||||
|
|
||||||
<%= f.rich_text_area :content %>
|
<%= f.rich_text_area :content %>
|
||||||
|
|
||||||
|
<%= text_field_tag :tags, tag_string(@micropost) %>
|
||||||
|
|
||||||
<%= f.submit button_text %>
|
<%= f.submit button_text %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
<div class="micropost">
|
<div class="micropost">
|
||||||
<%= micropost.content %>
|
<%= micropost.content %>
|
||||||
|
<% unless micropost.tags.empty? %>
|
||||||
|
<h5>Tags:</h5>
|
||||||
|
<ul id="micropost-<%= micropost.id %>-tags" class="micropost-tags">
|
||||||
|
<% micropost.tags.each do |tag| %>
|
||||||
|
<li><%= link_to tag.name, tag %></li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
<% end %>
|
||||||
<div class="created_at">
|
<div class="created_at">
|
||||||
<%= link_to "Edit", edit_micropost_path(micropost) if micropost.user == current_user %>
|
<%= link_to "Edit", edit_micropost_path(micropost) if micropost.user == current_user %>
|
||||||
<%= link_to micropost.created_at.strftime("%Y-%m-%d %H:%M"), micropost %>
|
<%= link_to micropost.created_at.strftime("%Y-%m-%d %H:%M"), micropost %>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<h2><%= t(".tags") %></h2>
|
||||||
|
|
||||||
|
<% if @tags.empty? %>
|
||||||
|
<p><%= t(".empty") %></p>
|
||||||
|
<% else %>
|
||||||
|
<ul id="tags">
|
||||||
|
<% @tags.each do |tag| %>
|
||||||
|
<li><%= link_to tag.name, tag %></li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
<%= paginate @tags %>
|
||||||
|
<% end %>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h2><%= @tag.name %></h2>
|
||||||
|
|
||||||
|
<%= render @tag.microposts %>
|
|
@ -52,7 +52,3 @@ builder:
|
||||||
remote:
|
remote:
|
||||||
arch: arm64
|
arch: arm64
|
||||||
host: ssh://kamal@tsvallender.co.uk
|
host: ssh://kamal@tsvallender.co.uk
|
||||||
|
|
||||||
healthcheck:
|
|
||||||
path: /sessions/new
|
|
||||||
port: 3000
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ Rails.application.configure do
|
||||||
config.log_tags = [ :request_id ]
|
config.log_tags = [ :request_id ]
|
||||||
|
|
||||||
# Use a different cache store in production.
|
# Use a different cache store in production.
|
||||||
# config.cache_store = :mem_cache_store
|
config.cache_store = :solid_cache_store
|
||||||
|
|
||||||
# Use a real queuing backend for Active Job (and separate queues per environment).
|
# Use a real queuing backend for Active Job (and separate queues per environment).
|
||||||
# config.active_job.queue_adapter = :resque
|
# config.active_job.queue_adapter = :resque
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
en:
|
||||||
|
tags:
|
||||||
|
index:
|
||||||
|
tags: Tags
|
||||||
|
empty: You don’t have any tags yet
|
||||||
|
|
|
@ -14,4 +14,7 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
resources :blog_posts
|
resources :blog_posts
|
||||||
resources :microposts
|
resources :microposts
|
||||||
|
resources :tags, only: [:index, :show]
|
||||||
|
|
||||||
|
get "up" => "rails/health#show", as: :rails_health_check
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# This migration comes from solid_cache (originally 20230724121448)
|
||||||
|
class CreateSolidCacheEntries < ActiveRecord::Migration[7.0]
|
||||||
|
def change
|
||||||
|
create_table :solid_cache_entries do |t|
|
||||||
|
t.binary :key, null: false, limit: 1024
|
||||||
|
t.binary :value, null: false, limit: 512.megabytes
|
||||||
|
t.datetime :created_at, null: false
|
||||||
|
|
||||||
|
t.index :key, unique: true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.1].define(version: 2023_10_19_172703) do
|
ActiveRecord::Schema[7.1].define(version: 2023_10_19_192600) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
|
||||||
|
@ -77,6 +77,13 @@ ActiveRecord::Schema[7.1].define(version: 2023_10_19_172703) do
|
||||||
t.index ["tag_id", "micropost_id"], name: "index_microposts_tags_on_tag_id_and_micropost_id"
|
t.index ["tag_id", "micropost_id"], name: "index_microposts_tags_on_tag_id_and_micropost_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "solid_cache_entries", force: :cascade do |t|
|
||||||
|
t.binary "key", null: false
|
||||||
|
t.binary "value", null: false
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.index ["key"], name: "index_solid_cache_entries_on_key", unique: true
|
||||||
|
end
|
||||||
|
|
||||||
create_table "tags", force: :cascade do |t|
|
create_table "tags", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class TagMicropostsTest < ActionDispatch::IntegrationTest
|
||||||
|
test "tags can be added to microposts" do
|
||||||
|
@user = users(:trevor)
|
||||||
|
sign_in(@user)
|
||||||
|
get new_micropost_path
|
||||||
|
assert_response :success
|
||||||
|
post microposts_path, params: {
|
||||||
|
micropost: {
|
||||||
|
content: "An interesting post",
|
||||||
|
},
|
||||||
|
tags: "foo bar baz",
|
||||||
|
}
|
||||||
|
assert_response :redirect
|
||||||
|
follow_redirect!
|
||||||
|
assert_includes response.body, "foo"
|
||||||
|
assert_includes response.body, "bar"
|
||||||
|
assert_includes response.body, "baz"
|
||||||
|
end
|
||||||
|
end
|
|
@ -17,4 +17,21 @@ class MicropostTest < ActiveSupport::TestCase
|
||||||
@micropost.content = nil
|
@micropost.content = nil
|
||||||
assert_not @micropost.valid?
|
assert_not @micropost.valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "can add tags" do
|
||||||
|
assert_empty @micropost.tags
|
||||||
|
assert_difference "@micropost.tags.count", +3 do
|
||||||
|
@micropost.set_tags("foo", "bar", "baz")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "duplicate tags are not added" do
|
||||||
|
assert_empty @micropost.tags
|
||||||
|
assert_difference "@micropost.tags.count", +3 do
|
||||||
|
@micropost.set_tags("foo", "bar", "baz")
|
||||||
|
end
|
||||||
|
assert_no_difference "@micropost.tags.count" do
|
||||||
|
@micropost.set_tags("bar", "baz")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue