natra 0.0.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +17 -0
  3. data/.github/workflows/ci.yml +50 -0
  4. data/.gitignore +2 -0
  5. data/.rubocop.yml +26 -0
  6. data/.ruby-version +1 -0
  7. data/CHANGELOG.md +58 -0
  8. data/CODE_OF_CONDUCT.md +0 -0
  9. data/Gemfile +12 -6
  10. data/Gemfile.lock +157 -116
  11. data/Guardfile +7 -5
  12. data/LICENSE.txt +0 -0
  13. data/README.md +138 -32
  14. data/Rakefile +4 -2
  15. data/bin/console +2 -0
  16. data/bin/natra +5 -3
  17. data/lib/extensions/string.rb +15 -11
  18. data/lib/natra/cli.rb +7 -2
  19. data/lib/natra/generators/app/app_generator.rb +32 -19
  20. data/lib/natra/generators/app/templates/Dockerfile +28 -10
  21. data/lib/natra/generators/app/templates/Gemfile +26 -20
  22. data/lib/natra/generators/app/templates/Guardfile +2 -0
  23. data/lib/natra/generators/app/templates/README.md +29 -30
  24. data/lib/natra/generators/app/templates/Rakefile +3 -2
  25. data/lib/natra/generators/app/templates/app/controllers/application_controller.rb +2 -0
  26. data/lib/natra/generators/app/templates/app/views/welcome.erb +2 -1
  27. data/lib/natra/generators/app/templates/bin/setup +4 -4
  28. data/lib/natra/generators/app/templates/config/database.yml +6 -6
  29. data/lib/natra/generators/app/templates/config/environment.rb +4 -5
  30. data/lib/natra/generators/app/templates/config/initializers/oj.rb +5 -4
  31. data/lib/natra/generators/app/templates/config/initializers/redis.rb +5 -3
  32. data/lib/natra/generators/app/templates/config/puma.rb +11 -5
  33. data/lib/natra/generators/app/templates/config.ru +2 -0
  34. data/lib/natra/generators/app/templates/db/migrate/add_extensions.rb +3 -1
  35. data/lib/natra/generators/app/templates/docker-compose.yml +3 -5
  36. data/lib/natra/generators/app/templates/rubocop.yml +8 -11
  37. data/lib/natra/generators/app/templates/spec/application_controller_spec.rb +2 -0
  38. data/lib/natra/generators/app/templates/spec/spec_helper.rb +10 -9
  39. data/lib/natra/generators/controller/controller_generator.rb +4 -0
  40. data/lib/natra/generators/model/migration.rb.erb +1 -1
  41. data/lib/natra/generators/model/model_generator.rb +8 -2
  42. data/lib/natra/generators/scaffold/scaffold_generator.rb +3 -0
  43. data/lib/natra/generators/service/service_generator.rb +31 -0
  44. data/lib/natra/generators/service/template/service.rb.erb +11 -0
  45. data/lib/natra/version.rb +3 -1
  46. data/lib/natra.rb +4 -0
  47. data/natra.gemspec +14 -11
  48. metadata +35 -39
  49. data/.coveralls.yml +0 -2
  50. data/.travis.yml +0 -3
data/README.md CHANGED
@@ -1,61 +1,167 @@
1
1
  # Natra
