Compare commits

..

19 commits

Author SHA1 Message Date
James f478010699 Update .gitignore 2025-06-25 22:42:56 -05:00
James 77bdebd0b1 Update README.md 2024-11-07 17:46:21 -06:00
James a9f4b05b16 Update README.md 2024-11-04 23:25:40 -06:00
James 2024a8367b link to latest bulma 1.x 2024-11-02 23:08:12 -05:00
James 0cd5093976 Update .gitignore 2024-11-02 22:36:20 -05:00
James 4f3d003a35 Update views/users.erb 2024-11-01 17:03:48 -05:00
James 9f00a34f7d Update views/layout.erb 2024-11-01 17:01:38 -05:00
James 15e6c8dff8 Update views/index.erb 2024-11-01 17:00:55 -05:00
James 3d679586d8 Update views/greeting.erb 2024-11-01 16:59:26 -05:00
James 10bcb49b56 Update README.md 2024-11-01 15:50:21 -05:00
James 57462f98fc Update README.md 2024-11-01 15:43:52 -05:00
James c05c3d3a89 Update views/layout.erb for bulma 1.0.2 2024-11-01 15:10:17 -05:00
James 5a91e0d0dd Expanded setup instructions in Readme. 2024-11-01 14:52:56 -05:00
James 14f1f3daa6 Added new views that use the database 2023-12-28 22:39:02 -06:00
James bffbab8fbc Added sequel with example setup 2023-12-28 18:36:49 -06:00
James 1a3a4287b0 Getting ready to use database 2023-12-28 00:13:50 -06:00
James 971c5f2233 Update readme.md 2023-12-27 19:09:35 -06:00
James 2151565e9c Split up config.ru and added views 2023-12-27 18:19:21 -06:00
James e5ffa9e318 Update README.md 2023-12-27 00:01:23 -06:00
14 changed files with 226 additions and 19 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
/.rake_tasks~
/temp.db
/vendor/
/bin/

12
Gemfile
View file

@ -1,4 +1,16 @@
source 'https://rubygems.org'
gem 'roda'
gem 'rack-unreloader'
gem 'tilt'
gem 'erubi'
gem 'sequel'
gem 'rake'
# Change to whatever database you plan to use
gem 'sqlite3'
# gem 'pg' # will also want gem sequel-pg
# gem 'mysql2'
# change to gunicorn or passenger if you prefer:
gem 'puma'

View file

