strum 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rakeTasks +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +25 -0
- data/CHANGELOG.md +1 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +71 -0
- data/README.md +35 -0
- data/Rakefile +8 -0
- data/bin/strum +5 -0
- data/lib/strum/Rakefile +6 -0
- data/lib/strum/cli.rb +37 -0
- data/lib/strum/command.rb +18 -0
- data/lib/strum/commands/generate.rb +33 -0
- data/lib/strum/commands/mixin/app_check.rb +21 -0
- data/lib/strum/commands/mixin/fields.rb +29 -0
- data/lib/strum/commands/mixin/names.rb +57 -0
- data/lib/strum/commands/new.rb +68 -0
- data/lib/strum/commands/resource/migration.rb +59 -0
- data/lib/strum/commands/resource/model.rb +31 -0
- data/lib/strum/commands/resource/route.rb +47 -0
- data/lib/strum/commands/resource/scaffold.rb +20 -0
- data/lib/strum/commands/resource/serializer.rb +31 -0
- data/lib/strum/commands/resource/service.rb +42 -0
- data/lib/strum/service.rb +116 -0
- data/lib/strum/sub_command_base.rb +18 -0
- data/lib/strum/tasks/sequel.rake +87 -0
- data/lib/strum/templates/app/blank/.env.local.tt +6 -0
- data/lib/strum/templates/app/blank/.env.test.tt +4 -0
- data/lib/strum/templates/app/blank/.gitignore +26 -0
- data/lib/strum/templates/app/blank/.rubocop.yml +28 -0
- data/lib/strum/templates/app/blank/Dockerfile +15 -0
- data/lib/strum/templates/app/blank/Gemfile.tt +68 -0
- data/lib/strum/templates/app/blank/Rakefile +8 -0
- data/lib/strum/templates/app/blank/bin/console.tt +15 -0
- data/lib/strum/templates/app/blank/config/app.rb.tt +60 -0
- data/lib/strum/templates/app/blank/config/env.rb +12 -0
- data/lib/strum/templates/app/blank/config.ru.tt +18 -0
- data/lib/strum/templates/app/blank/lib/.keep +0 -0
- data/lib/strum/templates/app/blank/routes/.keep +0 -0
- data/lib/strum/templates/app/blank/services/.keep +0 -0
- data/lib/strum/templates/app/json/serializers/.keep +0 -0
- data/lib/strum/templates/app/sequel/config/models.rb +18 -0
- data/lib/strum/templates/app/sequel/config/sequel.rb +10 -0
- data/lib/strum/templates/app/sequel/db/migrations/001_setup.rb +17 -0
- data/lib/strum/templates/app/sequel/models/.keep +0 -0
- data/lib/strum/templates/migration/%migration_filename%.rb.tt +27 -0
- data/lib/strum/templates/model/%resource_filename%.rb.tt +12 -0
- data/lib/strum/templates/route/%resource_filename%.rb.tt +9 -0
- data/lib/strum/templates/route_crud/%resource_filename%.rb.tt +44 -0
- data/lib/strum/templates/serializer/%resource_name%_serializer.rb.tt +17 -0
- data/lib/strum/templates/service/%resource_filename%.rb.tt +22 -0
- data/lib/strum/templates/service_crud/%resource_name%/create.rb.tt +28 -0
- data/lib/strum/templates/service_crud/%resource_name%/delete.rb.tt +27 -0
- data/lib/strum/templates/service_crud/%resource_name%/find.rb.tt +25 -0
- data/lib/strum/templates/service_crud/%resource_name%/search.rb.tt +23 -0
- data/lib/strum/templates/service_crud/%resource_name%/update.rb.tt +28 -0
- data/lib/strum/version.rb +5 -0
- data/lib/strum.rb +9 -0
- data/strum.gemspec +46 -0
- metadata +219 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "strum/commands/mixin/app_check"
|
4
|
+
require "strum/commands/mixin/names"
|
5
|
+
require "strum/commands/mixin/fields"
|
6
|
+
|
7
|
+
module Strum::Commands::Resource
|
8
|
+
# Strum generate sub command
|
9
|
+
# `strum generate service`
|
10
|
+
class Service < Thor::Group
|
11
|
+
include Thor::Actions
|
12
|
+
include Strum::Commands::Mixin::AppCheck
|
13
|
+
include Strum::Commands::Mixin::Names
|
14
|
+
include Strum::Commands::Mixin::Fields
|
15
|
+
|
16
|
+
argument :name
|
17
|
+
class_option :crud, type: :boolean, aliases: ["-c"]
|
18
|
+
class_option :fields, type: :array, default: []
|
19
|
+
|
20
|
+
def self.source_root
|
21
|
+
File.expand_path("../../templates", __dir__)
|
22
|
+
end
|
23
|
+
|
24
|
+
def pre_check
|
25
|
+
raise StrumGenerateError, "This is not Strum application" unless strum?
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_service_files
|
29
|
+
options[:crud] ? crud_service : basic_service
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def basic_service
|
35
|
+
directory("service", File.expand_path(namespace_path, "services"))
|
36
|
+
end
|
37
|
+
|
38
|
+
def crud_service
|
39
|
+
directory("service_crud", File.expand_path(namespace_path, "services"))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/matcher"
|
4
|
+
|
5
|
+
module Strum
|
6
|
+
# Module
|
7
|
+
module Service
|
8
|
+
class Failure < StandardError; end
|
9
|
+
|
10
|
+
StrumMatcher = Dry::Matcher.new(
|
11
|
+
success: Dry::Matcher::Case.new(
|
12
|
+
match: lambda do |value, *pattern|
|
13
|
+
value[0] && (pattern.any? ? pattern.include?(value[1]) : true)
|
14
|
+
end,
|
15
|
+
resolve: ->(value) { value.last }
|
16
|
+
),
|
17
|
+
failure: Dry::Matcher::Case.new(
|
18
|
+
match: lambda do |value, *pattern|
|
19
|
+
!value[0] && (pattern.any? ? pattern.include?(value[1]) : true)
|
20
|
+
end,
|
21
|
+
resolve: ->(value) { value.last }
|
22
|
+
)
|
23
|
+
)
|
24
|
+
|
25
|
+
def self.included(base)
|
26
|
+
base.class_eval do
|
27
|
+
extend ClassMethods
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Internal: Interactor class methods.
|
32
|
+
module ClassMethods
|
33
|
+
def call(input = {}, &block)
|
34
|
+
strum = new(input)
|
35
|
+
strum.audit
|
36
|
+
strum.call if strum.valid?
|
37
|
+
strum.valid? ? valid_result(strum, &block) : invalid_result(strum, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def valid_result(strum, &block)
|
43
|
+
return strum.output || strum.outputs unless block_given?
|
44
|
+
return StrumMatcher.call([true, strum.output], &block) if strum.output
|
45
|
+
|
46
|
+
StrumMatcher.call([true, *strum.outputs.keys, strum.outputs], &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def invalid_result(strum, &block)
|
50
|
+
return nil unless block_given?
|
51
|
+
|
52
|
+
StrumMatcher.call([false, *strum.errors.values, strum.errors], &block)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
attr_reader :output, :outputs
|
57
|
+
|
58
|
+
# Instance methods
|
59
|
+
def initialize(input)
|
60
|
+
self.strum_errors = {}
|
61
|
+
self.outputs = {}
|
62
|
+
raise Failure, "'input' must be a Hash" unless input.is_a?(Hash)
|
63
|
+
|
64
|
+
self.input = input.transform_keys do |key|
|
65
|
+
key_to_sym(key)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def call
|
70
|
+
raise Failure, "call method must be implemented"
|
71
|
+
end
|
72
|
+
|
73
|
+
def audit; end
|
74
|
+
|
75
|
+
def valid?
|
76
|
+
strum_errors.empty?
|
77
|
+
end
|
78
|
+
|
79
|
+
def errors
|
80
|
+
strum_errors
|
81
|
+
end
|
82
|
+
|
83
|
+
protected
|
84
|
+
|
85
|
+
attr_accessor :input, :strum_errors
|
86
|
+
attr_writer :output, :outputs
|
87
|
+
|
88
|
+
def add_error(field, value)
|
89
|
+
if field.is_a?(Array)
|
90
|
+
field.each do |key|
|
91
|
+
value.is_a?(Array) ? value.each { |v| add_error(key, v) } : add_error(key, value)
|
92
|
+
add_error(key, value.is_a?(Array) ? value.first : value)
|
93
|
+
end
|
94
|
+
else
|
95
|
+
strum_errors[field] ||= []
|
96
|
+
strum_errors[field] = strum_errors[field] + Array(value)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def add_errors(errors)
|
101
|
+
errors.each { |field, value| add_error(field, value) }
|
102
|
+
end
|
103
|
+
|
104
|
+
def required(*keys)
|
105
|
+
keys.each { |key| add_error(key, :field_must_exist) unless input[key] }
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def key_to_sym(key)
|
111
|
+
key.to_sym
|
112
|
+
rescue StandardError
|
113
|
+
key
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
|
5
|
+
module Strum
|
6
|
+
# SubCommand Base class
|
7
|
+
class SubCommandBase < Thor
|
8
|
+
def self.banner(command, _namespace = nil, _subcommand = false)
|
9
|
+
"#{basename} #{subcommand_prefix} #{command.usage}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.subcommand_prefix
|
13
|
+
name.gsub(/.*::/, "")
|
14
|
+
.gsub(/^[A-Z]/) { |match| match[0].downcase }
|
15
|
+
.gsub(/[A-Z]/) { |match| "-#{match[0].downcase}" }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :sequel do # rubocop:disable Metrics/BlockLength
|
4
|
+
require "sequel"
|
5
|
+
Sequel.extension :migration
|
6
|
+
|
7
|
+
def postgres_cmd
|
8
|
+
postgres_db = Sequel.connect(adapter: "postgres",
|
9
|
+
host: ENV.fetch("DATABASE_HOST", "localhost"),
|
10
|
+
database: "postgres",
|
11
|
+
user: ENV.fetch("DATABASE_USER", "postgres"),
|
12
|
+
password: ENV.fetch("DATABASE_PASSWORD", nil))
|
13
|
+
yield(postgres_db)
|
14
|
+
postgres_db.disconnect
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Drop database"
|
18
|
+
task :drop do
|
19
|
+
postgres_cmd do |db|
|
20
|
+
db.execute "DROP DATABASE IF EXISTS \"#{ENV.fetch('DATABASE_NAME')}\""
|
21
|
+
puts "Database #{ENV.fetch('DATABASE_NAME')} dropped"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Create database"
|
26
|
+
task :create do
|
27
|
+
postgres_cmd do |db|
|
28
|
+
db.execute "CREATE DATABASE \"#{ENV.fetch('DATABASE_NAME')}\""
|
29
|
+
puts "Database #{ENV.fetch('DATABASE_NAME')} created"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Reset database"
|
34
|
+
task :reset do
|
35
|
+
postgres_cmd do |db|
|
36
|
+
db.execute "DROP DATABASE IF EXISTS \"#{ENV.fetch('DATABASE_NAME')}\""
|
37
|
+
db.execute "CREATE DATABASE \"#{ENV.fetch('DATABASE_NAME')}\""
|
38
|
+
puts "Database #{ENV.fetch('DATABASE_NAME')} recreated"
|
39
|
+
end
|
40
|
+
Rake::Task["sequel:migrate"].execute
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "Prints current schema version"
|
44
|
+
task :version do
|
45
|
+
require "config/sequel"
|
46
|
+
version = if DB.tables.include?(:schema_migrations) && DB[:schema_migrations].count.positive?
|
47
|
+
DB[:schema_migrations].order(:filename).last[:filename]
|
48
|
+
end || 0
|
49
|
+
|
50
|
+
puts "Current schema version: #{version}"
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "Migrate database"
|
54
|
+
task :migrate, [:version] do |_t, args|
|
55
|
+
require "config/sequel"
|
56
|
+
require "logger"
|
57
|
+
Sequel.extension :migration
|
58
|
+
DB.loggers << Logger.new($stdout) if DB.loggers.empty?
|
59
|
+
Sequel::TimestampMigrator.apply(DB, File.join(ENV["STRUM_ROOT"], "db/migrations"), args.version)
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "Rollback database"
|
63
|
+
task :rollback do
|
64
|
+
require "config/sequel"
|
65
|
+
Rake::Task["sequel:version"].execute
|
66
|
+
if DB[:schema_migrations].count > 1
|
67
|
+
prev_version = DB[:schema_migrations]
|
68
|
+
.order(Sequel.desc(:filename))
|
69
|
+
.limit(2)
|
70
|
+
.all
|
71
|
+
.last[:filename]
|
72
|
+
target = prev_version.split("_").first.to_i
|
73
|
+
end
|
74
|
+
|
75
|
+
Rake::Task["sequel:migrate"].invoke(target || 0)
|
76
|
+
Rake::Task["sequel:version"].execute
|
77
|
+
end
|
78
|
+
|
79
|
+
desc "Annotate Sequel models"
|
80
|
+
task "annotate" do
|
81
|
+
ENV["RACK_ENV"] = "development"
|
82
|
+
require File.join(ENV["STRUM_ROOT"], "config", "models.rb")
|
83
|
+
DB.loggers.clear
|
84
|
+
require "sequel/annotate"
|
85
|
+
Sequel::Annotate.annotate(Dir[File.join(ENV["STRUM_ROOT"], "models/*.rb")])
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore all logfiles and tempfiles.
|
11
|
+
/log/*
|
12
|
+
/tmp/*
|
13
|
+
!/log/.keep
|
14
|
+
!/tmp/.keep
|
15
|
+
|
16
|
+
.byebug_history
|
17
|
+
|
18
|
+
# Editor directories and files
|
19
|
+
.idea
|
20
|
+
.vscode
|
21
|
+
*.suo
|
22
|
+
*.ntvs*
|
23
|
+
*.njsproj
|
24
|
+
*.sln
|
25
|
+
*.sw*
|
26
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.6
|
3
|
+
|
4
|
+
# Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
|
5
|
+
Style/HashSyntax:
|
6
|
+
Enabled: true
|
7
|
+
|
8
|
+
# Method definitions after `private` or `protected` isolated calls need one
|
9
|
+
# extra level of indentation.
|
10
|
+
Layout/IndentationConsistency:
|
11
|
+
Enabled: true
|
12
|
+
# EnforcedStyle: rails
|
13
|
+
|
14
|
+
# Two spaces, no tabs (for indentation).
|
15
|
+
Layout/IndentationWidth:
|
16
|
+
Enabled: true
|
17
|
+
|
18
|
+
# Check quotes usage according to lint rule below.
|
19
|
+
Style/StringLiterals:
|
20
|
+
Enabled: true
|
21
|
+
EnforcedStyle: double_quotes
|
22
|
+
|
23
|
+
Metrics/LineLength:
|
24
|
+
Max: 120
|
25
|
+
IgnoredPatterns: ['\A#']
|
26
|
+
|
27
|
+
Style/Semicolon:
|
28
|
+
AllowAsExpressionSeparator: true
|
@@ -0,0 +1,15 @@
|
|
1
|
+
FROM registry.gitlab.com/qpard/ruby:latest as builder
|
2
|
+
|
3
|
+
WORKDIR /usr/src/app
|
4
|
+
ENV RACK_ENV production
|
5
|
+
RUN apk add curl-dev ruby-dev build-base tzdata postgresql-dev
|
6
|
+
COPY Gemfile* ./
|
7
|
+
RUN bundle install --without development test
|
8
|
+
|
9
|
+
FROM registry.gitlab.com/qpard/ruby:latest AS runtime
|
10
|
+
WORKDIR /usr/src/app
|
11
|
+
ENV RACK_ENV production
|
12
|
+
|
13
|
+
RUN apk add tzdata postgresql-dev
|
14
|
+
COPY --from=builder /usr/local/bundle /usr/local/bundle
|
15
|
+
COPY . ./
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
# framework
|
6
|
+
<% if rabbit? -%>
|
7
|
+
gem "bunny", ">= 2.14.1"
|
8
|
+
<% end -%>
|
9
|
+
<% if json? -%>
|
10
|
+
gem "fast_jsonapi"
|
11
|
+
<% end -%>
|
12
|
+
gem "puma", "~> 4.2.0"
|
13
|
+
<% if cors? -%>
|
14
|
+
gem "rack-cors"
|
15
|
+
<% end -%>
|
16
|
+
gem "rack-unreloader", "~> 1.7"
|
17
|
+
gem "rake", "~> 13"
|
18
|
+
<% if redis? -%>
|
19
|
+
gem "redis-objects"
|
20
|
+
<% end -%>
|
21
|
+
gem "roda", "~> 3.24"
|
22
|
+
<% if sequel? -%>
|
23
|
+
|
24
|
+
# database
|
25
|
+
gem "pg", "~> 1.1.4"
|
26
|
+
gem "sequel", "~> 5.24"
|
27
|
+
gem "sequel_pg", "~> 1.12"
|
28
|
+
<% end -%>
|
29
|
+
|
30
|
+
# Strum framework
|
31
|
+
gem "strum", "~> 0.0.19"
|
32
|
+
|
33
|
+
group :development do
|
34
|
+
# A Ruby code quality reporter
|
35
|
+
gem "rubycritic", require: false
|
36
|
+
|
37
|
+
# A Ruby static code analyzer and formatter,
|
38
|
+
# based on the community Ruby style guide. https://docs.rubocop.org
|
39
|
+
gem "rubocop", "~> 0.62.0", require: false
|
40
|
+
|
41
|
+
gem "roda-route_list"
|
42
|
+
end
|
43
|
+
|
44
|
+
group :test do
|
45
|
+
<% if sequel? -%>
|
46
|
+
gem "database_cleaner"
|
47
|
+
<% end -%>
|
48
|
+
gem "email_spec"
|
49
|
+
gem "json_spec"
|
50
|
+
end
|
51
|
+
|
52
|
+
group :development, :test do
|
53
|
+
# Call "byebug" anywhere in the code
|
54
|
+
# to stop execution and get a debugger console
|
55
|
+
gem "byebug", platforms: %i[mri mingw x64_mingw]
|
56
|
+
gem "factory_bot"
|
57
|
+
gem "rspec"
|
58
|
+
gem "rspec_junit_formatter"
|
59
|
+
|
60
|
+
gem "debase", "~> 0.2.4"
|
61
|
+
gem "ruby-debug-ide", "~> 0.7.0"
|
62
|
+
<% if sequel? -%>
|
63
|
+
gem "sequel-annotate"
|
64
|
+
<% end -%>
|
65
|
+
|
66
|
+
# A Ruby gem to load environment variables from `.env`.
|
67
|
+
gem "dotenv"
|
68
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "irb"
|
5
|
+
require "logger"
|
6
|
+
require "./config/env"
|
7
|
+
unless defined?(Unreloader)
|
8
|
+
require "rack/unreloader"
|
9
|
+
Unreloader = Rack::Unreloader.new(subclasses: %w[Sequel::Model], logger: Logger.new($stdout), reload: true) { <%= app_class_name %> }
|
10
|
+
end
|
11
|
+
<% if sequel? %>
|
12
|
+
require "config/sequel"
|
13
|
+
Unreloader.require('models'){|f| Sequel::Model.send(:camelize, File.basename(f).sub(/\.rb\z/, ''))}
|
14
|
+
<% end %>
|
15
|
+
IRB.start
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
<% if sequel? -%>
|
4
|
+
require "config/sequel"
|
5
|
+
require "config/models"
|
6
|
+
|
7
|
+
<% end -%>
|
8
|
+
require "roda"
|
9
|
+
<% if json? -%>
|
10
|
+
require "fast_jsonapi"
|
11
|
+
<% end -%>
|
12
|
+
require "strum"
|
13
|
+
<% if cors? -%>
|
14
|
+
require "rack/cors"
|
15
|
+
<% end -%>
|
16
|
+
<% if rabbit? -%>
|
17
|
+
require "bunny"
|
18
|
+
<% end -%>
|
19
|
+
<% if redis? -%>
|
20
|
+
require "redis/objects"
|
21
|
+
<% end -%>
|
22
|
+
|
23
|
+
unless defined?(Unreloader)
|
24
|
+
require "rack/unreloader"
|
25
|
+
Unreloader = Rack::Unreloader.new(reload: false)
|
26
|
+
end
|
27
|
+
|
28
|
+
Unreloader.require("services")
|
29
|
+
<% if json? -%>
|
30
|
+
Unreloader.require("serializers")
|
31
|
+
<% end -%>
|
32
|
+
|
33
|
+
# Main <%= app_class_name %> route class
|
34
|
+
class <%= app_class_name %> < Roda
|
35
|
+
opts[:root] = ENV["STRUM_ROOT"]
|
36
|
+
plugin :all_verbs
|
37
|
+
plugin :symbol_status
|
38
|
+
plugin :json, content_type: "application/vnd.api+json"
|
39
|
+
plugin :json_parser
|
40
|
+
<% if cors? %>
|
41
|
+
# Rack Middleware for handling Cross-Origin Resource Sharing (CORS), which makes cross-origin AJAX possible.
|
42
|
+
# https://github.com/cyu/rack-cors#rack-configuration
|
43
|
+
use Rack::Cors do
|
44
|
+
allow do
|
45
|
+
origins "*"
|
46
|
+
resource "*", headers: :any, methods: %i[get post options]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
<% end %>
|
50
|
+
plugin :hash_routes
|
51
|
+
Unreloader.require("routes")
|
52
|
+
|
53
|
+
route(&:hash_routes)
|
54
|
+
|
55
|
+
# for more details usage
|
56
|
+
# route do |req|
|
57
|
+
# req.public
|
58
|
+
# req.hash_routes
|
59
|
+
# end
|
60
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.expand_path("..", __dir__), File.expand_path("../lib", __dir__))
|
4
|
+
|
5
|
+
ENV["RACK_ENV"] ||= "development"
|
6
|
+
|
7
|
+
unless ENV["RACK_ENV"] == "production"
|
8
|
+
require "dotenv"
|
9
|
+
Dotenv.load(".env.#{ENV['RACK_ENV'].downcase}", ".env.local")
|
10
|
+
end
|
11
|
+
|
12
|
+
ENV["STRUM_ROOT"] = File.expand_path("..", __dir__)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "./config/env"
|
4
|
+
|
5
|
+
dev = ENV["RACK_ENV"] == "development"
|
6
|
+
|
7
|
+
if dev
|
8
|
+
require "logger"
|
9
|
+
logger = Logger.new($stdout)
|
10
|
+
end
|
11
|
+
|
12
|
+
require "rack/unreloader"
|
13
|
+
Unreloader = Rack::Unreloader.new(subclasses: %w[Roda Sequel::Model],
|
14
|
+
logger: logger,
|
15
|
+
reload: dev) { <%= app_class_name %> }
|
16
|
+
|
17
|
+
Unreloader.require("config/app.rb") { "<%= app_class_name %>" }
|
18
|
+
run(dev ? Unreloader : <%= app_class_name %>.freeze.app)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "sequel/model"
|
4
|
+
require "config/sequel.rb"
|
5
|
+
|
6
|
+
Sequel::Model.plugin(:auto_validations)
|
7
|
+
Sequel::Model.plugin(:constraint_validations)
|
8
|
+
Sequel::Model.plugin(:subclasses)
|
9
|
+
Sequel::Model.cache_associations = false if ENV["RACK_ENV"] == "development"
|
10
|
+
|
11
|
+
unless defined?(Unreloader)
|
12
|
+
require "rack/unreloader"
|
13
|
+
Unreloader = Rack::Unreloader.new(reload: false)
|
14
|
+
end
|
15
|
+
|
16
|
+
Unreloader.require("models") do |f|
|
17
|
+
Sequel::Model.send(:camelize, File.basename(f).sub(/\.rb\z/, ""))
|
18
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "sequel"
|
4
|
+
|
5
|
+
DB = Sequel.connect adapter: "postgres",
|
6
|
+
host: ENV.delete("DATABASE_HOST") || "localhost",
|
7
|
+
database: ENV.delete("DATABASE_NAME"),
|
8
|
+
user: ENV.delete("DATABASE_USER"),
|
9
|
+
password: ENV.delete("DATABASE_PASSWORD")
|
10
|
+
DB.extension(:pg_array, :pg_json)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Sequel.migration do
|
4
|
+
up do
|
5
|
+
DB.extension(:constraint_validations)
|
6
|
+
DB.extension(:pg_array)
|
7
|
+
DB.extension(:pg_json)
|
8
|
+
DB.create_constraint_validations_table
|
9
|
+
extension :date_arithmetic
|
10
|
+
run "CREATE EXTENSION IF NOT EXISTS citext;"
|
11
|
+
end
|
12
|
+
|
13
|
+
down do
|
14
|
+
DB.extension(:constraint_validations)
|
15
|
+
DB.drop_constraint_validations_table
|
16
|
+
end
|
17
|
+
end
|
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Sequel.migration do
|
4
|
+
<%- if model? -%>
|
5
|
+
change do
|
6
|
+
extension(:constraint_validations)
|
7
|
+
create_table(:<%= table_name %>) do
|
8
|
+
primary_key :id
|
9
|
+
# code here ...
|
10
|
+
end
|
11
|
+
end
|
12
|
+
<%- else -%>
|
13
|
+
change do
|
14
|
+
primary_key :id
|
15
|
+
# code here...
|
16
|
+
end
|
17
|
+
|
18
|
+
# or use up/down
|
19
|
+
# up do
|
20
|
+
# # up here...
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# down do
|
24
|
+
# # down here...
|
25
|
+
# end
|
26
|
+
<%- end -%>
|
27
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
<%- namespace_names.each_with_index do |c,i| -%>
|
4
|
+
<%= ' ' * i %>module <%= c %>
|
5
|
+
<%- end -%>
|
6
|
+
<%= ident %># Strum service
|
7
|
+
<%= ident %># You model description here...
|
8
|
+
<%= ident %>class <%= resource_class_name -%> < Sequel::Model
|
9
|
+
<%= ident %>end
|
10
|
+
<%- (namespace_names.size - 1).downto(0) do |i| -%>
|
11
|
+
<%= ' ' * i %>end
|
12
|
+
<%- end -%>
|