chore: remove rails app
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||
|
||||
ruby '2.6.3'
|
||||
|
||||
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
||||
gem 'rails', '~> 5.2.6'
|
||||
# Use postgresql as the database for Active Record
|
||||
gem 'pg', '>= 0.18', '< 2.0'
|
||||
# Use Puma as the app server
|
||||
gem 'puma', '~> 4.3.8'
|
||||
# Use Uglifier as compressor for JavaScript assets
|
||||
gem 'uglifier', '>= 1.3.0'
|
||||
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
|
||||
gem 'webpacker'
|
||||
# See https://github.com/rails/execjs#readme for more supported runtimes
|
||||
# gem 'mini_racer', platforms: :ruby
|
||||
|
||||
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
|
||||
gem 'turbolinks', '~> 5'
|
||||
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
|
||||
gem 'jbuilder', '~> 2.5'
|
||||
# Use Redis adapter to run Action Cable in production
|
||||
# gem 'redis', '~> 4.0'
|
||||
# Use ActiveModel has_secure_password
|
||||
gem 'bcrypt', '~> 3.1.7'
|
||||
|
||||
# Use ActiveStorage variant
|
||||
# gem 'mini_magick', '~> 4.8'
|
||||
|
||||
# Use Capistrano for deployment
|
||||
# gem 'capistrano-rails', group: :development
|
||||
|
||||
# Reduces boot times through caching; required in config/boot.rb
|
||||
gem 'bootsnap', '>= 1.1.0', require: false
|
||||
|
||||
group :development, :test do
|
||||
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
|
||||
gem 'byebug', platforms: %i[mri mingw x64_mingw]
|
||||
end
|
||||
|
||||
group :development do
|
||||
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
|
||||
gem 'listen', '>= 3.0.5', '< 3.2'
|
||||
gem 'web-console', '>= 3.3.0'
|
||||
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
|
||||
gem 'spring'
|
||||
gem 'spring-watcher-listen', '~> 2.0.0'
|
||||
# A Ruby static code analyzer and formatter, based on the community Ruby style guide.
|
||||
gem 'rubocop', '~> 1.17'
|
||||
# A RuboCop extension focused on enforcing Rails best practices and coding conventions.
|
||||
gem 'rubocop-rails'
|
||||
end
|
||||
|
||||
group :test do
|
||||
# Adds support for Capybara system testing and selenium driver
|
||||
gem 'capybara', '>= 2.15'
|
||||
gem 'selenium-webdriver'
|
||||
# Easy installation and use of chromedriver to run system tests with Chrome
|
||||
gem 'webdrivers'
|
||||
# SimpleCov is a code coverage analysis tool for Ruby
|
||||
gem 'simplecov'
|
||||
|
||||
# Simple console output formatter for SimpleCov
|
||||
gem 'simplecov-console'
|
||||
end
|
||||
-269
@@ -1,269 +0,0 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailer (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
actionview (= 5.2.6)
|
||||
activejob (= 5.2.6)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.2.6)
|
||||
actionview (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
rack (~> 2.0, >= 2.0.8)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
activejob (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
activerecord (5.2.6)
|
||||
activemodel (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
arel (>= 9.0)
|
||||
activestorage (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
activerecord (= 5.2.6)
|
||||
marcel (~> 1.0.0)
|
||||
activesupport (5.2.6)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
ansi (1.5.0)
|
||||
arel (9.0.0)
|
||||
ast (2.4.2)
|
||||
bcrypt (3.1.16)
|
||||
bcrypt (3.1.16-java)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.7.5)
|
||||
msgpack (~> 1.0)
|
||||
builder (3.2.4)
|
||||
byebug (11.1.3)
|
||||
capybara (3.35.3)
|
||||
addressable
|
||||
mini_mime (>= 0.1.3)
|
||||
nokogiri (~> 1.8)
|
||||
rack (>= 1.6.0)
|
||||
rack-test (>= 0.6.3)
|
||||
regexp_parser (>= 1.5, < 3.0)
|
||||
xpath (~> 3.2)
|
||||
childprocess (3.0.0)
|
||||
concurrent-ruby (1.1.9)
|
||||
crass (1.0.6)
|
||||
docile (1.4.0)
|
||||
erubi (1.10.0)
|
||||
execjs (2.8.1)
|
||||
ffi (1.15.1)
|
||||
ffi (1.15.1-java)
|
||||
ffi (1.15.1-x64-mingw32)
|
||||
ffi (1.15.1-x86-mingw32)
|
||||
globalid (0.4.2)
|
||||
activesupport (>= 4.2.0)
|
||||
i18n (1.8.10)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jbuilder (2.11.2)
|
||||
activesupport (>= 5.0.0)
|
||||
listen (3.1.5)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
ruby_dep (~> 1.2)
|
||||
loofah (2.10.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
marcel (1.0.1)
|
||||
method_source (1.0.0)
|
||||
mini_mime (1.1.0)
|
||||
mini_portile2 (2.5.3)
|
||||
minitest (5.14.4)
|
||||
msgpack (1.4.2)
|
||||
msgpack (1.4.2-java)
|
||||
nio4r (2.5.7)
|
||||
nio4r (2.5.7-java)
|
||||
nokogiri (1.11.7)
|
||||
mini_portile2 (~> 2.5.0)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.11.7-java)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.11.7-x64-mingw32)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.11.7-x86-mingw32)
|
||||
racc (~> 1.4)
|
||||
parallel (1.20.1)
|
||||
parser (3.0.1.1)
|
||||
ast (~> 2.4.1)
|
||||
pg (1.2.3)
|
||||
pg (1.2.3-x64-mingw32)
|
||||
pg (1.2.3-x86-mingw32)
|
||||
public_suffix (4.0.6)
|
||||
puma (4.3.8)
|
||||
nio4r (~> 2.0)
|
||||
puma (4.3.8-java)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.5.2)
|
||||
racc (1.5.2-java)
|
||||
rack (2.2.3)
|
||||
rack-proxy (0.7.0)
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rails (5.2.6)
|
||||
actioncable (= 5.2.6)
|
||||
actionmailer (= 5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
actionview (= 5.2.6)
|
||||
activejob (= 5.2.6)
|
||||
activemodel (= 5.2.6)
|
||||
activerecord (= 5.2.6)
|
||||
activestorage (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 5.2.6)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.3.0)
|
||||
loofah (~> 2.3)
|
||||
railties (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.19.0, < 2.0)
|
||||
rainbow (3.0.0)
|
||||
rake (13.0.3)
|
||||
rb-fsevent (0.11.0)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
regexp_parser (2.1.1)
|
||||
rexml (3.2.5)
|
||||
rubocop (1.17.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.0.0.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml
|
||||
rubocop-ast (>= 1.7.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 3.0)
|
||||
rubocop-ast (1.7.0)
|
||||
parser (>= 3.0.1.1)
|
||||
rubocop-rails (2.10.1)
|
||||
activesupport (>= 4.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.7.0, < 2.0)
|
||||
ruby-progressbar (1.11.0)
|
||||
ruby_dep (1.5.0)
|
||||
rubyzip (2.3.0)
|
||||
selenium-webdriver (3.142.7)
|
||||
childprocess (>= 0.5, < 4.0)
|
||||
rubyzip (>= 1.2.2)
|
||||
semantic_range (3.0.0)
|
||||
simplecov (0.21.2)
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-console (0.9.1)
|
||||
ansi
|
||||
simplecov
|
||||
terminal-table
|
||||
simplecov-html (0.12.3)
|
||||
simplecov_json_formatter (0.1.3)
|
||||
spring (2.1.1)
|
||||
spring-watcher-listen (2.0.1)
|
||||
listen (>= 2.7, < 4.0)
|
||||
spring (>= 1.2, < 3.0)
|
||||
sprockets (3.7.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.2.2)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
terminal-table (3.0.1)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
thor (1.1.0)
|
||||
thread_safe (0.3.6)
|
||||
thread_safe (0.3.6-java)
|
||||
turbolinks (5.2.1)
|
||||
turbolinks-source (~> 5.2)
|
||||
turbolinks-source (5.2.0)
|
||||
tzinfo (1.2.9)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (4.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unicode-display_width (2.0.0)
|
||||
web-console (3.7.0)
|
||||
actionview (>= 5.0)
|
||||
activemodel (>= 5.0)
|
||||
bindex (>= 0.4.0)
|
||||
railties (>= 5.0)
|
||||
webdrivers (4.6.0)
|
||||
nokogiri (~> 1.6)
|
||||
rubyzip (>= 1.3.0)
|
||||
selenium-webdriver (>= 3.0, < 4.0)
|
||||
webpacker (5.4.0)
|
||||
activesupport (>= 5.2)
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
websocket-driver (0.7.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-driver (0.7.5-java)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
|
||||
PLATFORMS
|
||||
java
|
||||
ruby
|
||||
x64-mingw32
|
||||
x86-mingw32
|
||||
x86-mswin32
|
||||
|
||||
DEPENDENCIES
|
||||
bcrypt (~> 3.1.7)
|
||||
bootsnap (>= 1.1.0)
|
||||
byebug
|
||||
capybara (>= 2.15)
|
||||
jbuilder (~> 2.5)
|
||||
listen (>= 3.0.5, < 3.2)
|
||||
pg (>= 0.18, < 2.0)
|
||||
puma (~> 4.3.8)
|
||||
rails (~> 5.2.6)
|
||||
rubocop (~> 1.17)
|
||||
rubocop-rails
|
||||
selenium-webdriver
|
||||
simplecov
|
||||
simplecov-console
|
||||
spring
|
||||
spring-watcher-listen (~> 2.0.0)
|
||||
turbolinks (~> 5)
|
||||
uglifier (>= 1.3.0)
|
||||
web-console (>= 3.3.0)
|
||||
webdrivers
|
||||
webpacker
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.6.3p62
|
||||
|
||||
BUNDLED WITH
|
||||
2.1.4 2.1.4
|
||||
@@ -1,49 +0,0 @@
|
||||
# URL shortener
|
||||
|
||||
<img width="1200" alt="image" src="https://user-images.githubusercontent.com/27580836/227800665-4ff7e2ae-8189-4593-8961-496b7c9ac861.png">
|
||||
|
||||
# Features
|
||||
- [x] Create link model (make sure to create a index for the slug and click counter)
|
||||
- [x] Generate unique slug
|
||||
- [x] Link unit tests
|
||||
- [x] Stimulus setup
|
||||
- [x] Link controller (handle redirection)
|
||||
- [x] Main page with input box
|
||||
- [x] Create user model
|
||||
- [x] User unit tests
|
||||
- [x] Add userId key to link model
|
||||
- [x] Login and logout (sessions)
|
||||
- [x] User links view
|
||||
- [x] Modals layout
|
||||
- [x] Deployment CI
|
||||
|
||||
# How to run
|
||||
|
||||
## Development
|
||||
- Run migrations
|
||||
```bash
|
||||
docker-compose up -d db
|
||||
docker-compose run --rm app bundle exec rails db:migrate
|
||||
```
|
||||
- Run
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
docker-compose run --rm app bundle exec rails test
|
||||
```
|
||||
|
||||
## Rubocop
|
||||
```bash
|
||||
docker-compose run --rm app bundle exec rubocop
|
||||
```
|
||||
|
||||
## Dokku deployment
|
||||
```bash
|
||||
bundle exec rails db:migrate
|
||||
```
|
||||
|
||||
## Production link
|
||||
https://url-shortener.sjdonado.de
|
||||
@@ -1,8 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
||||
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
||||
|
||||
require_relative 'config/application'
|
||||
|
||||
Rails.application.load_tasks
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
def authenticate
|
||||
@current_user = User.find_by(id: session[:user_id])
|
||||
end
|
||||
end
|
||||
@@ -1,49 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class LinksController < ApplicationController
|
||||
include LinksHelper
|
||||
|
||||
before_action :authenticate, only: %i[create]
|
||||
before_action :set_link, only: %i[redirect counter]
|
||||
|
||||
def redirect
|
||||
if @link
|
||||
@link.increment!(:click_counter) # rubocop:disable Rails/SkipsModelValidations
|
||||
redirect_to @link.parsed_url
|
||||
else
|
||||
render file: Rails.root.join('/public/404'), status: :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def counter
|
||||
if @link
|
||||
render json: @link.click_counter
|
||||
else
|
||||
render json: nil, status: :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
url = stripped_url(link_params[:url])
|
||||
|
||||
@link = Link.find_or_create_by(url: url) do |link|
|
||||
link.user = @current_user if @current_user
|
||||
end
|
||||
|
||||
if @link.errors.any?
|
||||
render json: @link.errors, status: :unprocessable_entity
|
||||
else
|
||||
render partial: 'links/show', locals: { link: @link }, status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_link
|
||||
@link = Link.find_by(slug: params[:slug])
|
||||
end
|
||||
|
||||
def link_params
|
||||
params.require(:link).permit(:url)
|
||||
end
|
||||
end
|
||||
@@ -1,31 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SessionsController < ApplicationController
|
||||
before_action :authenticate, except: %i[create]
|
||||
before_action :set_user, only: %i[create]
|
||||
|
||||
def create
|
||||
if @user&.authenticate(session_params[:password])
|
||||
session[:user_id] = @user.id
|
||||
session[:username] = @user.username
|
||||
render json: nil, status: :ok
|
||||
else
|
||||
render json: { username: ['Credentials not valid, try again or create an account'] }, status: :unauthorized
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
reset_session
|
||||
render json: nil, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_user
|
||||
@user = User.find_by(username: session_params[:username])
|
||||
end
|
||||
|
||||
def session_params
|
||||
params.permit(:username, :password)
|
||||
end
|
||||
end
|
||||
@@ -1,30 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class UsersController < ApplicationController
|
||||
around_action :confirm_password_validation, only: %i[create]
|
||||
|
||||
def create
|
||||
@user = User.create(user_params)
|
||||
if @user.errors.any?
|
||||
render json: @user.errors, status: :unprocessable_entity
|
||||
else
|
||||
session[:user_id] = @user.id
|
||||
session[:username] = @user.username
|
||||
render json: nil, status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def confirm_password_validation
|
||||
if user_params[:password] == params[:user][:confirm_password]
|
||||
yield
|
||||
else
|
||||
render json: { password: ['Password not match with Confirm Password'] }, status: :bad_request
|
||||
end
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:username, :password)
|
||||
end
|
||||
end
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module LinksHelper
|
||||
def stripped_url(url)
|
||||
url.sub(%r{^.*://(www\.)?}, '').sub(/^www\./, '')
|
||||
end
|
||||
end
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SessionsHelper
|
||||
def current_user_username
|
||||
session[:username]
|
||||
end
|
||||
end
|
||||
@@ -1,10 +0,0 @@
|
||||
// Load all the controllers within this directory and all subdirectories.
|
||||
// Controller files must be named *_controller.js.
|
||||
|
||||
import { Application } from "stimulus"
|
||||
import { definitionsFromContext } from "stimulus/webpack-helpers"
|
||||
|
||||
const application = Application.start()
|
||||
|
||||
const context = require.context("controllers", true, /_controller\.js$/)
|
||||
application.load(definitionsFromContext(context))
|
||||
@@ -1,60 +0,0 @@
|
||||
import { Controller } from "stimulus"
|
||||
import Turbolinks from "turbolinks"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["url", "output", "userLinks"]
|
||||
|
||||
initialize() {
|
||||
this.lastLink = null
|
||||
this.sessionUsername = localStorage.getItem("session-username")
|
||||
}
|
||||
|
||||
onCreateLinkSuccess(event) {
|
||||
const [, , xhr] = event.detail
|
||||
|
||||
this.outputTarget.innerHTML = xhr.response
|
||||
|
||||
if (this.sessionUsername && this.lastLink && this.lastLink.includes(this.sessionUsername)
|
||||
&& !this.userLinksTarget.innerHTML.includes(this.lastLink)) {
|
||||
this.userLinksTarget.innerHTML = this.lastLink + this.userLinksTarget.innerHTML
|
||||
}
|
||||
|
||||
this.lastLink = xhr.response
|
||||
}
|
||||
|
||||
onCreateLinkError(event) {
|
||||
const [data, ,] = event.detail
|
||||
const urlError = `Url: ${data.url.join(' ')}`
|
||||
alert(urlError)
|
||||
}
|
||||
|
||||
async updateLinkCounter(counterElem, slug) {
|
||||
const clickCounter = await fetch(`links/${slug}/counter`, {
|
||||
headers: {
|
||||
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
}
|
||||
}).then((res) => res.json());
|
||||
|
||||
if (clickCounter) {
|
||||
counterElem.innerText = clickCounter
|
||||
}
|
||||
}
|
||||
|
||||
openLink(event) {
|
||||
const counterElem = event.target.parentElement.parentElement.parentElement.getElementsByClassName("counter")[0]
|
||||
const link = event.target.innerText
|
||||
|
||||
let visibilitychange = 0
|
||||
const visibilitychangeListener = () => {
|
||||
if(visibilitychange > 0) {
|
||||
document.removeEventListener("visibilitychange", visibilitychangeListener)
|
||||
this.updateLinkCounter(counterElem, link.substring(link.lastIndexOf('/') + 1))
|
||||
return
|
||||
}
|
||||
visibilitychange += 1
|
||||
}
|
||||
document.addEventListener("visibilitychange", visibilitychangeListener)
|
||||
|
||||
window.open(link, "_blank")
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
import { Controller } from "stimulus"
|
||||
import Turbolinks from "turbolinks"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["signupModal", "loginModal"]
|
||||
|
||||
openLoginModal() {
|
||||
this.loginModalTarget.classList.remove("hidden")
|
||||
}
|
||||
|
||||
closeLoginModal() {
|
||||
this.loginModalTarget.classList.add("hidden")
|
||||
}
|
||||
|
||||
openSignupModal() {
|
||||
this.closeLoginModal()
|
||||
this.signupModalTarget.classList.remove("hidden")
|
||||
}
|
||||
|
||||
closeSignupModal() {
|
||||
this.signupModalTarget.classList.add("hidden")
|
||||
}
|
||||
|
||||
onSignupSuccess() {
|
||||
this.closeSignupModal();
|
||||
Turbolinks.visit('/')
|
||||
}
|
||||
|
||||
onLoginSuccess() {
|
||||
this.closeLoginModal();
|
||||
Turbolinks.visit('/')
|
||||
}
|
||||
|
||||
onError(event) {
|
||||
const [data, ,] = event.detail
|
||||
|
||||
const errors = []
|
||||
|
||||
if (data.username) {
|
||||
errors.push(`Username: ${data.username.join(' ')}`)
|
||||
}
|
||||
|
||||
if (data.password) {
|
||||
errors.push(`Password: ${data.password.join(' ')}`)
|
||||
}
|
||||
|
||||
alert(errors.join(','))
|
||||
}
|
||||
|
||||
confirmLogout(event) {
|
||||
if (!window.confirm("Do you really want to leave?")) {
|
||||
event.stopPropagation()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
onSuccessLogout() {
|
||||
localStorage.removeItem("session-username")
|
||||
Turbolinks.visit('/')
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "tailwindcss/utilities";
|
||||
|
||||
@import "../stylesheets/base.css";
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint no-console:0 */
|
||||
// This file is automatically compiled by Webpack, along with any other files
|
||||
// present in this directory. You're encouraged to place your actual application logic in
|
||||
// a relevant structure within app/javascript and only use these pack files to reference
|
||||
// that code so it'll be compiled.
|
||||
//
|
||||
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
|
||||
// layout file, like app/views/layouts/application.html.erb
|
||||
|
||||
|
||||
// Uncomment to copy all static images under ../images to the output folder and reference
|
||||
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
|
||||
// or the `imagePath` JavaScript helper below.
|
||||
//
|
||||
// const images = require.context('../images', true)
|
||||
// const imagePath = (name) => images(name, true)
|
||||
|
||||
require("@rails/ujs").start()
|
||||
require("turbolinks").start()
|
||||
|
||||
import "controllers"
|
||||
|
||||
import "./application.css"
|
||||
@@ -1,3 +0,0 @@
|
||||
a, button, input[type=submit] {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ApplicationRecord < ActiveRecord::Base
|
||||
self.abstract_class = true
|
||||
end
|
||||
@@ -1,34 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Link < ApplicationRecord
|
||||
validates :url, presence: true
|
||||
validates :slug, uniqueness: true
|
||||
|
||||
validates :url,
|
||||
format: {
|
||||
with: %r{\A(?:https?://)?(?:\w+\.)?(?:google\.com|sjdonado\.de)(?:/[\w-]+)*/?\z},
|
||||
message: 'domains allowed for demo purposes: [google.com, sjdonado.de]'
|
||||
}
|
||||
validates :url, length: { within: 3..30_000, on: :create, message: 'max length is 30000' }
|
||||
|
||||
before_validation :generate_slug
|
||||
|
||||
def parsed_url
|
||||
"https://#{url}"
|
||||
end
|
||||
|
||||
def generate_slug(attempts = 0)
|
||||
return if slug.present? || attempts == 3
|
||||
|
||||
# Number of combinations 62P6
|
||||
generated_slug = SecureRandom.alphanumeric(6)
|
||||
|
||||
if Link.exists?(slug: generated_slug)
|
||||
generate_slug(attempts + 1)
|
||||
else
|
||||
self.slug = generated_slug
|
||||
end
|
||||
end
|
||||
|
||||
belongs_to :user, optional: true
|
||||
end
|
||||
@@ -1,8 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class User < ApplicationRecord
|
||||
validates :username, uniqueness: true
|
||||
has_secure_password
|
||||
|
||||
has_many :links, dependent: :nullify
|
||||
end
|
||||
@@ -1,10 +0,0 @@
|
||||
<div data-users-target="<%= target %>" class="fixed z-10 inset-0 overflow-y-auto hidden" aria-labelledby="modal-title" role="dialog" aria-modal="true">
|
||||
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
|
||||
|
||||
<!-- This element is to trick the browser into centering the modal contents. -->
|
||||
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
|
||||
|
||||
<%= yield %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,33 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>URL Shortener</title>
|
||||
<meta name="description" content="Tailwind + Stimulus + Rails 5 app">
|
||||
<meta name="keywords" content="url-shortener, shortener, url">
|
||||
|
||||
<meta property="og:title" content="URL Shortener">
|
||||
<meta property="og:type" content="website">
|
||||
|
||||
<meta property="og:url" content="https://url-shortener.sjdonado.de">
|
||||
<meta property="og:site_name" content="URL Shortener">
|
||||
<meta property="og:description" content="Tailwind + Stimulus + Rails 5 app">
|
||||
|
||||
<meta property="og:image" content="https://user-images.githubusercontent.com/27580836/227800665-4ff7e2ae-8189-4593-8961-496b7c9ac861.png">
|
||||
<meta property="og:image:alt" content="URL Shortener screenshot">
|
||||
|
||||
<%= csrf_meta_tags %>
|
||||
<%= csp_meta_tag %>
|
||||
|
||||
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
|
||||
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<%= yield %>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +0,0 @@
|
||||
<%= form_with model: Link.new, url: links_path(@link), data: { action: 'ajax:success->links#onCreateLinkSuccess ajax:error->links#onCreateLinkError' } do |f| %>
|
||||
<div class="col-span-3 sm:col-span-2">
|
||||
<label for="company_website" class="text-lg leading-6 font-medium text-gray-900">
|
||||
URL Shortener
|
||||
</label>
|
||||
<div class="mt-4 flex rounded-md shadow-sm">
|
||||
<%= f.text_field :url, pattern: '(https?:\/\/)?(www\.)?([a-zA-Z0-9_-]+\.)+[a-zA-Z]{2,}(\.[a-zA-Z]{2,})?([\/?#][^\s]*)?', data: { target: "links.url" }, placeholder: "https://google.com", class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="py-3 text-right">
|
||||
<%= f.submit "Shorten", class: "inline-flex w-full sm:w-auto justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -1,8 +0,0 @@
|
||||
<% unless @current_user.nil? %>
|
||||
<h2 class="text-2xl leading-6 font-medium text-gray-900 mx-4 my-6">My links</h2>
|
||||
<div data-links-target="userLinks">
|
||||
<% @current_user.links.order(created_at: :desc).each do |link| %>
|
||||
<%= render partial: "links/show", locals: { link: link } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -1,4 +0,0 @@
|
||||
<div class="bg-white shadow overflow-hidden sm:rounded-lg m-3 p-6">
|
||||
<%= render partial: "links/form" %>
|
||||
</div>
|
||||
<div data-links-target="output" class="my-6"></div>
|
||||
@@ -1,38 +0,0 @@
|
||||
<div class="bg-white shadow overflow-hidden sm:rounded-lg m-3">
|
||||
<div class="border-t border-gray-200">
|
||||
<dl>
|
||||
<div class="bg-gray-50 px-4 py-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium text-gray-500">
|
||||
Website
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<a href="<%= link.parsed_url %>" class="mt-1 text-sm text-gray-600 underline" target="_blank" rel="noreferrer"><%= link.url %></a>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="bg-white px-4 py-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium text-gray-500">
|
||||
Shortened URL
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<button data-action="click->links#openLink" class="mt-1 text-sm text-gray-600 underline"><%= short_url(slug: link.slug) %></button>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium text-gray-500">
|
||||
Click counter
|
||||
</dt>
|
||||
<dd class="counter mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<%= link.click_counter %>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="bg-white px-4 py-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium text-gray-500">
|
||||
Created by
|
||||
</dt>
|
||||
<dd class="counter mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<%= link.user ? link.user.username : 'Guest user' %>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,34 +0,0 @@
|
||||
<%= form_with url: '/login', data: { action: 'ajax:success->users#onLoginSuccess ajax:error->users#onError' }, class: "inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" do |f| %>
|
||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div class="flex-1 mt-3 text-center sm:mt-0 sm:mx-4 sm:text-left">
|
||||
<h3 class="text-xl leading-6 font-medium text-gray-900">
|
||||
Login
|
||||
</h3>
|
||||
<div class="flex-col mt-4">
|
||||
<div class="my-2">
|
||||
<label for="username" class="block text-sm font-medium text-gray-700 text-left">
|
||||
Username
|
||||
</label>
|
||||
<%= f.text_field :username, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
<div class="my-2">
|
||||
<label for="password" class="block text-sm font-medium text-gray-700 text-left">
|
||||
Password
|
||||
</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<%= f.password_field :password, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" data-action="click->users#openSignupModal" class="block w-full text-sm font-medium sm:pl-4 pt-6 underline text-center sm:text-left">Create an account</button>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<%= f.submit "Login", class: "my-1 mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" %>
|
||||
<button data-action="click->users#closeLoginModal" type="button" class="my-1 sm:mt-0 w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<%end%>
|
||||
@@ -1,21 +0,0 @@
|
||||
<div data-controller="users">
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<% if @current_user.nil? %>
|
||||
<button data-action="click->users#openLoginModal" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
Login
|
||||
</button>
|
||||
<% end %>
|
||||
<%= render partial: "users/show" %>
|
||||
</div>
|
||||
<%= render partial: "users/new", layout: "layouts/modal", locals: { target: 'signupModal' } %>
|
||||
<%= render partial: "sessions/new", layout: "layouts/modal", locals: { target: 'loginModal' } %>
|
||||
</div>
|
||||
|
||||
<div data-controller="links">
|
||||
<%= render partial: "links/new" %>
|
||||
<%= render partial: "links/index" %>
|
||||
</div>
|
||||
|
||||
<% unless @current_user.nil? %>
|
||||
<script>localStorage.setItem("session-username", "<%= current_user_username %>");</script>
|
||||
<% end %>
|
||||
@@ -1,39 +0,0 @@
|
||||
<%= form_with model: User.new, url: users_path(@user), data: { action: 'ajax:success->users#onSignupSuccess ajax:error->users#onError' }, class: "inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" do |f| %>
|
||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div class="flex-1 mt-3 text-center sm:mt-0 sm:mx-4 sm:text-left">
|
||||
<h3 class="text-xl leading-6 font-medium text-gray-900">
|
||||
Sign Up
|
||||
</h3>
|
||||
<div class="flex-col mt-4">
|
||||
<div class="my-2">
|
||||
<label for="username" class="block text-sm font-medium text-gray-700 text-left">
|
||||
Username
|
||||
</label>
|
||||
<%= f.text_field :username, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
<div class="my-2">
|
||||
<label for="password" class="block text-sm font-medium text-gray-700 text-left">
|
||||
Password
|
||||
</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<%= f.password_field :password, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-2">
|
||||
<label for="confirm_password" class="block text-sm font-medium text-gray-700 text-left">
|
||||
Confirm password
|
||||
</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<%= f.password_field :confirm_password, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<%= f.submit "Sign Up", class: "my-1 mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" %>
|
||||
<button data-action="click->users#closeSignupModal" type="button" class="my-1 sm:mt-0 w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<%end%>
|
||||
@@ -1,4 +0,0 @@
|
||||
<% unless @current_user.nil? %>
|
||||
<%= link_to "Logout", '/session/logout', data: { action: 'ajax:before->users#confirmLogout ajax:success->users#onSuccessLogout' }, remote: true, class: "mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" %>
|
||||
<h1 class="px-2 py-2 text-sm font-medium">You are Logged In, <%= @current_user.username %></h1>
|
||||
<%end%>
|
||||
@@ -1,70 +0,0 @@
|
||||
module.exports = function(api) {
|
||||
var validEnv = ['development', 'test', 'production']
|
||||
var currentEnv = api.env()
|
||||
var isDevelopmentEnv = api.env('development')
|
||||
var isProductionEnv = api.env('production')
|
||||
var isTestEnv = api.env('test')
|
||||
|
||||
if (!validEnv.includes(currentEnv)) {
|
||||
throw new Error(
|
||||
'Please specify a valid `NODE_ENV` or ' +
|
||||
'`BABEL_ENV` environment variables. Valid values are "development", ' +
|
||||
'"test", and "production". Instead, received: ' +
|
||||
JSON.stringify(currentEnv) +
|
||||
'.'
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
presets: [
|
||||
isTestEnv && [
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: {
|
||||
node: 'current'
|
||||
}
|
||||
}
|
||||
],
|
||||
(isProductionEnv || isDevelopmentEnv) && [
|
||||
'@babel/preset-env',
|
||||
{
|
||||
forceAllTransforms: true,
|
||||
useBuiltIns: 'entry',
|
||||
corejs: 3,
|
||||
modules: false,
|
||||
exclude: ['transform-typeof-symbol']
|
||||
}
|
||||
]
|
||||
].filter(Boolean),
|
||||
plugins: [
|
||||
'babel-plugin-macros',
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
isTestEnv && 'babel-plugin-dynamic-import-node',
|
||||
'@babel/plugin-transform-destructuring',
|
||||
[
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
{
|
||||
loose: false
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
{
|
||||
useBuiltIns: true
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/plugin-transform-runtime',
|
||||
{
|
||||
helpers: false
|
||||
}
|
||||
],
|
||||
[
|
||||
'@babel/plugin-transform-regenerator',
|
||||
{
|
||||
async: false
|
||||
}
|
||||
]
|
||||
].filter(Boolean)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
||||
load Gem.bin_path('bundler', 'bundle')
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
APP_PATH = File.expand_path('../config/application', __dir__)
|
||||
require_relative '../config/boot'
|
||||
require 'rails/commands'
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../config/boot'
|
||||
require 'rake'
|
||||
Rake.application.run
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'fileutils'
|
||||
include FileUtils
|
||||
|
||||
# path to your application root.
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
|
||||
def system!(*args)
|
||||
system(*args) || abort("\n== Command #{args} failed ==")
|
||||
end
|
||||
|
||||
chdir APP_ROOT do
|
||||
# This script is a starting point to setup your application.
|
||||
# Add necessary setup steps to this file.
|
||||
|
||||
puts '== Installing dependencies =='
|
||||
system! 'gem install bundler --conservative'
|
||||
system('bundle check') || system!('bundle install')
|
||||
|
||||
# Install JavaScript dependencies if using Yarn
|
||||
# system('bin/yarn')
|
||||
|
||||
# puts "\n== Copying sample files =="
|
||||
# unless File.exist?('config/database.yml')
|
||||
# cp 'config/database.yml.sample', 'config/database.yml'
|
||||
# end
|
||||
|
||||
puts "\n== Preparing database =="
|
||||
system! 'bin/rails db:setup'
|
||||
|
||||
puts "\n== Removing old logs and tempfiles =="
|
||||
system! 'bin/rails log:clear tmp:clear'
|
||||
|
||||
puts "\n== Restarting application server =="
|
||||
system! 'bin/rails restart'
|
||||
end
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'fileutils'
|
||||
include FileUtils
|
||||
|
||||
# path to your application root.
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
|
||||
def system!(*args)
|
||||
system(*args) || abort("\n== Command #{args} failed ==")
|
||||
end
|
||||
|
||||
chdir APP_ROOT do
|
||||
# This script is a way to update your development environment automatically.
|
||||
# Add necessary update steps to this file.
|
||||
|
||||
puts '== Installing dependencies =='
|
||||
system! 'gem install bundler --conservative'
|
||||
system('bundle check') || system!('bundle install')
|
||||
|
||||
# Install JavaScript dependencies if using Yarn
|
||||
# system('bin/yarn')
|
||||
|
||||
puts "\n== Updating database =="
|
||||
system! 'bin/rails db:migrate'
|
||||
|
||||
puts "\n== Removing old logs and tempfiles =="
|
||||
system! 'bin/rails log:clear tmp:clear'
|
||||
|
||||
puts "\n== Restarting application server =="
|
||||
system! 'bin/rails restart'
|
||||
end
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development'
|
||||
ENV['NODE_ENV'] ||= 'development'
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'bundler/setup'
|
||||
|
||||
require 'webpacker'
|
||||
require 'webpacker/webpack_runner'
|
||||
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
Dir.chdir(APP_ROOT) do
|
||||
Webpacker::WebpackRunner.run(ARGV)
|
||||
end
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development'
|
||||
ENV['NODE_ENV'] ||= 'development'
|
||||
|
||||
require 'pathname'
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
|
||||
Pathname.new(__FILE__).realpath)
|
||||
|
||||
require 'bundler/setup'
|
||||
|
||||
require 'webpacker'
|
||||
require 'webpacker/dev_server_runner'
|
||||
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
Dir.chdir(APP_ROOT) do
|
||||
Webpacker::DevServerRunner.run(ARGV)
|
||||
end
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
APP_ROOT = File.expand_path('..', __dir__)
|
||||
Dir.chdir(APP_ROOT) do
|
||||
exec 'yarnpkg', *ARGV
|
||||
rescue Errno::ENOENT
|
||||
warn 'Yarn executable was not detected in the system.'
|
||||
warn 'Download Yarn at https://yarnpkg.com/en/docs/install'
|
||||
exit 1
|
||||
end
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# This file is used by Rack-based servers to start the application.
|
||||
|
||||
require_relative 'config/environment'
|
||||
|
||||
run Rails.application
|
||||
@@ -1,21 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'boot'
|
||||
|
||||
require 'rails/all'
|
||||
|
||||
# Require the gems listed in Gemfile, including any gems
|
||||
# you've limited to :test, :development, or :production.
|
||||
Bundler.require(*Rails.groups)
|
||||
|
||||
module App
|
||||
class Application < Rails::Application
|
||||
# Initialize configuration defaults for originally generated Rails version.
|
||||
config.load_defaults 5.2
|
||||
|
||||
# Settings in config/environments/* take precedence over those specified here.
|
||||
# Application configuration can go into files in config/initializers
|
||||
# -- all .rb files in that directory are automatically loaded after loading
|
||||
# the framework and any gems in your application.
|
||||
end
|
||||
end
|
||||
@@ -1,6 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
||||
|
||||
require 'bundler/setup' # Set up gems listed in the Gemfile.
|
||||
require 'bootsnap/setup' # Speed up boot time by caching expensive operations.
|
||||
@@ -1,8 +0,0 @@
|
||||
development:
|
||||
adapter: async
|
||||
|
||||
test:
|
||||
adapter: async
|
||||
|
||||
production:
|
||||
adapter: async
|
||||
@@ -1 +0,0 @@
|
||||
/UPkhc4cuB6geZB3wUkY6YEc2RAEr775PbtKCLNL47TG7qdyd8Cl2rcrgwpGBnqJY2ZTXGqoIV20O5HyejxD6+jiFmuEjXi/scS451d0SoMQDZobH2G2+wSfPCIoz5uW5E9ZRE+HUEIa8Ja2fQ4rUK/TFa90RLt5x67SKWBNFoXkbJ4NR+s6/3B6b7LUyoTc8SpWuzxLbXjfXSoUAB6VZNvfN/wX8U5wK+vKb9cZVkd1ltGvAm1QLbrWfAKQTL5uzy/pNJflH9AFEga5d/JMG1NAui7T87NVSh08iYpkJOEpjbqAEwQOE1WRyCCQ6v+nsQSV7sEaMxjMOEItHAi/8gEnbMP5NmXmJ1/7VTgDFZVoolww7T64KyIiFShORxg71z1BqojwdKTjsWQ2XjVlchZIk0CYakMukJC/--daZZ3htNyJPK0uYc--VdreTqiXCOY5i5RJnF0dmg==
|
||||
@@ -1,89 +0,0 @@
|
||||
# PostgreSQL. Versions 9.1 and up are supported.
|
||||
#
|
||||
# Install the pg driver:
|
||||
# gem install pg
|
||||
# On OS X with Homebrew:
|
||||
# gem install pg -- --with-pg-config=/usr/local/bin/pg_config
|
||||
# On OS X with MacPorts:
|
||||
# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
|
||||
# On Windows:
|
||||
# gem install pg
|
||||
# Choose the win32 build.
|
||||
# Install PostgreSQL and put its /bin directory on your path.
|
||||
#
|
||||
# Configure Using Gemfile
|
||||
# gem 'pg'
|
||||
#
|
||||
default: &default
|
||||
adapter: postgresql
|
||||
encoding: unicode
|
||||
# For details on connection pooling, see Rails configuration guide
|
||||
# http://guides.rubyonrails.org/configuring.html#database-pooling
|
||||
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
host: db
|
||||
database: url_shortener
|
||||
username: app_user
|
||||
password: secure_12345
|
||||
|
||||
# The specified database role being used to connect to postgres.
|
||||
# To create additional roles in postgres see `$ createuser --help`.
|
||||
# When left blank, postgres will use the default role. This is
|
||||
# the same name as the operating system user that initialized the database.
|
||||
#username: app
|
||||
|
||||
# The password associated with the postgres role (username).
|
||||
#password:
|
||||
|
||||
# Connect on a TCP socket. Omitted by default since the client uses a
|
||||
# domain socket that doesn't need configuration. Windows does not have
|
||||
# domain sockets, so uncomment these lines.
|
||||
#host: localhost
|
||||
|
||||
# The TCP port the server listens on. Defaults to 5432.
|
||||
# If your server runs on a different port number, change accordingly.
|
||||
#port: 5432
|
||||
|
||||
# Schema search path. The server defaults to $user,public
|
||||
#schema_search_path: myapp,sharedapp,public
|
||||
|
||||
# Minimum log levels, in increasing order:
|
||||
# debug5, debug4, debug3, debug2, debug1,
|
||||
# log, notice, warning, error, fatal, and panic
|
||||
# Defaults to warning.
|
||||
#min_messages: notice
|
||||
|
||||
# Warning: The database defined as "test" will be erased and
|
||||
# re-generated from your development database when you run "rake".
|
||||
# Do not set this db to the same as development or production.
|
||||
test:
|
||||
<<: *default
|
||||
host: db
|
||||
database: test_url_shortener
|
||||
username: app_user
|
||||
password: secure_12345
|
||||
|
||||
# As with config/secrets.yml, you never want to store sensitive information,
|
||||
# like your database password, in your source code. If your source code is
|
||||
# ever seen by anyone, they now have access to your database.
|
||||
#
|
||||
# Instead, provide the password as a unix environment variable when you boot
|
||||
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
|
||||
# for a full rundown on how to provide these environment variables in a
|
||||
# production deployment.
|
||||
#
|
||||
# On Heroku and other platform providers, you may have a full connection URL
|
||||
# available as an environment variable. For example:
|
||||
#
|
||||
# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
|
||||
#
|
||||
# You can use this database configuration with:
|
||||
#
|
||||
# production:
|
||||
# url: <%= ENV['DATABASE_URL'] %>
|
||||
#
|
||||
production:
|
||||
<<: *default
|
||||
url: <%= ENV['DATABASE_URL'] %>
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Load the Rails application.
|
||||
require_relative 'application'
|
||||
|
||||
# Initialize the Rails application.
|
||||
Rails.application.initialize!
|
||||
@@ -1,65 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# In the development environment your application's code is reloaded on
|
||||
# every request. This slows down response time but is perfect for development
|
||||
# since you don't have to restart the web server when you make code changes.
|
||||
config.cache_classes = false
|
||||
|
||||
# Do not eager load code on boot.
|
||||
config.eager_load = false
|
||||
|
||||
# Show full error reports.
|
||||
config.consider_all_requests_local = true
|
||||
|
||||
# Enable/disable caching. By default caching is disabled.
|
||||
# Run rails dev:cache to toggle caching.
|
||||
if Rails.root.join('tmp/caching-dev.txt').exist?
|
||||
config.action_controller.perform_caching = true
|
||||
|
||||
config.cache_store = :memory_store
|
||||
config.public_file_server.headers = {
|
||||
'Cache-Control' => "public, max-age=#{2.days.to_i}"
|
||||
}
|
||||
else
|
||||
config.action_controller.perform_caching = false
|
||||
|
||||
config.cache_store = :null_store
|
||||
end
|
||||
|
||||
# Store uploaded files on the local file system (see config/storage.yml for options)
|
||||
config.active_storage.service = :local
|
||||
|
||||
# Don't care if the mailer can't send.
|
||||
config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# Print deprecation notices to the Rails logger.
|
||||
config.active_support.deprecation = :log
|
||||
|
||||
# Raise an error on page load if there are pending migrations.
|
||||
config.active_record.migration_error = :page_load
|
||||
|
||||
# Highlight code that triggered database queries in logs.
|
||||
config.active_record.verbose_query_logs = true
|
||||
|
||||
# Debug mode disables concatenation and preprocessing of assets.
|
||||
# This option may cause significant delays in view rendering with a large
|
||||
# number of complex assets.
|
||||
config.assets.debug = true
|
||||
|
||||
# Suppress logger output for asset requests.
|
||||
config.assets.quiet = true
|
||||
|
||||
# Raises error for missing translations
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
|
||||
# Use an evented file watcher to asynchronously detect changes in source code,
|
||||
# routes, locales, etc. This feature depends on the listen gem.
|
||||
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
|
||||
|
||||
Rails.application.routes.default_url_options[:host] = "#{ENV['HOSTNAME']}:#{ENV['RAILS_PORT']}"
|
||||
end
|
||||
@@ -1,97 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Code is not reloaded between requests.
|
||||
config.cache_classes = true
|
||||
|
||||
# Eager load code on boot. This eager loads most of Rails and
|
||||
# your application in memory, allowing both threaded web servers
|
||||
# and those relying on copy on write to perform better.
|
||||
# Rake tasks automatically ignore this option for performance.
|
||||
config.eager_load = true
|
||||
|
||||
# Full error reports are disabled and caching is turned on.
|
||||
config.consider_all_requests_local = false
|
||||
config.action_controller.perform_caching = true
|
||||
|
||||
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
|
||||
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
|
||||
config.require_master_key = true
|
||||
|
||||
# Disable serving static files from the `/public` folder by default since
|
||||
# Apache or NGINX already handles this.
|
||||
config.public_file_server.enabled = true
|
||||
|
||||
# Compress JavaScripts and CSS.
|
||||
config.assets.js_compressor = Uglifier.new(harmony: true)
|
||||
# config.assets.css_compressor = :sass
|
||||
|
||||
# Do not fallback to assets pipeline if a precompiled asset is missed.
|
||||
config.assets.compile = true
|
||||
|
||||
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
|
||||
# config.action_controller.asset_host = 'http://assets.example.com'
|
||||
|
||||
# Specifies the header that your server uses for sending files.
|
||||
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
|
||||
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
|
||||
|
||||
# Store uploaded files on the local file system (see config/storage.yml for options)
|
||||
config.active_storage.service = :local
|
||||
|
||||
# Mount Action Cable outside main process or domain
|
||||
# config.action_cable.mount_path = nil
|
||||
# config.action_cable.url = 'wss://example.com/cable'
|
||||
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
|
||||
|
||||
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
||||
# config.force_ssl = true
|
||||
|
||||
# Use the lowest log level to ensure availability of diagnostic information
|
||||
# when problems arise.
|
||||
config.log_level = :debug
|
||||
|
||||
# Prepend all log lines with the following tags.
|
||||
config.log_tags = [:request_id]
|
||||
|
||||
config.cache_store = :memory_store
|
||||
|
||||
# Use a real queuing backend for Active Job (and separate queues per environment)
|
||||
# config.active_job.queue_adapter = :resque
|
||||
# config.active_job.queue_name_prefix = "app_#{Rails.env}"
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# Ignore bad email addresses and do not raise email delivery errors.
|
||||
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||
# config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Send deprecation notices to registered listeners.
|
||||
config.active_support.deprecation = :notify
|
||||
|
||||
# Use default logging formatter so that PID and timestamp are not suppressed.
|
||||
config.log_formatter = ::Logger::Formatter.new
|
||||
|
||||
# Use a different logger for distributed setups.
|
||||
# require 'syslog/logger'
|
||||
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
|
||||
|
||||
if ENV['RAILS_LOG_TO_STDOUT'].present?
|
||||
logger = ActiveSupport::Logger.new($stdout)
|
||||
logger.formatter = config.log_formatter
|
||||
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
||||
end
|
||||
|
||||
# Do not dump schema after migrations.
|
||||
config.active_record.dump_schema_after_migration = false
|
||||
|
||||
Rails.application.routes.default_url_options[:host] = ENV['HOSTNAME']
|
||||
end
|
||||
@@ -1,49 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# The test environment is used exclusively to run your application's
|
||||
# test suite. You never need to work with it otherwise. Remember that
|
||||
# your test database is "scratch space" for the test suite and is wiped
|
||||
# and recreated between test runs. Don't rely on the data there!
|
||||
config.cache_classes = true
|
||||
|
||||
# Do not eager load code on boot. This avoids loading your whole application
|
||||
# just for the purpose of running a single test. If you are using a tool that
|
||||
# preloads Rails for running tests, you may have to set it to true.
|
||||
config.eager_load = false
|
||||
|
||||
# Configure public file server for tests with Cache-Control for performance.
|
||||
config.public_file_server.enabled = true
|
||||
config.public_file_server.headers = {
|
||||
'Cache-Control' => "public, max-age=#{1.hour.to_i}"
|
||||
}
|
||||
|
||||
# Show full error reports and disable caching.
|
||||
config.consider_all_requests_local = true
|
||||
config.action_controller.perform_caching = false
|
||||
|
||||
# Raise exceptions instead of rendering exception templates.
|
||||
config.action_dispatch.show_exceptions = false
|
||||
|
||||
# Disable request forgery protection in test environment.
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
|
||||
# Store uploaded files on the local file system in a temporary directory
|
||||
config.active_storage.service = :test
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
# Tell Action Mailer not to deliver emails to the real world.
|
||||
# The :test delivery method accumulates sent emails in the
|
||||
# ActionMailer::Base.deliveries array.
|
||||
config.action_mailer.delivery_method = :test
|
||||
|
||||
# Print deprecation notices to the stderr.
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
# Raises error for missing translations
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
Rails.application.routes.default_url_options[:host] = "#{ENV['HOSTNAME']}:#{ENV['RAILS_PORT']}"
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# ActiveSupport::Reloader.to_prepare do
|
||||
# ApplicationController.renderer.defaults.merge!(
|
||||
# http_host: 'example.org',
|
||||
# https: false
|
||||
# )
|
||||
# end
|
||||
@@ -1,16 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Version of your assets, change this if you want to expire all your assets.
|
||||
Rails.application.config.assets.version = '1.0'
|
||||
|
||||
# Add additional assets to the asset load path.
|
||||
# Rails.application.config.assets.paths << Emoji.images_path
|
||||
# Add Yarn node_modules folder to the asset load path.
|
||||
Rails.application.config.assets.paths << Rails.root.join('node_modules')
|
||||
|
||||
# Precompile additional assets.
|
||||
# application.js, application.css, and all non-JS/CSS in the app/assets
|
||||
# folder are already added.
|
||||
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
|
||||
@@ -1,8 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
||||
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
||||
|
||||
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
||||
# Rails.backtrace_cleaner.remove_silencers!
|
||||
@@ -1,26 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Define an application-wide content security policy
|
||||
# For further information see the following documentation
|
||||
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
|
||||
|
||||
# Rails.application.config.content_security_policy do |policy|
|
||||
# policy.default_src :self, :https
|
||||
# policy.font_src :self, :https, :data
|
||||
# policy.img_src :self, :https, :data
|
||||
# policy.object_src :none
|
||||
# policy.script_src :self, :https
|
||||
# policy.style_src :self, :https
|
||||
|
||||
# # Specify URI for violation reports
|
||||
# # policy.report_uri "/csp-violation-report-endpoint"
|
||||
# end
|
||||
|
||||
# If you are using UJS then enable automatic nonce generation
|
||||
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
|
||||
|
||||
# Report CSP violations to a specified URI
|
||||
# For further information see the following documentation:
|
||||
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
|
||||
# Rails.application.config.content_security_policy_report_only = true
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Specify a serializer for the signed and encrypted cookie jars.
|
||||
# Valid options are :json, :marshal, and :hybrid.
|
||||
Rails.application.config.action_dispatch.cookies_serializer = :json
|
||||
@@ -1,6 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Configure sensitive parameters which will be filtered from the log file.
|
||||
Rails.application.config.filter_parameters += [:password]
|
||||
@@ -1,17 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Add new inflection rules using the following format. Inflections
|
||||
# are locale specific, and you may define rules for as many different
|
||||
# locales as you wish. All of these examples are active by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.plural /^(ox)$/i, '\1en'
|
||||
# inflect.singular /^(ox)en/i, '\1'
|
||||
# inflect.irregular 'person', 'people'
|
||||
# inflect.uncountable %w( fish sheep )
|
||||
# end
|
||||
|
||||
# These inflection rules are supported but not enabled by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.acronym 'RESTful'
|
||||
# end
|
||||
@@ -1,5 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Add new mime types for use in respond_to blocks:
|
||||
# Mime::Type.register "text/richtext", :rtf
|
||||
@@ -1,16 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# This file contains settings for ActionController::ParamsWrapper which
|
||||
# is enabled by default.
|
||||
|
||||
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
||||
ActiveSupport.on_load(:action_controller) do
|
||||
wrap_parameters format: [:json]
|
||||
end
|
||||
|
||||
# To enable root element in JSON for ActiveRecord objects.
|
||||
# ActiveSupport.on_load(:active_record) do
|
||||
# self.include_root_in_json = true
|
||||
# end
|
||||
@@ -1,33 +0,0 @@
|
||||
# Files in the config/locales directory are used for internationalization
|
||||
# and are automatically loaded by Rails. If you want to use locales other
|
||||
# than English, add the necessary files in this directory.
|
||||
#
|
||||
# To use the locales, use `I18n.t`:
|
||||
#
|
||||
# I18n.t 'hello'
|
||||
#
|
||||
# In views, this is aliased to just `t`:
|
||||
#
|
||||
# <%= t('hello') %>
|
||||
#
|
||||
# To use a different locale, set it with `I18n.locale`:
|
||||
#
|
||||
# I18n.locale = :es
|
||||
#
|
||||
# This would use the information in config/locales/es.yml.
|
||||
#
|
||||
# The following keys must be escaped otherwise they will not be retrieved by
|
||||
# the default I18n backend:
|
||||
#
|
||||
# true, false, on, off, yes, no
|
||||
#
|
||||
# Instead, surround them with single quotes.
|
||||
#
|
||||
# en:
|
||||
# 'true': 'foo'
|
||||
#
|
||||
# To learn more, please read the Rails Internationalization guide
|
||||
# available at http://guides.rubyonrails.org/i18n.html.
|
||||
|
||||
en:
|
||||
hello: "Hello world"
|
||||
@@ -1,39 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Puma can serve each request in a thread from an internal thread pool.
|
||||
# The `threads` method setting takes two numbers: a minimum and maximum.
|
||||
# Any libraries that use thread pools should be configured to match
|
||||
# the maximum value specified for Puma. Default is set to 5 threads for minimum
|
||||
# and maximum; this matches the default thread size of Active Record.
|
||||
#
|
||||
threads_count = ENV.fetch('RAILS_MAX_THREADS', 5)
|
||||
threads threads_count, threads_count
|
||||
|
||||
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
|
||||
#
|
||||
port ENV.fetch('PORT', 3000)
|
||||
|
||||
# Specifies the `environment` that Puma will run in.
|
||||
#
|
||||
environment ENV.fetch('RAILS_ENV', 'development')
|
||||
|
||||
# Specifies the `pidfile` that Puma will use.
|
||||
pidfile ENV.fetch('PIDFILE', 'tmp/pids/server.pid')
|
||||
|
||||
# Specifies the number of `workers` to boot in clustered mode.
|
||||
# Workers are forked webserver processes. If using threads and workers together
|
||||
# the concurrency of the application would be max `threads` * `workers`.
|
||||
# Workers do not work on JRuby or Windows (both of which do not support
|
||||
# processes).
|
||||
#
|
||||
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
|
||||
|
||||
# Use the `preload_app!` method when specifying a `workers` number.
|
||||
# This directive tells Puma to first boot the application and load code
|
||||
# before forking the application. This takes advantage of Copy On Write
|
||||
# process behavior so workers use less memory.
|
||||
#
|
||||
# preload_app!
|
||||
|
||||
# Allow puma to be restarted by `rails restart` command.
|
||||
plugin :tmp_restart
|
||||
@@ -1,14 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.routes.draw do
|
||||
root 'sessions#index'
|
||||
|
||||
get '/:slug', to: 'links#redirect', as: :short
|
||||
get 'links/:slug/counter', to: 'links#counter', as: :counter
|
||||
get 'session/logout', to: 'sessions#destroy', as: :logout
|
||||
|
||||
post 'login', to: 'sessions#create', as: :login
|
||||
|
||||
resources :links, only: %i[create]
|
||||
resources :users, only: %i[create]
|
||||
end
|
||||
@@ -1,8 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
%w[
|
||||
.ruby-version
|
||||
.rbenv-vars
|
||||
tmp/restart.txt
|
||||
tmp/caching-dev.txt
|
||||
].each { |path| Spring.watch(path) }
|
||||
@@ -1,34 +0,0 @@
|
||||
test:
|
||||
service: Disk
|
||||
root: <%= Rails.root.join("tmp/storage") %>
|
||||
|
||||
local:
|
||||
service: Disk
|
||||
root: <%= Rails.root.join("storage") %>
|
||||
|
||||
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
|
||||
# amazon:
|
||||
# service: S3
|
||||
# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
|
||||
# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
|
||||
# region: us-east-1
|
||||
# bucket: your_own_bucket
|
||||
|
||||
# Remember not to checkin your GCS keyfile to a repository
|
||||
# google:
|
||||
# service: GCS
|
||||
# project: your_project
|
||||
# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
|
||||
# bucket: your_own_bucket
|
||||
|
||||
# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
|
||||
# microsoft:
|
||||
# service: AzureStorage
|
||||
# storage_account_name: your_account_name
|
||||
# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
|
||||
# container: your_container_name
|
||||
|
||||
# mirror:
|
||||
# service: Mirror
|
||||
# primary: local
|
||||
# mirrors: [ amazon, google, microsoft ]
|
||||
@@ -1,5 +0,0 @@
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
||||
|
||||
const environment = require('./environment')
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
||||
@@ -1,3 +0,0 @@
|
||||
const { environment } = require('@rails/webpacker')
|
||||
|
||||
module.exports = environment
|
||||
@@ -1,5 +0,0 @@
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'production'
|
||||
|
||||
const environment = require('./environment')
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
||||
@@ -1,5 +0,0 @@
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
|
||||
|
||||
const environment = require('./environment')
|
||||
|
||||
module.exports = environment.toWebpackConfig()
|
||||
@@ -1,92 +0,0 @@
|
||||
# Note: You must restart bin/webpack-dev-server for changes to take effect
|
||||
|
||||
default: &default
|
||||
source_path: app/javascript
|
||||
source_entry_path: packs
|
||||
public_root_path: public
|
||||
public_output_path: packs
|
||||
cache_path: tmp/cache/webpacker
|
||||
webpack_compile_output: true
|
||||
|
||||
# Additional paths webpack should lookup modules
|
||||
# ['app/assets', 'engine/foo/app/assets']
|
||||
additional_paths: []
|
||||
|
||||
# Reload manifest.json on all requests so we reload latest compiled packs
|
||||
cache_manifest: false
|
||||
|
||||
# Extract and emit a css file
|
||||
extract_css: false
|
||||
|
||||
static_assets_extensions:
|
||||
- .jpg
|
||||
- .jpeg
|
||||
- .png
|
||||
- .gif
|
||||
- .tiff
|
||||
- .ico
|
||||
- .svg
|
||||
- .eot
|
||||
- .otf
|
||||
- .ttf
|
||||
- .woff
|
||||
- .woff2
|
||||
|
||||
extensions:
|
||||
- .mjs
|
||||
- .js
|
||||
- .sass
|
||||
- .scss
|
||||
- .css
|
||||
- .module.sass
|
||||
- .module.scss
|
||||
- .module.css
|
||||
- .png
|
||||
- .svg
|
||||
- .gif
|
||||
- .jpeg
|
||||
- .jpg
|
||||
|
||||
development:
|
||||
<<: *default
|
||||
compile: false
|
||||
|
||||
# Reference: https://webpack.js.org/configuration/dev-server/
|
||||
dev_server:
|
||||
https: false
|
||||
host: localhost
|
||||
port: 3035
|
||||
public: localhost:3035
|
||||
hmr: false
|
||||
# Inline should be set to true if using HMR
|
||||
inline: true
|
||||
overlay: true
|
||||
compress: true
|
||||
disable_host_check: true
|
||||
use_local_ip: false
|
||||
quiet: false
|
||||
pretty: false
|
||||
headers:
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
watch_options:
|
||||
ignored: '**/node_modules/**'
|
||||
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
compile: true
|
||||
|
||||
# Compile test packs to a separate directory
|
||||
public_output_path: packs-test
|
||||
|
||||
production:
|
||||
<<: *default
|
||||
|
||||
# Production depends on precompilation of packs prior to booting for performance.
|
||||
compile: true
|
||||
|
||||
# Extract and emit a css file
|
||||
extract_css: true
|
||||
|
||||
# Cache manifest.json for performance
|
||||
cache_manifest: true
|
||||
@@ -1,13 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CreateLinks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :links do |t|
|
||||
t.string :slug, null: false
|
||||
t.text :url
|
||||
t.integer :click_counter, default: 0
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddSlugIndexToLinks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_index :links, :slug
|
||||
end
|
||||
end
|
||||
@@ -1,12 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CreateUsers < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :users do |t|
|
||||
t.string :username
|
||||
t.string :password_digest
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddUserIdToLinks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_reference :links, :user, foreign_key: true
|
||||
end
|
||||
end
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddUsernameIndexToUsers < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_index :users, :username, unique: true
|
||||
end
|
||||
end
|
||||
@@ -1,8 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class UniqueSlugIndex < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
remove_index :links, column: :slug
|
||||
add_index :links, :slug, unique: true
|
||||
end
|
||||
end
|
||||
@@ -1,38 +0,0 @@
|
||||
# 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.
|
||||
#
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2021_06_15_200050) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
create_table "links", force: :cascade do |t|
|
||||
t.string "slug", null: false
|
||||
t.text "url"
|
||||
t.integer "click_counter", default: 0
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.bigint "user_id"
|
||||
t.index ["slug"], name: "index_links_on_slug", unique: true
|
||||
t.index ["user_id"], name: "index_links_on_user_id"
|
||||
end
|
||||
|
||||
create_table "users", force: :cascade do |t|
|
||||
t.string "username"
|
||||
t.string "password_digest"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["username"], name: "index_users_on_username", unique: true
|
||||
end
|
||||
|
||||
add_foreign_key "links", "users"
|
||||
end
|
||||
@@ -1,8 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
# This file should contain all the record creation needed to seed the database with its default values.
|
||||
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
|
||||
# Character.create(name: 'Luke', movie: movies.first)
|
||||
@@ -1,42 +0,0 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
db:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.db
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_USER: app_user
|
||||
POSTGRES_PASSWORD: secure_12345
|
||||
ports:
|
||||
- 5432:5432
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
volumes:
|
||||
- .:/usr/src/app
|
||||
- gem_cache:/usr/local/bundle/gems
|
||||
command: bundle exec rails s -b '0.0.0.0'
|
||||
tty: true
|
||||
environment:
|
||||
RAILS_ENV: development
|
||||
HOSTNAME: 0.0.0.0
|
||||
ports:
|
||||
- 3000:3000
|
||||
depends_on:
|
||||
- db
|
||||
webpack:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
volumes:
|
||||
- .:/usr/src/app
|
||||
- gem_cache:/usr/local/bundle/gems
|
||||
command: bin/webpack --watch --colors --progress
|
||||
tty: true
|
||||
volumes:
|
||||
gem_cache:
|
||||
db_data:
|
||||
@@ -1,5 +0,0 @@
|
||||
CREATE DATABASE url_shortener;
|
||||
CREATE DATABASE test_url_shortener;
|
||||
|
||||
GRANT ALL PRIVILEGES ON DATABASE url_shortener TO app_user;
|
||||
GRANT ALL PRIVILEGES ON DATABASE test_url_shortener TO app_user;
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
bundle check || bundle install --jobs 20 --retry 5
|
||||
|
||||
rm -f $APP_PATH/tmp/pids/server.pid
|
||||
|
||||
${@}
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
rm -f "$APP_PATH/tmp/pids/server.pid"
|
||||
|
||||
"${@}"
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "app",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@rails/ujs": "^6.0.3-7",
|
||||
"@rails/webpacker": "5.4.0",
|
||||
"@tailwindcss/forms": "^0.3.3",
|
||||
"autoprefixer": "^9",
|
||||
"css-loader": "^5.2.6",
|
||||
"css-minimizer-webpack-plugin": "^3.0.1",
|
||||
"mini-css-extract-plugin": "^1.6.0",
|
||||
"postcss": "^8.2.10",
|
||||
"stimulus": "^2.0.0",
|
||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
|
||||
"turbolinks": "^5.2.0",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('postcss-import'),
|
||||
require('tailwindcss'),
|
||||
require('postcss-flexbugs-fixes'),
|
||||
require('postcss-preset-env')({
|
||||
autoprefixer: {
|
||||
flexbox: 'no-2009'
|
||||
},
|
||||
stage: 3
|
||||
})
|
||||
]
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The page you were looking for doesn't exist (404)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
.rails-default-error-page {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #B00100 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
.rails-default-error-page h1 {
|
||||
font-size: 100%;
|
||||
color: #730E15;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="rails-default-error-page">
|
||||
<!-- This file lives in public/404.html -->
|
||||
<div class="dialog">
|
||||
<div>
|
||||
<h1>The page you were looking for doesn't exist.</h1>
|
||||
<p>You may have mistyped the address or the page may have moved.</p>
|
||||
</div>
|
||||
<p>If you are the application owner check the logs for more information.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,67 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The change you wanted was rejected (422)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
.rails-default-error-page {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #B00100 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
.rails-default-error-page h1 {
|
||||
font-size: 100%;
|
||||
color: #730E15;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="rails-default-error-page">
|
||||
<!-- This file lives in public/422.html -->
|
||||
<div class="dialog">
|
||||
<div>
|
||||
<h1>The change you wanted was rejected.</h1>
|
||||
<p>Maybe you tried to change something you didn't have access to.</p>
|
||||
</div>
|
||||
<p>If you are the application owner check the logs for more information.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,66 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>We're sorry, but something went wrong (500)</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<style>
|
||||
.rails-default-error-page {
|
||||
background-color: #EFEFEF;
|
||||
color: #2E2F30;
|
||||
text-align: center;
|
||||
font-family: arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog {
|
||||
width: 95%;
|
||||
max-width: 33em;
|
||||
margin: 4em auto 0;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > div {
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #BBB;
|
||||
border-top: #B00100 solid 4px;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
background-color: white;
|
||||
padding: 7px 12% 0;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
|
||||
.rails-default-error-page h1 {
|
||||
font-size: 100%;
|
||||
color: #730E15;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.rails-default-error-page div.dialog > p {
|
||||
margin: 0 0 1em;
|
||||
padding: 1em;
|
||||
background-color: #F7F7F7;
|
||||
border: 1px solid #CCC;
|
||||
border-right-color: #999;
|
||||
border-left-color: #999;
|
||||
border-bottom-color: #999;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-color: #DADADA;
|
||||
color: #666;
|
||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="rails-default-error-page">
|
||||
<!-- This file lives in public/500.html -->
|
||||
<div class="dialog">
|
||||
<div>
|
||||
<h1>We're sorry, but something went wrong.</h1>
|
||||
</div>
|
||||
<p>If you are the application owner check the logs for more information.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
|
||||
@@ -1,13 +0,0 @@
|
||||
module.exports = {
|
||||
purge: [],
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [
|
||||
require('@tailwindcss/forms'),
|
||||
],
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
|
||||
driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
|
||||
end
|
||||
@@ -1,63 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class LinksControllerTest < ActionDispatch::IntegrationTest
|
||||
test 'Should get index page' do
|
||||
get '/'
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test 'Should return 404 for unavailable slug' do
|
||||
get '/test'
|
||||
assert_response :not_found
|
||||
end
|
||||
|
||||
test 'Should create a link' do
|
||||
url = 'https://test.sjdonado.de'
|
||||
post links_url, params: { link: { url: url } }
|
||||
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test 'Should create a link with user' do
|
||||
user = users(:one)
|
||||
post login_url, params: { username: user.username, password: '12345' }
|
||||
|
||||
assert_response :success
|
||||
|
||||
url = 'https://test.sjdonado.de'
|
||||
post links_url, params: { link: { url: url } }
|
||||
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test 'Should return 422 on create an invalid link' do
|
||||
url = 'test'
|
||||
post links_url, params: { link: { url: url } }
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
end
|
||||
|
||||
test 'Should redirect from slug to url' do
|
||||
link = links(:one)
|
||||
slug = link.slug
|
||||
|
||||
get short_url(slug: slug)
|
||||
|
||||
assert_redirected_to link.parsed_url
|
||||
end
|
||||
|
||||
test 'Should get link counter' do
|
||||
link = links(:one)
|
||||
get counter_url(slug: link.slug)
|
||||
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test 'Should return 404 on get counter with an invalid slug' do
|
||||
get counter_url(slug: 'test')
|
||||
|
||||
assert_response :not_found
|
||||
end
|
||||
end
|
||||
@@ -1,34 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class SessionsControllerTest < ActionDispatch::IntegrationTest
|
||||
test 'Should create an user session' do
|
||||
user = users(:one)
|
||||
params = { username: user.username, password: '12345' }
|
||||
post login_url, params: params
|
||||
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test 'Should return 401 with not available user' do
|
||||
params = { username: nil, password: 'test' }
|
||||
post login_url, params: params
|
||||
|
||||
assert_response :unauthorized
|
||||
end
|
||||
|
||||
test 'Should return 401 with wrong credentials' do
|
||||
user = users(:one)
|
||||
params = { username: user.username, password: 'test' }
|
||||
post login_url, params: params
|
||||
|
||||
assert_response :unauthorized
|
||||
end
|
||||
|
||||
test 'Should destroy session' do
|
||||
get logout_url
|
||||
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
@@ -1,28 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class UsersControllerTest < ActionDispatch::IntegrationTest
|
||||
test 'Should create an user' do
|
||||
params = { user: { username: 'testing', password: 'testing', confirm_password: 'testing' } }
|
||||
post users_url, params: params
|
||||
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test 'Should return 400 on create an user without confirm_password' do
|
||||
user = users(:one)
|
||||
params = { user: { username: user.username, password: 'testing' } }
|
||||
post users_url, params: params
|
||||
|
||||
assert_response :bad_request
|
||||
end
|
||||
|
||||
test 'Should return 422 on create an user with existing username' do
|
||||
user = users(:one)
|
||||
params = { user: { username: user.username, password: 'testing', confirm_password: 'testing' } }
|
||||
post users_url, params: params
|
||||
|
||||
assert_response :unprocessable_entity
|
||||
end
|
||||
end
|
||||
Vendored
-16
@@ -1,16 +0,0 @@
|
||||
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
one:
|
||||
slug: ktr4ms
|
||||
url: 'https://google.com'
|
||||
click_counter: 1
|
||||
|
||||
two:
|
||||
slug: qwu62l
|
||||
url: 'https://www.google.com'
|
||||
click_counter: 1
|
||||
|
||||
three:
|
||||
slug: rwi43l
|
||||
url: 'google.com'
|
||||
click_counter: 1
|
||||
Vendored
-9
@@ -1,9 +0,0 @@
|
||||
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
one:
|
||||
username: sjdonado
|
||||
password_digest: <%= BCrypt::Password.create('12345') %>
|
||||
|
||||
two:
|
||||
username: other_user
|
||||
password_digest: <%= BCrypt::Password.create('67891') %>
|
||||
@@ -1,47 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
require 'minitest/mock'
|
||||
|
||||
class LinkTest < ActiveSupport::TestCase
|
||||
test 'Should not save a link without a url' do
|
||||
link = Link.new
|
||||
assert_not link.save, 'Saved the link without a url'
|
||||
end
|
||||
|
||||
test 'Should not save a link with a invalid url - number' do
|
||||
link = Link.new
|
||||
link.url = 0
|
||||
assert_not link.save, 'Saved the link with invalid url format'
|
||||
end
|
||||
|
||||
test 'Should not save a link with a invalid url - string' do
|
||||
link = Link.new
|
||||
link.url = 'test'
|
||||
assert_not link.save, 'Saved the link with invalid url format'
|
||||
end
|
||||
|
||||
test 'Should generate a slug on save a new link - format https://google.com' do
|
||||
link = links(:one)
|
||||
assert link.save, 'Slug generated on save a new link'
|
||||
end
|
||||
|
||||
test 'Should generate a slug on save a new link - format http://www.google.com' do
|
||||
link = links(:two)
|
||||
assert link.save, 'Slug generated on save a new link'
|
||||
end
|
||||
|
||||
test 'Should generate a slug on save a new link - format google.com' do
|
||||
link = links(:three)
|
||||
assert link.save, 'Slug generated on save a new link'
|
||||
end
|
||||
|
||||
test 'Should generate an unique slug' do
|
||||
SecureRandom.stub :alphanumeric, 'ktr4ms' do
|
||||
link = Link.new
|
||||
link.url = 'https://test.sjdonado.de'
|
||||
link.generate_slug
|
||||
assert_raise(ActiveRecord::NotNullViolation) { link.save }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,23 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class UserTest < ActiveSupport::TestCase
|
||||
test 'Should create an user' do
|
||||
user = User.new
|
||||
user.username = 'testing'
|
||||
user.password = 'testing'
|
||||
|
||||
assert user.save, 'User not created'
|
||||
end
|
||||
|
||||
test 'Should not create a user if username is already taken' do
|
||||
test_user = users(:one)
|
||||
|
||||
user = User.new
|
||||
user.username = test_user.username
|
||||
user.password = 'testing'
|
||||
|
||||
assert_not user.save, 'User created with duplicate username'
|
||||
end
|
||||
end
|
||||
@@ -1,35 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
ENV['RAILS_ENV'] ||= 'test'
|
||||
require_relative '../config/environment'
|
||||
require 'rails/test_help'
|
||||
|
||||
if ENV['RAILS_ENV'] == 'test'
|
||||
require 'simplecov'
|
||||
SimpleCov.start 'rails' do
|
||||
add_filter '/app/channels'
|
||||
add_filter '/app/mailers'
|
||||
add_filter '/app/jobs'
|
||||
|
||||
enable_coverage :branch
|
||||
end
|
||||
|
||||
simplecov_formatters = [
|
||||
SimpleCov::Formatter::HTMLFormatter,
|
||||
SimpleCov::Formatter::Console
|
||||
]
|
||||
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(simplecov_formatters)
|
||||
|
||||
SimpleCov::Formatter::Console.show_covered = true
|
||||
|
||||
puts 'required simplecov'
|
||||
end
|
||||
|
||||
module ActiveSupport
|
||||
class TestCase
|
||||
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
|
||||
fixtures :all
|
||||
|
||||
# Add more helper methods to be used by all tests here...
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user