2
- [![Coverage Status](https://coveralls.io/repos/github/thirunjuguna/natra/badge.svg?branch=master)](https://coveralls.io/github/thirunjuguna/natra?branch=master)
3
- [![Build Status](https://travis-ci.com/thirunjuguna/natra.svg?branch=master)](https://travis-ci.com/thirunjuguna/natra)
4
- [![Maintainability](https://api.codeclimate.com/v1/badges/e76bbd27a1c4cb8911ae/maintainability)](https://codeclimate.com/github/thirunjuguna/natra/maintainability)
5
- [![Codacy Badge](https://api.codacy.com/project/badge/Grade/450f5da9d33d4adca897563ec759c1b2)](https://www.codacy.com/app/thirunjuguna/natra?utm_source=github.com&utm_medium=referral&utm_content=thirunjuguna/natra&utm_campaign=Badge_Grade)
2
+
3
+ [![CI](https://github.com/jamesnjuguna0419/natra/actions/workflows/ci.yml/badge.svg)](https://github.com/jamesnjuguna0419/natra/actions/workflows/ci.yml)
4
+ [![Gem Version](https://img.shields.io/gem/v/natra.svg)](https://rubygems.org/gems/natra)
5
+ [![Downloads](https://img.shields.io/gem/dt/natra.svg)](https://rubygems.org/gems/natra)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.txt)
7
+
8
+ Natra is a command line generator for small Sinatra services. `natra new` creates a JSON API skeleton with ActiveRecord, PostgreSQL, Puma, RSpec, RuboCop and a Docker setup. Inside that app, `natra model`, `natra controller`, `natra scaffold` and `natra service_object` add models with migrations, controllers with views, and plain Ruby service objects.
9
+
10
+ ## Requirements
11
+
12
+ - Ruby 3.3 or newer to run natra and the apps it generates.
13
+ - PostgreSQL for the generated app's database.
14
+ - Docker with Compose v2, only if you want the generated Docker setup. `natra new` runs `docker compose build --pull` as its last step. Without Docker that step prints an error, but the app is still generated and you can run it locally.
6
15
 
7
16
  ## Installation
8
17
 
9
- Add this line to your application's Gemfile:
18
+ ```sh
19
+ gem install natra
20
+ ```
21
+
22
+ ## Quick start
23
+
24
+ ```sh
25
+ natra new my-api
26
+ cd my-api
27
+ ```
28
+
29
+ ### Run with Docker
30
+
31
+ `secrets.env` holds the database settings for the `web` and `db` containers.
10
32
 
11
- ```ruby
12
- gem 'natra'
33
+ ```sh
34
+ docker compose run --rm web bin/setup
35
+ docker compose up
13
36
  ```
14
37
 
15
- And then execute:
38
+ ### Run locally
16
39
 
17
- $ bundle
40
+ Start PostgreSQL first. Without `DATABASE_URL`, `config/database.yml` uses the databases `development_my_api` and `test_my_api` (override them with `DEV_DATABASE` and `TEST_DATABASE`).
18
41
 
19
- Or install it yourself as:
42
+ ```sh
43
+ bundle install
44
+ bundle exec rake db:create db:migrate
45
+ bundle exec puma -C config/puma.rb
46
+ ```
20
47
 
21
- $ gem install natra
48
+ Either way the app listens on http://localhost:9292. Run its specs with `bundle exec rspec` after `RACK_ENV=test bundle exec rake db:create db:migrate`.
22
49
 
23
50
  ## Commands
51
+
52
+ | Command | What it does | Options |
53
+ | --- | --- | --- |
54
+ | `natra new APP_PATH` | Creates a new Sinatra application in `APP_PATH` | `--git` runs `git init` and `git add .`<br>`--bundle` runs `bundle install`<br>`--redis` adds the redis gem, `config/redis.yml` and a Redis initializer<br>`--capistrano` runs `cap install`<br>`--rvm` writes `.ruby-version` (the Ruby running natra) and `.ruby-gemset`, and skips `--bundle` |
55
+ | `natra model NAME [field:type ...]` | Generates a model and a migration that creates its table | `--no-migration` skips the migration |
56
+ | `natra controller NAME` | Generates a controller with routes, mounts it in `config.ru` and adds its views | `--no-views` skips the views |
57
+ | `natra scaffold NAME [field:type ...]` | Runs `model` and `controller` for `NAME` | |
58
+ | `natra service_object NAME` | Generates a service object in `app/services` | |
59
+ | `natra -v`, `natra --version` | Prints the natra version | |
60
+ | `natra help [COMMAND]` | Lists the commands, or describes one | |
61
+
62
+ Run `model`, `controller`, `scaffold` and `service_object` from the root of a generated app.
63
+
64
+ Naming rules:
65
+
66
+ - `APP_PATH` is lowercased, and characters other than letters, `-` and `_` are dropped. `natra new My-Blog` creates `my-blog`.
67
+ - Fields are written `name:type`, for example `title:string body:text published:boolean`. The type defaults to `string`, so `title` is the same as `title:string`.
68
+ - Models are singular (a plural name is singularized with a warning). Controllers and service objects are pluralized: `natra controller post` creates `PostsController`, and `natra service_object payment` creates `PaymentsService`.
69
+
70
+ ## What you get
71
+
72
+ `natra new blog` creates:
73
+
24
74
  ```
25
- natra -v # Show Natra version number
26
- natra help [COMMAND] # Describe available commands or one specific command
27
- natra new APP-NAME # Creates a new Sinatra application
28
- natra model NAME # Generate a model
29
- natra controller NAME # Generate a controller
30
- natra scaffold NAME # Generate a model with its associated views and controllers
75
+ blog/
76
+ ├── .gitignore
77
+ ├── .rspec
78
+ ├── .rubocop.yml
79
+ ├── Dockerfile
80
+ ├── Gemfile
81
+ ├── Guardfile
82
+ ├── README.md
83
+ ├── Rakefile
84
+ ├── config.ru
85
+ ├── docker-compose.yml
86
+ ├── secrets.env
87
+ ├── app/
88
+ │ ├── controllers/application_controller.rb
89
+ │ ├── models/
90
+ │ ├── services/
91
+ │ └── views/
92
+ │ ├── layout.erb
93
+ │ └── welcome.erb
94
+ ├── bin/setup
95
+ ├── config/
96
+ │ ├── database.yml
97
+ │ ├── environment.rb
98
+ │ ├── puma.rb
99
+ │ └── initializers/oj.rb
100
+ ├── db/
101
+ │ ├── migrate/YYYYMMDD0000_add_extensions.rb
102
+ │ └── seeds.rb
103
+ ├── lib/
104
+ ├── public/favicon.ico
105
+ └── spec/
106
+ ├── application_controller_spec.rb
107
+ ├── spec_helper.rb
108
+ └── support/
31
109
  ```
32
- The controller generator also have an optional views flag `--no-views` to create controllers without views.
33
110
 
34
- ## Using Natra
111
+ The Gemfile uses Sinatra 4, ActiveRecord 8.1 through sinatra-activerecord, pg, Puma, Oj, rack-timeout and Scout APM, with RSpec, Capybara, FactoryBot, Faker, DatabaseCleaner, SimpleCov and Guard for tests. The first migration enables the `hstore`, `uuid-ossp` and `pgcrypto` PostgreSQL extensions. The Rakefile loads the sinatra-activerecord tasks, such as `db:create`, `db:migrate`, `db:seed` and `db:create_migration`.
35
112
 
36
- To generate your app:
113
+ `natra scaffold post title:string body:text` then creates:
37
114
 
38
- natra new APP-NAME
39
-
40
- After natra is done generating your app, run `bundle install` from your app's directory:
115
+ ```
116
+ app/models/post.rb # class Post < ActiveRecord::Base
117
+ db/migrate/YYYYMMDDHHMMSS_create_posts.rb # posts table with a UUID id, title, body and timestamps
118
+ app/controllers/posts_controller.rb # index, new, create, show, edit, update and delete routes
119
+ app/views/posts/index.html.erb
120
+ app/views/posts/new.html.erb
121
+ app/views/posts/show.html.erb
122
+ app/views/posts/edit.html.erb
123
+ ```
41
124
 
42
- cd APP-NAME
43
- bundle install
125
+ It also adds `use PostsController` to `config.ru`.
44
126
 
45
127
  ## Development
46
128
 
47
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
129
+ Natra is developed on Ruby 3.3.10 (see `.ruby-version`). CI runs on Ruby 3.3 and 3.4.
48
130
 
49
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
131
+ ```sh
132
+ bin/setup # install dependencies
133
+ bundle exec rspec # run the specs
134
+ bundle exec rubocop # lint
135
+ bin/console # Pry session with natra loaded
136
+ ```
50
137
 
51
- ## Contributing
138
+ SimpleCov measures line and branch coverage and writes a report to `coverage/`. CI requires 100% line and branch coverage. Run `CI=true bundle exec rspec` to apply the same check locally.
52
139
 
53
- Bug reports and pull requests are welcome on GitHub at https://github.com/thirunjuguna/natra. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
140
+ To release a new version:
54
141
 
55
- ## License
142
+ 1. Update the version number in `lib/natra/version.rb`.
143
+ 2. Move the entries under "Unreleased" in [CHANGELOG.md](CHANGELOG.md) to a section for the new version.
144
+ 3. Commit, then run `bundle exec rake release`. This builds the gem, tags the version, pushes the commit and tag, and pushes the gem to [rubygems.org](https://rubygems.org/gems/natra).
56
145
 
57
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
146
+ ## Changelog
147
+
148
+ Notable changes are listed in [CHANGELOG.md](CHANGELOG.md).
149
+
150
+ ## Contributing
151
+
152
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jamesnjuguna0419/natra.
153
+
154
+ 1. Open an issue first for larger changes, so the approach can be agreed before you write code.
155
+ 2. Fork the repository and create a branch from `master`.
156
+ 3. Make your change and add or update specs for it. If you change what a generator produces, update its spec under `spec/natra/generators/`.
157
+ 4. Check that `CI=true bundle exec rspec` passes with 100% line and branch coverage, and that `bundle exec rubocop` reports no offenses.
158
+ 5. Add a line to the "Unreleased" section of [CHANGELOG.md](CHANGELOG.md).
159
+ 6. Open a pull request that explains what changed and why.
58
160
 
59
161
  ## Code of Conduct
60
162
 
61
- Everyone interacting in the Natra project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/thirunjuguna/natra/blob/master/CODE_OF_CONDUCT.md).
163
+ This project is intended to be a safe, welcoming space for collaboration. Everyone interacting in the Natra project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [Code of Conduct](CODE_OF_CONDUCT.md), which is adapted from the [Contributor Covenant](https://www.contributor-covenant.org).
164
+
165
+ ## License
166
+
167
+ The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
data/Rakefile CHANGED
@@ -1,5 +1,7 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
  task default: :spec
data/bin/console CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  require 'bundler/setup'
3
5
  require 'natra'
4
6
  require 'pry'
data/bin/natra CHANGED
@@ -1,4 +1,6 @@
1
- #!/usr/bin/env bash
2
- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
3
- require "natra"
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
5
+ require 'natra'
4
6
  Natra::CLI.start
@@ -1,34 +1,38 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Natra
2
4
  module Extensions
5
+ # Naming helpers mixed into String for turning user input into Ruby names.
3
6
  module String
4
7
  def camel_case
5
- return self.gsub(/^./) { |l| l.capitalize } if !match(/[_-]/)
6
- altered_self = self.downcase.capitalize
8
+ return gsub(/^./, &:capitalize) unless match(/[_-]/)
9
+
10
+ altered_self = downcase.capitalize
7
11
  altered_self.scan(/[_-][a-zA-Z]/).each { |match| altered_self.gsub!(match, match[1].upcase) }
8
12
  altered_self
9
13
  end
10
14
 
11
15
  def camel_case!
12
- self.replace camel_case
16
+ replace camel_case
13
17
  end
14
18
 
15
19
  def directory_name
16
- self.downcase.gsub(/[^a-z|\-|\_]/, '')
20
+ downcase.gsub(/[^a-z|_-]/, '')
17
21
  end
18
22
 
19
23
  def file_name
20
- self.gsub(/[\-| ]/, '_').
21
- gsub(/([A-Z]+|[A-Z][a-z])/) { |x| "_#{x}" }.
22
- sub(/^_/, "").
23
- gsub(/_{2,}+/, "_").
24
- downcase
24
+ gsub(/[-| ]/, '_')
25
+ .gsub(/([A-Z]+|[A-Z][a-z])/) { |x| "_#{x}" }
26
+ .sub(/^_/, '')
27
+ .gsub(/_{2,}+/, '_')
28
+ .downcase
25
29
  end
26
30
 
27
31
  def file_name!
28
- self.replace file_name
32
+ replace file_name
29
33
  end
30
34
  end
31
35
  end
32
36
  end
33
37
 
34
- String.send(:include, Natra::Extensions::String)
38
+ String.include(Natra::Extensions::String)
data/lib/natra/cli.rb CHANGED
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
  module Natra
5
+ # Entry point for the natra executable: maps commands onto generators.
3
6
  class CLI < Thor
4
7
  desc '-v', 'Show Natra version number'
5
8
  map %w[-v --version] => :version
@@ -11,9 +14,11 @@ module Natra
11
14
  register Natra::Generators::AppGenerator, 'new', 'new APP_PATH', 'Creates a new Sinatra application'
12
15
  register Natra::Generators::ModelGenerator, 'model', 'model NAME', 'Generate a model'
13
16
  register Natra::Generators::ControllerGenerator, 'controller', 'controller NAME', 'Generate a controller'
14
- register Natra::Generators::ScaffoldGenerator, 'scaffold', 'scaffold NAME', 'Generate a model with its associated views and controllers'
17
+ register Natra::Generators::ScaffoldGenerator, 'scaffold', 'scaffold NAME',
18
+ 'Generate a model with its associated views and controllers'
19
+ register Natra::Generators::ServiceGenerator, 'service_object', 'service_object NAME', 'Generate a service object'
15
20
 
16
- def self.exit_on_failure
21
+ def self.exit_on_failure?
17
22
  true
18
23
  end
19
24
  end
@@ -1,20 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shellwords'
1
4
  require 'thor/group'
2
5
  module Natra
3
6
  module Generators
7
+ # Generates a new Sinatra application skeleton (natra new).
4
8
  class AppGenerator < Thor::Group
5
9
  include Thor::Actions
10
+
6
11
  desc 'Creates a new Sinatra application'
7
12
  argument :name, type: :string, desc: 'The name of the new application'
8
13
  class_option :capistrano, type: :boolean, desc: 'Include Capistrano configuration'
9
14
  class_option :redis, type: :boolean, desc: 'Include Redis configuration'
10
- class_option :rvm, type: :boolean, desc: 'Create .ruby-version (ruby-2.1.0) and .ruby-gemset'
15
+ class_option :rvm, type: :boolean, desc: 'Create .ruby-version (the Ruby running natra, 3.3+) and .ruby-gemset'
11
16
  class_option :bundle, type: :boolean, desc: 'Run bundle after generating the app'
12
17
  class_option :git, type: :boolean, desc: 'Initialize a Git repository'
13
18
 
14
19
  def setup
15
20
  @app_path = name.directory_name
16
21
  @name = name.file_name
17
- options.each { |key, value| instance_variable_set "@#{key}".to_sym, value }
22
+ options.each { |key, value| instance_variable_set :"@#{key}", value }
18
23
  end
19
24
 
20
25
  def self.source_root
@@ -22,22 +27,24 @@ module Natra
22
27
  end
23
28
 
24
29
  def create_empty_directories
25
- %w[config/initializers lib spec].each {|dir| empty_directory File.join(@app_path, dir)}
30
+ %w[config/initializers lib spec app/services].each { |dir| empty_directory File.join(@app_path, dir) }
26
31
  empty_directory File.join(@app_path, 'db/migrate')
27
32
  create_file File.join(@app_path, 'lib', '.keep')
28
33
  template 'config/environment.rb', File.join(@app_path, 'config/environment.rb')
29
34
  end
30
35
 
31
36
  def create_seeds_file
32
- create_file File.join(@app_path, 'db', 'seeds.rb')
37
+ create_file File.join(@app_path, 'db', 'seeds.rb'), "# Seed data, loaded by rake db:seed.\n"
33
38
  end
34
39
 
35
40
  def initialize_db
36
41
  copy_file('bin/setup', File.join(@app_path, 'bin/setup'))
42
+ chmod(File.join(@app_path, 'bin/setup'), 0o755)
37
43
  end
38
44
 
39
45
  def uuid_setup
40
- template 'db/migrate/add_extensions.rb', File.join(@app_path, "db/migrate/#{Time.now.strftime('%Y%m%d')}0000_add_extensions.rb")
46
+ template 'db/migrate/add_extensions.rb',
47
+ File.join(@app_path, "db/migrate/#{Time.now.strftime('%Y%m%d')}0000_add_extensions.rb")
41
48
  end
42
49
 
43
50
  def create_public_directory
@@ -45,7 +52,7 @@ module Natra
45
52
  end
46
53
 
47
54
  def create_app_directory
48
- %w[app/controllers app/views app/models].each {|dir| directory dir, File.join(@app_path, dir)}
55
+ %w[app/controllers app/views app/models].each { |dir| directory dir, File.join(@app_path, dir) }
49
56
  end
50
57
 
51
58
  def create_app_spec
@@ -60,6 +67,14 @@ module Natra
60
67
  template 'config.ru', File.join(@app_path, 'config.ru')
61
68
  end
62
69
 
70
+ def create_puma_config
71
+ copy_file 'config/puma.rb', File.join(@app_path, 'config/puma.rb')
72
+ end
73
+
74
+ def create_oj_initializer
75
+ copy_file 'config/initializers/oj.rb', File.join(@app_path, 'config/initializers/oj.rb')
76
+ end
77
+
63
78
  def create_gemfile
64
79
  template 'Gemfile', File.join(@app_path, 'Gemfile')
65
80
  end
@@ -121,13 +136,13 @@ module Natra
121
136
  end
122
137
 
123
138
  def create_rvm_gemset
124
- if @rvm
125
- create_file(File.join(@app_path, '.ruby-version'), 'ruby-2.1.0')
126
- create_file(File.join(@app_path, '.ruby-gemset'), @app_path)
139
+ return unless @rvm
140
+
141
+ create_file(File.join(@app_path, '.ruby-version'), "ruby-#{RUBY_VERSION}")
142
+ create_file(File.join(@app_path, '.ruby-gemset'), @app_path)
127
143
 
128
- @bundle = false
129
- puts "You need to run 'bundle install' manually."
130
- end
144
+ @bundle = false
145
+ puts "You need to run 'bundle install' manually."
131
146
  end
132
147
 
133
148
  def initialize_git_repo
@@ -138,14 +153,12 @@ module Natra
138
153
  inside(@app_path) { run('bundle') if @bundle }
139
154
  end
140
155
 
156
+ # The Git repository, if any, was created by initialize_git_repo.
141
157
  def initialize_app
142
- system <<~SCRIPT
143
- cd #{@app_path}
144
- #{'chmod +x bin/setup'}
145
- git init
146
- git add .
147
- docker-compose build --pull
148
- SCRIPT
158
+ commands = ["cd #{Shellwords.escape(@app_path)}"]
159
+ commands << 'git add .' if @git
160
+ commands << 'docker compose build --pull'
161
+ system commands.join("\n")
149
162
  end
150
163
  end
151
164
  end
@@ -1,13 +1,31 @@
1
- FROM ruby AS base
1
+ FROM ruby:3.3-slim AS base
2
+
3
+ # build-essential compiles native gems (bcrypt, oj, puma); libpq-dev is needed by pg.
4
+ RUN apt-get update -qq \
5
+ && apt-get install -y --no-install-recommends build-essential git libpq-dev libyaml-dev \
6
+ && rm -rf /var/lib/apt/lists/*
7
+
2
8
  WORKDIR /usr/src/app
3
- RUN gem install bundler
4
- COPY Gemfile /usr/src/app/
9
+
10
+ COPY Gemfile Gemfile.lock* ./
11
+
5
12
  FROM base AS development
6
- RUN bundle install -j5 --without staging production
7
- COPY . /usr/src/app
13
+
14
+ RUN bundle install -j5
15
+
16
+ COPY . .
17
+
8
18
  FROM base AS release
9
- RUN bundle install -j5 --without development test
10
- RUN chmod 755 ./usr/src/app
11
- RUN chmod 755 ./usr/src/app/bin/setup
12
- COPY . /usr/src/app
13
- CMD puma
19
+
20
+ ENV RACK_ENV=production \
21
+ BUNDLE_WITHOUT=development:test
22
+
23
+ RUN bundle install -j5
24
+
25
+ COPY . .
26
+
27
+ RUN chmod 755 bin/setup
28
+
29
+ EXPOSE 9292
30
+
31
+ CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
@@ -1,32 +1,38 @@
1
- source 'http://rubygems.org'
2
- ruby '2.5.3'
3
- gem 'bcrypt'
4
- gem 'coveralls'
5
- gem 'natra'
6
- gem 'oj'
7
- gem 'pg', '~> 0.21.0'
8
- gem 'puma'
9
- gem 'rake'
10
- gem 'rack-timeout'
11
- gem 'require_all'
12
- gem 'seed-fu'
13
- gem 'scout_apm'
14
- gem 'sinatra'
15
- gem 'sinatra-activerecord', :require => 'sinatra/activerecord'
16
- gem 'tux'
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ ruby '~> 3.3'
5
+
6
+ gem 'activerecord', '~> 8.1'
7
+ gem 'bcrypt', '~> 3.1'
8
+ gem 'oj', '~> 3.16'
9
+ gem 'pg', '~> 1.5'
10
+ gem 'puma', '>= 6.4'
11
+ gem 'rack-timeout', '~> 0.7'
12
+ gem 'rake', '~> 13.0'
13
+ <% if @redis -%>
14
+ gem 'redis', '~> 5.0'
15
+ <% end -%>
16
+ gem 'require_all', '~> 3.0'
17
+ gem 'scout_apm', '~> 6.0'
18
+ gem 'seed-fu', '~> 2.3'
19
+ gem 'sinatra', '~> 4.1'
20
+ gem 'sinatra-activerecord', '~> 2.0', require: 'sinatra/activerecord'
21
+
17
22
  group :development, :test do
18
- gem 'pry-byebug'
19
23
  gem 'pry'
24
+ gem 'pry-byebug'
20
25
  end
26
+
21
27
  group :test do
22
- gem 'awesome_print'
28
+ gem 'amazing_print'
23
29
  gem 'capybara'
24
- gem 'database_cleaner'
30
+ gem 'database_cleaner-active_record'
25
31
  gem 'factory_bot'
26
32
  gem 'faker'
27
33
  gem 'guard-rspec'
28
34
  gem 'guard-rubocop'
29
- gem 'simplecov'
30
35
  gem 'rack-test'
31
36
  gem 'rspec'
37
+ gem 'simplecov', require: false
32
38
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  guard :rspec, cmd: 'rspec', all_after_pass: true, all_on_start: true do
2
4
  require 'guard/rspec/dsl'
3
5
  dsl = Guard::RSpec::Dsl.new(self)
@@ -1,52 +1,51 @@
1
1
  # <%= @name %> service
2
2
 
3
- ## Commands
4
- ```
5
- natra -v # Show Natra version number
6
- natra help [COMMAND] # Describe available commands or one specific command
7
- natra new APP-NAME # Creates a new Sinatra application
8
- natra model NAME # Generate a model
9
- natra controller NAME # Generate a controller
10
- natra scaffold NAME # Generate a model with its associated views and controllers
11
- ```
12
- The controller generator also have an optional views flag `--no-views` to create controllers without views.
13
-
14
- ## Using Natra
3
+ A Sinatra JSON API with ActiveRecord and PostgreSQL, generated by [natra](https://github.com/jamesnjuguna0419/natra).
15
4
 
16
- To generate your app:
5
+ ## Running with Docker
17
6
 
18
- natra new APP-NAME
7
+ The database settings come from `secrets.env`.
19
8
 
20
- After natra is done generating your app, run `bundle install` from your app's directory:
9
+ ```sh
10
+ docker compose build
11
+ docker compose run --rm web bin/setup
12
+ docker compose up
13
+ ```
21
14
 
22
- cd APP-NAME
23
- bundle install
15
+ The app listens on http://localhost:9292.
24
16
 
25
- ## Development
17
+ ## Running locally
26
18
 
27
- This project is configured to run in Docker containers facilitated by `docker-compose`. [nib](https://github.com/technekes/nib) is our tool of choice for interacting with `docker-compose` in development.
19
+ You need Ruby 3.3 and a running PostgreSQL server.
28
20
 
21
+ ```sh
22
+ bundle install
23
+ bundle exec rake db:create db:migrate
24
+ bundle exec puma -C config/puma.rb
25
+ ```
29
26
 
30
- ### Running the app
27
+ `config/database.yml` reads the database names from `DEV_DATABASE`, `TEST_DATABASE` and `PROD_DATABASE`, and falls back to `development_<%= @name.directory_name %>`, `test_<%= @name.directory_name %>` and `production_<%= @name.directory_name %>`. If `DATABASE_URL` is set, it is used instead.
31
28
 
32
- Use [nib](https://github.com/technekes/nib) to build and start up the web app.
29
+ ## Tests
33
30
 
34
31
  ```sh
35
- nib build --pull
36
- nib up
32
+ RACK_ENV=test bundle exec rake db:create db:migrate
33
+ bundle exec rspec
37
34
  ```
38
35
 
39
- ### Running Tests
40
-
41
- The app is configured to use [guard](https://github.com/guard/guard) facilitate running the tests as files change. To start up guard run:
36
+ To run the specs and RuboCop as files change:
42
37
 
43
38
  ```sh
44
- nib guard web
39
+ bundle exec guard
45
40
  ```
46
41
 
47
- Alternatively the specs can be run as a one-off with:
42
+ ## Generators
43
+
44
+ Run these from the app directory:
48
45
 
49
46
  ```sh
50
- nib rspec web
47
+ natra model NAME [field:type ...] # Generate a model and its migration
48
+ natra controller NAME # Generate a controller and its views
49
+ natra scaffold NAME [field:type ...] # Generate a model, controller and views
50
+ natra service_object NAME # Generate a service object in app/services
51
51
  ```
52
-
@@ -1,3 +1,4 @@
1
- require_relative './config/environment'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'config/environment'
2
4
  require 'sinatra/activerecord/rake'
3
- require 'sinatra/activerecord'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require './config/environment'
2
4
 
3
5
  class ApplicationController < Sinatra::Base
@@ -1,3 +1,4 @@
1
+ <h1>Welcome to the Sinatra Template!</h1>
1
2
  <div class="sidebar">
2
3
  <h3>Environment</h3>
3
4
  <ul>
@@ -5,6 +6,6 @@
5
6
  <li><b>Environment:</b> <%= ENV["RACK_ENV"] %></li>
6
7
  <li><b>Server:</b> <%= @env["SERVER_SOFTWARE"] %></li>
7
8
  <li><b>Port:</b> <%= @env["SERVER_PORT"] %></li>
8
- <li><b>Help:</b>see the <a href="https://github.com/thirunjuguna/natra">README</a> </li>
9
+ <li><b>Help:</b> see the <a href="https://github.com/jamesnjuguna0419/natra">README</a></li>
9
10
  </ul>
10
11
  </div>