@ -2,8 +2,29 @@
For the single file app template, really the only file you need is the config.ru and run it with puma.
## Database
## Views
In this template, I've taken the single-file template and split up the config.ru to put routes and app logic in app.rb and call on templates to render proper html pages. `tilt` and `erubi` gems are added to do the rendering, and `rack-unreloader` gem is added to have puma automatically load file changes while running in development mode.
My example html layout uses [Bulma](https://bulma.io/) to make it easier to make modern looking webpages.
Next Roda app template iterations will add database, then authentication.
## Setup
### Get git
```
sudo apt install git
git config --global user.email "myemail@gmail.com"
git config --global user.name "Full Name"
git config --global credential.helper "cache"
git clone https://path/to/project.git
```
### Prereq installs
Will need ruby; install it via package manager or a ruby manager like rbenv/ruby-build. Will need the roda gem, and then an application server such as puma (recommended), gunicorn, or passenger. My examples will use system ruby and puma.
@ -13,31 +34,64 @@ Will need ruby; install it via package manager or a ruby manager like rbenv/ruby
With this example, will basically just ignore the project's Gemfile. Debian 12 has a pretty current ruby version so just using it.
```
sudo apt install ruby ruby-rack puma
sudo gem install roda
sudo apt install ruby ruby-rack puma ruby-erubi ruby-tilt ruby-sequel ruby-sqlite3 rake
sudo gem install roda rack-unreloader
cd my-project
```
#### Option 2: Bundler
#### Option 2a: Bundler system package
Run the bundle command from the project's root directory
Run the bundle install command from the project's root directory
```
sudo apt install ruby ruby-bundler
bundle config set --local path 'vendor/bundle'
sudo apt install ruby ruby-bundler ruby-dev gcc pkgconf make g++ libyaml-dev libffi-dev
echo 'gem: --no-document' >> ~/.gemrc
sudo cp ~/.gemrc /root/
bundle config set --global path 'vendor/bundle'
sudo cp -r .bundle /root/
cd my-project
bundle install
```
#### Option 2b: Bundler system gem (recommended)
Similar to above but might as well use the gem install to get the latest bundler. The Debian apt packaged bundler is currently a bit outdated and missing some features compared to the latest.
```
sudo apt install ruby ruby-dev gcc pkgconf make g++ libyaml-dev # zlib1g-dev libffi-dev #(for rails stuff)
echo 'gem: --no-document' >> ~/.gemrc
sudo cp ~/.gemrc /root/
sudo gem install bundler
bundle config set --global path 'vendor/bundle'
sudo cp -r .bundle /root/
cd my-project
bundle install
```
#### Option 3: Rbenv Ruby
Todo
## Run it
In the project root directory:
```
bundle exec puma
# or if you did not use bundler to install puma...
puma
```
This default to development mode. Run it in production mode with:
```
RACK_ENV=production bundle exec puma
# or if you did not install puma
RACK_ENV=production puma
```
@ -45,4 +99,20 @@ For development, just run it like that. For production, probably want to set up
### Run it with systemd in production
Copy the example myapp.service file to `/etc/systemd/system/` and edit accordingly. The example assumes a user named "myapp" with a group name "myapp", the application files are in `/opt/myapp/`, and puma is the system puma.
Copy the example myapp.service file to `/etc/systemd/system/` and edit accordingly. The example assumes a user named "myapp" with a group name "myapp", the application files are in `/opt/myapp/`, and puma is the system puma. If you installed puma with bundler, the exe will be at `/opt/myapp/vendor/bundle/ruby/3.1.0/bin/puma`.
### Notes
## Unreloader
This has puma reload with any file changes while you are working on the app, when in development mode. When puma is in production mode, it loads the app on startup like normal with no performance penalty. It's very useful during development and no reason to not leave it in.
<https://github.com/jeremyevans/rack-unreloader>.
Basically, you require the app from the config.ru, and then within you app files, any "require_relative" will be "Unreloader.require" instead, plus you do need to include the file extension.
In config.ru, the `dev =` line stores true or false depending on the RACK_ENV environment variable (see above for changing from default development). Then the `:reload=>dev` uses the dev variable to tell Unreload to reload files or not. Lastly the `run` command uses the dev variable to choose between running Unreloader, or bypass Unreloader and run App like normal in production.
## Additional credit
I took a lot of inspirations from Jeremy Evans [roda-sequel-stack](https://github.com/jeremyevans/roda-sequel-stack). Jeremy Evans is the author of Roda and also Unreloader, Sequel, and a ruby core contributor, among other things.

33
Rakefile Normal file
View file

@ -0,0 +1,33 @@
namespace :db do
migrator = lambda do |version|
require_relative 'db'
Sequel.extension :migration
Sequel::Migrator.apply(DB, 'migrate', version)
end
namespace :migrate do
desc "Perform migration up to latest migration available"
task :up do
migrator.call(nil)
end
desc "Perform migration all the way down (erase all data)"
task :down do
migrator.call(0)
end
end
desc "Erase all data, then bring back to latest migration"
task :reset do
migrator.call(0)
Sequel::Migrator.apply(DB, 'migrate')
end
#desc "Migrate to a specific version"
#task :migrate do |version|
#end
end

31
app.rb Normal file
View file

@ -0,0 +1,31 @@
# frozen_string_literal: true
require 'roda'
require 'tilt'
require 'tilt/erubi'
class App < Roda
plugin :render, escape: true
plugin :route_csrf
route do |r|
check_csrf!
r.root do
view :index
end
r.is 'users' do
@users = User.order(:id)
view :users
end
r.on 'hello' do
r.is String do |name|
@page_title = 'A Custom Greeting'
@name = name.capitalize
view :greeting
end
end
end
end

View file

@ -1,15 +1,10 @@
require 'roda'
class App < Roda
route do |r|
r.root do
"<h1>Hello, World!</h1>"
end
dev = ENV['RACK_ENV'] == 'development'
r.is String do |name|
"<h1>Hello, #{name.capitalize}!</h1>"
end
end
end
require 'rack/unreloader'
run App
Unreloader = Rack::Unreloader.new(:subclasses=>%w'Roda Sequel::Model', reload: dev, autoload: dev){App}
Unreloader.require './models.rb'
Unreloader.require './app.rb'
run(dev ? Unreloader : App)

4
db.rb Normal file
View file

@ -0,0 +1,4 @@
# frozen_string_literal: true
require 'sequel/core'
DB = Sequel.connect('sqlite://temp.db')

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
Sequel.migration do
change do
create_table(:users) do
primary_key :id
String :name, unique: true, null: false
end
end
end

14
models.rb Normal file
View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
require_relative 'db'
require 'sequel/model'
if ENV['RACK_ENV'] == 'development'
Sequel::Model.cache_associations = false
end
unless defined?(Unreloader)
require 'rack/unreloader'
Unreloader = Rack::Unreloader.new(reload: false, autoload: !ENV['NO_AUTOLOAD'])
end
Unreloader.autoload('models'){|f| Sequel::Model.send(:camelize, File.basename(f).sub(/\.rb\z/, ''))}

3
models/user.rb Normal file
View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
class User < Sequel::Model
end

3
views/greeting.erb Normal file
View file

@ -0,0 +1,3 @@
<p class="subtitle">
Hello, <%= @name %>!
</p>

3
views/index.erb Normal file
View file

@ -0,0 +1,3 @@
<p class="subtitle">
Welcome to my new page! Running in <%= ENV['RACK_ENV'] %> mode!
</p>

19
views/layout.erb Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><%= @page_title || "My Website" %></title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1/css/bulma.min.css">
</head>
<body>
<section class="section">
<div class="container">
<h1 class="title">
<%= @page_title || 'Page Title Placeholder' %>
</h1>
<%== yield %>
</div>
</section>
</body>
</html>

5
views/users.erb Normal file
View file

@ -0,0 +1,5 @@
<% for u in @users do %>
<p class="subtitle">
Hello, <%= u.name %>! You're #<%= u.id %>!
</p>
<% end %>