shaf 0.3.1 → 0.4.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/bin/shaf +3 -0
- data/lib/shaf.rb +1 -0
- data/lib/shaf/api_doc/document.rb +0 -1
- data/lib/shaf/app.rb +1 -1
- data/lib/shaf/command.rb +19 -2
- data/lib/shaf/command/generate.rb +11 -1
- data/lib/shaf/command/new.rb +1 -6
- data/lib/shaf/command/server.rb +7 -0
- data/lib/shaf/command/upgrade.rb +38 -0
- data/lib/shaf/extensions/authorize.rb +8 -6
- data/lib/shaf/extensions/resource_uris.rb +129 -71
- data/lib/shaf/generator.rb +4 -0
- data/lib/shaf/generator/controller.rb +2 -2
- data/lib/shaf/generator/migration.rb +33 -14
- data/lib/shaf/generator/migration/add_column.rb +1 -3
- data/lib/shaf/generator/migration/add_index.rb +42 -0
- data/lib/shaf/generator/model.rb +4 -4
- data/lib/shaf/generator/policy.rb +1 -1
- data/lib/shaf/generator/scaffold.rb +3 -3
- data/lib/shaf/generator/serializer.rb +5 -5
- data/lib/shaf/rake.rb +5 -0
- data/lib/shaf/rake/db.rb +79 -0
- data/lib/shaf/rake/test.rb +32 -0
- data/lib/shaf/registrable_factory.rb +8 -3
- data/lib/shaf/settings.rb +20 -4
- data/lib/shaf/tasks.rb +6 -3
- data/lib/shaf/{api_doc/task.rb → tasks/api_doc_task.rb} +6 -5
- data/lib/shaf/tasks/db_task.rb +42 -0
- data/lib/shaf/tasks/test_task.rb +16 -0
- data/lib/shaf/upgrade.rb +3 -0
- data/lib/shaf/upgrade/manifest.rb +31 -0
- data/lib/shaf/upgrade/package.rb +158 -0
- data/lib/shaf/upgrade/version.rb +52 -0
- data/lib/shaf/utils.rb +30 -0
- data/lib/shaf/version.rb +1 -1
- data/templates/Rakefile +2 -3
- data/templates/config/database.rb +3 -3
- metadata +33 -202
- metadata.gz.sig +0 -0
- data/lib/shaf/api_doc.rb +0 -3
- data/lib/shaf/tasks/db.rb +0 -81
- data/lib/shaf/tasks/test.rb +0 -48
data/lib/shaf/generator.rb
CHANGED
@@ -24,12 +24,16 @@ module Shaf
|
|
24
24
|
def usage(str = nil, &block)
|
25
25
|
@usage = str || block
|
26
26
|
end
|
27
|
+
|
28
|
+
def options(option_parser, options); end
|
27
29
|
end
|
28
30
|
|
29
31
|
def initialize(*args)
|
30
32
|
@args = args.dup
|
31
33
|
end
|
32
34
|
|
35
|
+
def call(options = {}); end
|
36
|
+
|
33
37
|
def template_dir
|
34
38
|
File.expand_path('../generator/templates', __FILE__)
|
35
39
|
end
|
@@ -5,9 +5,9 @@ module Shaf
|
|
5
5
|
identifier :controller
|
6
6
|
usage 'generate controller RESOURCE_NAME [attribute:type] [..]'
|
7
7
|
|
8
|
-
def call
|
8
|
+
def call(options = {})
|
9
9
|
create_controller
|
10
|
-
create_integration_spec
|
10
|
+
create_integration_spec if options[:specs]
|
11
11
|
add_link_to_root
|
12
12
|
end
|
13
13
|
|
@@ -23,19 +23,24 @@ module Shaf
|
|
23
23
|
|
24
24
|
class Base
|
25
25
|
DB_COL_TYPES = {
|
26
|
-
integer: ['Integer :%s',
|
27
|
-
varchar: ['String %s',
|
28
|
-
string: ['String :%s',
|
29
|
-
text: ['String :%s, text: true',
|
30
|
-
blob: ['File :%s',
|
31
|
-
bigint: ['Bignum :%s',
|
32
|
-
double: ['Float :%s',
|
33
|
-
numeric: ['BigDecimal :%s',
|
34
|
-
date: ['Date :%s',
|
35
|
-
timestamp: ['DateTime :%s',
|
36
|
-
time: ['Time :%s',
|
37
|
-
bool: ['TrueClass :%s',
|
38
|
-
boolean: ['TrueClass :%s',
|
26
|
+
integer: ['Integer :%s', 'add_column :%s, Integer'],
|
27
|
+
varchar: ['String %s', 'add_column :%s, String'],
|
28
|
+
string: ['String :%s', 'add_column :%s, String'],
|
29
|
+
text: ['String :%s, text: true', 'add_column :%s, String, text: true'],
|
30
|
+
blob: ['File :%s', 'add_column :%s, File'],
|
31
|
+
bigint: ['Bignum :%s', 'add_column :%s, Bignum'],
|
32
|
+
double: ['Float :%s', 'add_column :%s, Float'],
|
33
|
+
numeric: ['BigDecimal :%s', 'add_column :%s, BigDecimal'],
|
34
|
+
date: ['Date :%s', 'add_column :%s, Date'],
|
35
|
+
timestamp: ['DateTime :%s', 'add_column :%s, DateTime'],
|
36
|
+
time: ['Time :%s', 'add_column :%s, Time'],
|
37
|
+
bool: ['TrueClass :%s', 'add_column :%s, TrueClass'],
|
38
|
+
boolean: ['TrueClass :%s', 'add_column :%s, TrueClass'],
|
39
|
+
index: ['index :%s, unique: true', 'add_index :%s'],
|
40
|
+
}
|
41
|
+
|
42
|
+
REGEXP_DB_TYPES = {
|
43
|
+
/\Aforeign_key\((\w+)\)/ => ['foreign_key :%s, :\1', 'add_foreign_key :%s, :\1'],
|
39
44
|
}
|
40
45
|
|
41
46
|
attr_reader :args
|
@@ -74,7 +79,13 @@ module Shaf
|
|
74
79
|
|
75
80
|
def db_type(type)
|
76
81
|
type ||= :string
|
77
|
-
DB_COL_TYPES[type.to_sym]
|
82
|
+
result = DB_COL_TYPES[type.to_sym]
|
83
|
+
result ||= REGEXP_DB_TYPES.each do |pattern, strings|
|
84
|
+
m = pattern.match(type) or next
|
85
|
+
break strings.map { |a| replace_backreferences(m, a) }
|
86
|
+
end
|
87
|
+
raise "Column type '#{type}' not supported" unless result
|
88
|
+
result
|
78
89
|
end
|
79
90
|
|
80
91
|
def column_def(str, create: true)
|
@@ -93,6 +104,13 @@ module Shaf
|
|
93
104
|
DateTime.now.strftime("%Y%m%d%H%M%S")
|
94
105
|
end
|
95
106
|
|
107
|
+
def replace_backreferences(match, str)
|
108
|
+
groups = match.size
|
109
|
+
(1...groups).inject(str) do |s, i|
|
110
|
+
s.gsub("\\#{i}", match[i])
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
96
114
|
def add_timestamp_columns?
|
97
115
|
if File.exist? 'config/initializers/sequel.rb'
|
98
116
|
require 'config/initializers/sequel'
|
@@ -116,6 +134,7 @@ module Shaf
|
|
116
134
|
end
|
117
135
|
|
118
136
|
require 'shaf/generator/migration/add_column'
|
137
|
+
require 'shaf/generator/migration/add_index'
|
119
138
|
require 'shaf/generator/migration/create_table'
|
120
139
|
require 'shaf/generator/migration/drop_column'
|
121
140
|
require 'shaf/generator/migration/empty'
|
@@ -34,9 +34,7 @@ module Shaf
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def add_columns_change
|
37
|
-
cols = columns.map
|
38
|
-
"add_column #{column_def(s, create: false)}"
|
39
|
-
end
|
37
|
+
cols = columns.map { |s| column_def(s, create: false) }
|
40
38
|
[
|
41
39
|
"alter_table(:#{table_name}) do",
|
42
40
|
*cols.map { |col| col.prepend(" ") }, # indent body with 2 spaces
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Shaf
|
2
|
+
module Generator
|
3
|
+
module Migration
|
4
|
+
class AddIndex < Base
|
5
|
+
|
6
|
+
identifier %w(add index)
|
7
|
+
usage 'generate migration add index TABLE_NAME COLUMN_NAME'
|
8
|
+
|
9
|
+
def validate_args
|
10
|
+
if (table_name || "").empty? || (column || "").empty?
|
11
|
+
raise "Please provide a table and the column to create index on"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def compile_migration_name
|
16
|
+
"add_#{column}_index_to_#{table_name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def table_name
|
20
|
+
args.first
|
21
|
+
end
|
22
|
+
|
23
|
+
def compile_changes
|
24
|
+
add_change add_index_change
|
25
|
+
end
|
26
|
+
|
27
|
+
def column
|
28
|
+
args[1]
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_index_change
|
32
|
+
col_def = column_def("#{column}:index", create: false)
|
33
|
+
[
|
34
|
+
"alter_table(:#{table_name}) do",
|
35
|
+
col_def.prepend(" "), # indent body with 2 spaces
|
36
|
+
"end\n"
|
37
|
+
]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/shaf/generator/model.rb
CHANGED
@@ -5,10 +5,10 @@ module Shaf
|
|
5
5
|
identifier :model
|
6
6
|
usage 'generate model MODEL_NAME [attribute:type] [..]'
|
7
7
|
|
8
|
-
def call
|
8
|
+
def call(options = {})
|
9
9
|
create_model
|
10
10
|
create_migration
|
11
|
-
create_serializer
|
11
|
+
create_serializer(options)
|
12
12
|
end
|
13
13
|
|
14
14
|
def model_name
|
@@ -61,10 +61,10 @@ module Shaf
|
|
61
61
|
Migration::Generator.new(*migration_args).call
|
62
62
|
end
|
63
63
|
|
64
|
-
def create_serializer
|
64
|
+
def create_serializer(options)
|
65
65
|
serializer_args = %W(serializer #{model_name})
|
66
66
|
serializer_args += args[1..-1].map { |arg| arg.split(':').first }
|
67
|
-
Generator::Factory.create(*serializer_args).call
|
67
|
+
Generator::Factory.create(*serializer_args).call(options)
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
@@ -5,13 +5,13 @@ module Shaf
|
|
5
5
|
identifier :scaffold
|
6
6
|
usage 'generate scaffold RESOURCE_NAME [attribute:type] [..]'
|
7
7
|
|
8
|
-
def call
|
8
|
+
def call(options = {})
|
9
9
|
if name.empty?
|
10
10
|
raise "Please provide a resource name when using the scaffold generator!"
|
11
11
|
end
|
12
12
|
|
13
|
-
Generator::Factory.create('model', *args).call
|
14
|
-
Generator::Factory.create('controller', *controller_args).call
|
13
|
+
Generator::Factory.create('model', *args).call(options)
|
14
|
+
Generator::Factory.create('controller', *controller_args).call(options)
|
15
15
|
end
|
16
16
|
|
17
17
|
def name
|
@@ -4,10 +4,10 @@ module Shaf
|
|
4
4
|
identifier :serializer
|
5
5
|
usage 'generate serializer MODEL_NAME [attribute] [..]'
|
6
6
|
|
7
|
-
def call
|
7
|
+
def call(options = {})
|
8
8
|
create_serializer
|
9
|
-
create_serializer_spec
|
10
|
-
create_policy
|
9
|
+
create_serializer_spec if options[:specs]
|
10
|
+
create_policy(options)
|
11
11
|
end
|
12
12
|
|
13
13
|
def name
|
@@ -248,9 +248,9 @@ module Shaf
|
|
248
248
|
}
|
249
249
|
end
|
250
250
|
|
251
|
-
def create_policy
|
251
|
+
def create_policy(options)
|
252
252
|
policy_args = ["policy", name, *args[1..-1]]
|
253
|
-
Generator::Factory.create(*policy_args).call
|
253
|
+
Generator::Factory.create(*policy_args).call(options)
|
254
254
|
end
|
255
255
|
end
|
256
256
|
end
|
data/lib/shaf/rake.rb
ADDED
data/lib/shaf/rake/db.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
Shaf::DbTask.new(:version, description: "Prints current schema version") do
|
2
|
+
if migrations.any?
|
3
|
+
version, filename = extract_version_and_filename(last_migration)
|
4
|
+
puts "Schema version: #{version} (#{filename})"
|
5
|
+
else
|
6
|
+
puts "No migrations found"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
Shaf::DbTask.new(:versions, description: "Prints all schema versions") do
|
11
|
+
if migrations.any?
|
12
|
+
migrations.each do |migration|
|
13
|
+
version, filename = extract_version_and_filename(migration)
|
14
|
+
next unless version && filename
|
15
|
+
puts "#{version}: #{filename}"
|
16
|
+
end
|
17
|
+
else
|
18
|
+
puts "No migrations found"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Shaf::DbTask.new(:migrate, description: "Run migrations", args: [:version]) do |t, args|
|
23
|
+
if args[:version]
|
24
|
+
puts "Migrating to version #{args[:version]}"
|
25
|
+
Sequel::Migrator.run(DB, MIGRATIONS_DIR, target: args[:version].to_i)
|
26
|
+
else
|
27
|
+
puts "Migrating to latest"
|
28
|
+
Sequel::Migrator.run(DB, MIGRATIONS_DIR)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Shaf::DbTask.new(
|
33
|
+
:rollback,
|
34
|
+
description: "Perform rollback to specified number of steps back or to the previous version",
|
35
|
+
args: [:target]
|
36
|
+
) do |t, args|
|
37
|
+
|
38
|
+
args.with_defaults(target: 1)
|
39
|
+
target = -(args[:target].to_i + 1)
|
40
|
+
target = 0 if -target > migrations.size
|
41
|
+
migration = migrations.dig(target, :filename)
|
42
|
+
version, _ = extract_version_and_filename(migration)
|
43
|
+
|
44
|
+
warn_if_rolling_back_more_than = 5
|
45
|
+
if target == 0 || -target > warn_if_rolling_back_more_than
|
46
|
+
puts "This would migrate the Database to version: #{version}. Continue [N/y]?"
|
47
|
+
next unless /\Ay/i =~ STDIN.gets.chomp&.downcase
|
48
|
+
end
|
49
|
+
Sequel::Migrator.run(DB, MIGRATIONS_DIR, target: version.to_i)
|
50
|
+
end
|
51
|
+
|
52
|
+
Rake::Task["db:migrate"].enhance do
|
53
|
+
Rake::Task["db:version"].invoke
|
54
|
+
end
|
55
|
+
|
56
|
+
Rake::Task["db:rollback"].enhance do
|
57
|
+
Rake::Task["db:version"].invoke
|
58
|
+
end
|
59
|
+
|
60
|
+
Shaf::DbTask.new(:reset, description: "Reset the database by deleting all rows in all columns") do
|
61
|
+
version = 0
|
62
|
+
Sequel::Migrator.run(DB, MIGRATIONS_DIR, target: version)
|
63
|
+
Sequel::Migrator.run(DB, MIGRATIONS_DIR)
|
64
|
+
end
|
65
|
+
|
66
|
+
Shaf::DbTask.new(:seed, description: "Seed the Database") do
|
67
|
+
ENV['RACK_ENV'] ||= 'development'
|
68
|
+
require 'config/bootstrap'
|
69
|
+
|
70
|
+
if File.exist? "db/seeds.rb"
|
71
|
+
require "db/seeds"
|
72
|
+
end
|
73
|
+
|
74
|
+
if Dir.exist? "db/seeds"
|
75
|
+
Dir['db/seeds/**/*.rb'].each do |file|
|
76
|
+
require file.sub(".rb", "")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'shaf/tasks'
|
2
|
+
|
3
|
+
namespace :test do |ns|
|
4
|
+
Shaf::TestTask.new(:integration) do |t|
|
5
|
+
t.pattern = "spec/integration/**/*_spec.rb"
|
6
|
+
end
|
7
|
+
|
8
|
+
Shaf::TestTask.new(:models) do |t|
|
9
|
+
t.pattern = "spec/models/**/*_spec.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
Shaf::TestTask.new(:serializers) do |t|
|
13
|
+
t.pattern = "spec/serializers/**/*_spec.rb"
|
14
|
+
end
|
15
|
+
|
16
|
+
Shaf::TestTask.new(:lib) do |t|
|
17
|
+
t.pattern = "spec/lib/**/*_spec.rb"
|
18
|
+
end
|
19
|
+
|
20
|
+
Shaf::TestTask.new(:all) do |t|
|
21
|
+
t.pattern = [
|
22
|
+
"spec/lib/**/*_spec.rb",
|
23
|
+
"spec/models/**/*_spec.rb",
|
24
|
+
"spec/serializers/**/*_spec.rb",
|
25
|
+
"spec/integration/**/*_spec.rb"
|
26
|
+
]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Run all tests"
|
31
|
+
task test: 'test:all'
|
32
|
+
|
@@ -7,6 +7,11 @@ module Shaf
|
|
7
7
|
reg.dup
|
8
8
|
end
|
9
9
|
|
10
|
+
def each
|
11
|
+
return all.each unless block_given?
|
12
|
+
all.each { |c| yield c }
|
13
|
+
end
|
14
|
+
|
10
15
|
def size
|
11
16
|
reg.size
|
12
17
|
end
|
@@ -29,7 +34,7 @@ module Shaf
|
|
29
34
|
|
30
35
|
def usage
|
31
36
|
reg.compact.map do |entry|
|
32
|
-
usage = entry.
|
37
|
+
usage = entry.instance_variable_get(:@usage)
|
33
38
|
usage.respond_to?(:call) ? usage.call : usage
|
34
39
|
end
|
35
40
|
end
|
@@ -49,7 +54,7 @@ module Shaf
|
|
49
54
|
end
|
50
55
|
|
51
56
|
def matching_class?(strings, clazz)
|
52
|
-
identifiers = clazz.
|
57
|
+
identifiers = clazz.instance_variable_get(:@identifiers)
|
53
58
|
return false if strings.size < identifiers.size
|
54
59
|
identifiers.zip(strings).all? { |pattern, str| matching_identifier? str, pattern }
|
55
60
|
end
|
@@ -62,7 +67,7 @@ module Shaf
|
|
62
67
|
end
|
63
68
|
|
64
69
|
def identifier_count(clazz)
|
65
|
-
clazz.
|
70
|
+
clazz.instance_variable_get(:@identifiers)&.size || 0
|
66
71
|
end
|
67
72
|
|
68
73
|
def init_args(clazz, params)
|
data/lib/shaf/settings.rb
CHANGED
@@ -18,16 +18,32 @@ module Shaf
|
|
18
18
|
def method_missing(method, *args)
|
19
19
|
load unless defined? @settings
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
if method.to_s.end_with? "="
|
22
|
+
define_setter(method)
|
23
|
+
public_send(method, args.first)
|
24
|
+
else
|
25
|
+
define_getter(method)
|
26
|
+
public_send(method)
|
23
27
|
end
|
24
|
-
|
25
|
-
return public_send(method)
|
26
28
|
end
|
27
29
|
|
28
30
|
def respond_to_missing?(method, include_private = false)
|
29
31
|
return true
|
30
32
|
end
|
33
|
+
|
34
|
+
def define_getter(method)
|
35
|
+
define_singleton_method(method) do
|
36
|
+
@settings.dig(env.to_s, method.to_s)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def define_setter(method)
|
41
|
+
define_singleton_method(method) do |arg|
|
42
|
+
key = method[0..-2]
|
43
|
+
@settings[env.to_s] ||= {}
|
44
|
+
@settings[env.to_s][key] = arg
|
45
|
+
end
|
46
|
+
end
|
31
47
|
end
|
32
48
|
end
|
33
49
|
end
|
data/lib/shaf/tasks.rb
CHANGED