shaf 2.1.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/shaf/app.rb +27 -9
- data/lib/shaf/command/base.rb +4 -0
- data/lib/shaf/command/new.rb +5 -1
- data/lib/shaf/command/server.rb +5 -1
- data/lib/shaf/command/templates/config/settings.yml.erb +9 -8
- data/lib/shaf/extensions/resource_uris.rb +37 -155
- data/lib/shaf/extensions/symbolic_routes.rb +5 -18
- data/lib/shaf/formable/builder.rb +58 -19
- data/lib/shaf/formable/form.rb +13 -10
- data/lib/shaf/formable.rb +10 -23
- data/lib/shaf/generator/base.rb +82 -0
- data/lib/shaf/generator/controller.rb +19 -35
- data/lib/shaf/generator/forms.rb +10 -14
- data/lib/shaf/generator/migration/add_column.rb +0 -4
- data/lib/shaf/generator/migration/add_index.rb +0 -4
- data/lib/shaf/generator/migration/base.rb +8 -0
- data/lib/shaf/generator/migration/create_table.rb +0 -4
- data/lib/shaf/generator/migration/drop_column.rb +0 -4
- data/lib/shaf/generator/migration/rename_column.rb +0 -4
- data/lib/shaf/generator/model.rb +29 -14
- data/lib/shaf/generator/policy.rb +8 -14
- data/lib/shaf/generator/profile.rb +9 -14
- data/lib/shaf/generator/scaffold.rb +6 -9
- data/lib/shaf/generator/serializer.rb +31 -30
- data/lib/shaf/generator/templates/api/controller.rb.erb +13 -13
- data/lib/shaf/generator/templates/api/forms.rb.erb +2 -2
- data/lib/shaf/generator/templates/api/model.rb.erb +1 -1
- data/lib/shaf/generator/templates/api/profile.rb.erb +1 -1
- data/lib/shaf/generator/templates/api/serializer.rb.erb +1 -1
- data/lib/shaf/generator/templates/spec/integration_spec.rb.erb +14 -14
- data/lib/shaf/helpers/paginate.rb +1 -1
- data/lib/shaf/profile.rb +8 -8
- data/lib/shaf/registrable_factory.rb +62 -32
- data/lib/shaf/responder/problem_json.rb +1 -1
- data/lib/shaf/router.rb +65 -12
- data/lib/shaf/spec/integration_spec.rb +1 -1
- data/lib/shaf/tasks.rb +0 -1
- data/lib/shaf/upgrade/package.rb +5 -7
- data/lib/shaf/version.rb +1 -1
- data/templates/Rakefile +0 -6
- data/templates/api/controllers/base_controller.rb +0 -2
- data/templates/api/serializers/root_serializer.rb +0 -11
- data/templates/config/initializers/middleware.rb +6 -0
- data/templates/spec/spec_helper.rb +4 -1
- data/upgrades/3.0.0.tar.gz +0 -0
- data.tar.gz.sig +0 -0
- metadata +19 -22
- metadata.gz.sig +0 -0
- data/lib/shaf/api_doc/comment.rb +0 -27
- data/lib/shaf/api_doc/document.rb +0 -137
- data/lib/shaf/api_doc/link_relations.rb +0 -77
- data/lib/shaf/middleware.rb +0 -1
- data/lib/shaf/tasks/api_doc_task.rb +0 -146
data/lib/shaf/formable.rb
CHANGED
@@ -3,43 +3,30 @@ require 'shaf/formable/builder'
|
|
3
3
|
module Shaf
|
4
4
|
module Formable
|
5
5
|
def self.add_class_reader(clazz, name, form)
|
6
|
-
clazz.define_singleton_method(name) { form }
|
6
|
+
clazz.define_singleton_method(name) { form.dup }
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.add_instance_reader(clazz, name, form, prefill)
|
10
10
|
clazz.define_method(name) do
|
11
|
-
form.tap do |f|
|
11
|
+
form.dup.tap do |f|
|
12
12
|
f.resource = self
|
13
13
|
f.fill! if prefill
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
# Deprecated legacy way of specifying forms inside models
|
19
|
-
def form(&block)
|
20
|
-
forms_for(self, &block)
|
21
|
-
|
22
|
-
Shaf.log.info <<~MSG
|
23
|
-
|
24
|
-
|
25
|
-
DEPRECATED method ::form in #{self}
|
26
|
-
Declare forms in a separate class extending Shaf::Formable with the class method forms_for!
|
27
|
-
MSG
|
28
|
-
end
|
29
|
-
|
30
|
-
# New way of writing forms in a separate class/file
|
31
18
|
def forms_for(clazz, &block)
|
32
19
|
builder = Formable::Builder.new(&block)
|
33
|
-
builder.forms.each do |
|
34
|
-
|
35
|
-
|
20
|
+
builder.forms.each do |form_wrapper|
|
21
|
+
method_name = form_wrapper.method_name
|
22
|
+
next unless method_name
|
36
23
|
|
37
|
-
|
24
|
+
form = form_wrapper.form
|
38
25
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
26
|
+
Formable.add_class_reader(clazz, method_name, form)
|
27
|
+
next unless form_wrapper.instance_accessor?
|
28
|
+
|
29
|
+
Formable.add_instance_reader(clazz, method_name, form, form_wrapper.prefill?)
|
43
30
|
end
|
44
31
|
end
|
45
32
|
alias form_for forms_for
|
data/lib/shaf/generator/base.rb
CHANGED
@@ -23,6 +23,10 @@ module Shaf
|
|
23
23
|
@usage = str || block
|
24
24
|
end
|
25
25
|
|
26
|
+
def identified_by
|
27
|
+
@identifiers
|
28
|
+
end
|
29
|
+
|
26
30
|
def options(option_parser, options); end
|
27
31
|
end
|
28
32
|
|
@@ -33,6 +37,60 @@ module Shaf
|
|
33
37
|
|
34
38
|
def call; end
|
35
39
|
|
40
|
+
def identifier
|
41
|
+
self.class.identified_by
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def params
|
47
|
+
args[1..-1].map { |param| param.split(':')}
|
48
|
+
end
|
49
|
+
|
50
|
+
def name_arg
|
51
|
+
n = args.first || ''
|
52
|
+
return n unless n.empty?
|
53
|
+
raise Command::ArgumentError,
|
54
|
+
"Please provide a name when using the #{identifier} generator!"
|
55
|
+
end
|
56
|
+
|
57
|
+
def name
|
58
|
+
name_arg.split('/', 2).last
|
59
|
+
end
|
60
|
+
|
61
|
+
def model_class_name
|
62
|
+
Utils.model_name(name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def plural_name
|
66
|
+
Utils.pluralize(name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def resource_name
|
70
|
+
[namespace, name].compact.join('_')
|
71
|
+
end
|
72
|
+
|
73
|
+
def collection_name
|
74
|
+
[namespace, plural_name].compact.join('_')
|
75
|
+
end
|
76
|
+
|
77
|
+
def namespace
|
78
|
+
names = name_arg.split('/')
|
79
|
+
return if names.size == 1
|
80
|
+
|
81
|
+
warn "Only a single namespaces is allowed: #{name_arg}" if names.size > 2
|
82
|
+
|
83
|
+
names.first
|
84
|
+
end
|
85
|
+
|
86
|
+
def module_name
|
87
|
+
Utils.model_name(namespace) if namespace
|
88
|
+
end
|
89
|
+
|
90
|
+
def target(directory: target_dir, ns: namespace, name: target_name)
|
91
|
+
File.join(*[directory, ns, name].compact)
|
92
|
+
end
|
93
|
+
|
36
94
|
def template_dir
|
37
95
|
File.expand_path('templates', __dir__)
|
38
96
|
end
|
@@ -56,6 +114,30 @@ module Shaf
|
|
56
114
|
raise
|
57
115
|
end
|
58
116
|
|
117
|
+
def wrap_in_module(content, module_name, search: nil)
|
118
|
+
return content if module_name.nil? || module_name.empty?
|
119
|
+
|
120
|
+
indentation = ' '
|
121
|
+
search ||= '(class|module) \w'
|
122
|
+
lines = []
|
123
|
+
added = false
|
124
|
+
|
125
|
+
content.split("\n").each do |line|
|
126
|
+
unless added
|
127
|
+
if m = line.match(/\A(\s*)#{search}/)
|
128
|
+
lines << "#{m[1]}module #{module_name}"
|
129
|
+
added = true
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
line.prepend(indentation) if added
|
134
|
+
lines << line
|
135
|
+
end
|
136
|
+
|
137
|
+
lines << 'end' if added
|
138
|
+
lines.join("\n")
|
139
|
+
end
|
140
|
+
|
59
141
|
def write_output(file, content)
|
60
142
|
FileTransactions::CreateFileCommand.execute(file) { content }
|
61
143
|
puts "Added: #{file}"
|
@@ -13,24 +13,7 @@ module Shaf
|
|
13
13
|
add_link_to_root
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
args[1..-1].map { |param| param.split(':')}
|
18
|
-
end
|
19
|
-
|
20
|
-
def name
|
21
|
-
n = args.first || ''
|
22
|
-
return n unless n.empty?
|
23
|
-
raise Command::ArgumentError,
|
24
|
-
'Please provide a controller name when using the controller generator!'
|
25
|
-
end
|
26
|
-
|
27
|
-
def model_class_name
|
28
|
-
Utils.model_name(name)
|
29
|
-
end
|
30
|
-
|
31
|
-
def plural_name
|
32
|
-
Utils.pluralize(name)
|
33
|
-
end
|
16
|
+
private
|
34
17
|
|
35
18
|
def pluralized_model_name
|
36
19
|
Utils.pluralize(model_class_name)
|
@@ -44,21 +27,31 @@ module Shaf
|
|
44
27
|
'spec/integration_spec.rb'
|
45
28
|
end
|
46
29
|
|
47
|
-
def
|
48
|
-
|
30
|
+
def target_dir
|
31
|
+
'api/controllers'
|
32
|
+
end
|
33
|
+
|
34
|
+
def target_name
|
35
|
+
"#{plural_name}_controller.rb"
|
49
36
|
end
|
50
37
|
|
51
38
|
def spec_target
|
52
|
-
|
39
|
+
target(directory: 'spec/integration', name: "#{plural_name}_controller_spec.rb")
|
40
|
+
end
|
41
|
+
|
42
|
+
def policy_file
|
43
|
+
File.join(['policies', namespace, "#{name}_policy"].compact)
|
53
44
|
end
|
54
45
|
|
55
46
|
def create_controller
|
56
47
|
content = render(template, opts)
|
48
|
+
content = wrap_in_module(content, module_name)
|
57
49
|
write_output(target, content)
|
58
50
|
end
|
59
51
|
|
60
52
|
def create_integration_spec
|
61
53
|
content = render(spec_template, opts)
|
54
|
+
content = wrap_in_module(content, module_name, search: "describe #{model_class_name}")
|
62
55
|
write_output(spec_target, content)
|
63
56
|
end
|
64
57
|
|
@@ -66,11 +59,14 @@ module Shaf
|
|
66
59
|
{
|
67
60
|
name: name,
|
68
61
|
plural_name: plural_name,
|
62
|
+
resource_name: resource_name,
|
63
|
+
collection_name: collection_name,
|
69
64
|
serializer_class_name: "#{model_class_name}Serializer",
|
70
65
|
model_class_name: model_class_name,
|
71
66
|
controller_class_name: "#{pluralized_model_name}Controller",
|
72
67
|
policy_class_name: "#{model_class_name}Policy",
|
73
|
-
policy_file:
|
68
|
+
policy_file: policy_file,
|
69
|
+
namespace: namespace,
|
74
70
|
params: params
|
75
71
|
}
|
76
72
|
end
|
@@ -97,19 +93,7 @@ module Shaf
|
|
97
93
|
end
|
98
94
|
|
99
95
|
def link_content(indentation = '')
|
100
|
-
|
101
|
-
|
102
|
-
# Auto generated doc:
|
103
|
-
# Link to the collection of #{plural_name}.
|
104
|
-
# Method: GET
|
105
|
-
# Example:
|
106
|
-
# ```
|
107
|
-
# curl -H "Accept: application/hal+json" \\
|
108
|
-
# -H "Authorization: abcdef" \\
|
109
|
-
# /#{plural_name}
|
110
|
-
#```
|
111
|
-
link :#{plural_name}, #{plural_name}_uri
|
112
|
-
DOC
|
96
|
+
"#{indentation}link :#{plural_name}, #{collection_name}_uri"
|
113
97
|
end
|
114
98
|
end
|
115
99
|
end
|
data/lib/shaf/generator/forms.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Shaf
|
2
4
|
module Generator
|
3
5
|
class Forms < Base
|
@@ -8,17 +10,6 @@ module Shaf
|
|
8
10
|
create_forms
|
9
11
|
end
|
10
12
|
|
11
|
-
def model_name
|
12
|
-
n = args.first || ''
|
13
|
-
return n unless n.empty?
|
14
|
-
raise Command::ArgumentError,
|
15
|
-
'Please provide a model name when using the forms generator!'
|
16
|
-
end
|
17
|
-
|
18
|
-
def model_class_name
|
19
|
-
Utils.model_name(model_name)
|
20
|
-
end
|
21
|
-
|
22
13
|
def class_name
|
23
14
|
"#{model_class_name}Forms"
|
24
15
|
end
|
@@ -27,19 +18,24 @@ module Shaf
|
|
27
18
|
'api/forms.rb'
|
28
19
|
end
|
29
20
|
|
30
|
-
def
|
31
|
-
|
21
|
+
def target_dir
|
22
|
+
'api/forms'
|
23
|
+
end
|
24
|
+
|
25
|
+
def target_name
|
26
|
+
"#{name}_forms.rb"
|
32
27
|
end
|
33
28
|
|
34
29
|
def create_forms
|
35
30
|
content = render(template, opts)
|
31
|
+
content = wrap_in_module(content, module_name)
|
36
32
|
# FIXME: Append if file exists!
|
37
33
|
write_output(target, content)
|
38
34
|
end
|
39
35
|
|
40
36
|
def opts
|
41
37
|
{
|
42
|
-
model_name:
|
38
|
+
model_name: name,
|
43
39
|
class_name: class_name,
|
44
40
|
model_class_name: model_class_name,
|
45
41
|
fields: fields
|
@@ -19,6 +19,10 @@ module Shaf
|
|
19
19
|
def usage(str = nil, &block)
|
20
20
|
@usage = str || block
|
21
21
|
end
|
22
|
+
|
23
|
+
def identified_by
|
24
|
+
@identifiers
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
def initialize(*args, **options)
|
@@ -35,6 +39,10 @@ module Shaf
|
|
35
39
|
raise Command::ArgumentError, e.message
|
36
40
|
end
|
37
41
|
|
42
|
+
def table_name
|
43
|
+
(args.first || '').tr('/', '_')
|
44
|
+
end
|
45
|
+
|
38
46
|
def add_change(change)
|
39
47
|
@changes ||= []
|
40
48
|
@changes << change if change
|
data/lib/shaf/generator/model.rb
CHANGED
@@ -5,44 +5,59 @@ module Shaf
|
|
5
5
|
identifier :model
|
6
6
|
usage 'generate model MODEL_NAME [attribute:type] [..]'
|
7
7
|
|
8
|
+
def self.options(parser, options)
|
9
|
+
parser.on("--skip-model", "don't generate model or migration") do |s|
|
10
|
+
options[:skip_model] = s
|
11
|
+
end
|
12
|
+
|
13
|
+
parser.on("--skip-migration", "don't generate a migration") do |s|
|
14
|
+
options[:skip_migration] = s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
8
18
|
def call
|
9
|
-
create_model
|
10
|
-
create_migration
|
19
|
+
create_model unless skip_model?
|
20
|
+
create_migration unless skip_migration?
|
11
21
|
create_serializer
|
12
22
|
create_forms
|
13
23
|
end
|
14
24
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
'Please provide a model name when using the model generator!'
|
25
|
+
private
|
26
|
+
|
27
|
+
def skip_model?
|
28
|
+
options[:skip_model]
|
20
29
|
end
|
21
30
|
|
22
|
-
def
|
23
|
-
|
31
|
+
def skip_migration?
|
32
|
+
options[:skip_migration] || skip_model?
|
24
33
|
end
|
25
34
|
|
26
35
|
def table_name
|
27
|
-
Utils.pluralize
|
36
|
+
Utils.pluralize name_arg
|
28
37
|
end
|
29
38
|
|
30
39
|
def template
|
31
40
|
'api/model.rb'
|
32
41
|
end
|
33
42
|
|
34
|
-
def
|
35
|
-
|
43
|
+
def target_dir
|
44
|
+
'api/models'
|
45
|
+
end
|
46
|
+
|
47
|
+
def target_name
|
48
|
+
"#{name}.rb"
|
36
49
|
end
|
37
50
|
|
38
51
|
def create_model
|
39
52
|
content = render(template, opts)
|
53
|
+
content = wrap_in_module(content, module_name)
|
40
54
|
write_output(target, content)
|
41
55
|
end
|
42
56
|
|
43
57
|
def opts
|
44
58
|
{
|
45
59
|
class_name: model_class_name,
|
60
|
+
table_name: [namespace, plural_name].compact.join('_')
|
46
61
|
}
|
47
62
|
end
|
48
63
|
|
@@ -52,12 +67,12 @@ module Shaf
|
|
52
67
|
end
|
53
68
|
|
54
69
|
def create_serializer
|
55
|
-
serializer_args = %W(serializer #{
|
70
|
+
serializer_args = %W(serializer #{name_arg}) + args[1..-1]
|
56
71
|
Generator::Factory.create(*serializer_args, **options).call
|
57
72
|
end
|
58
73
|
|
59
74
|
def create_forms
|
60
|
-
form_args = %W(forms #{
|
75
|
+
form_args = %W(forms #{name_arg}) + args[1..-1]
|
61
76
|
Generator::Factory.create(*form_args, **options).call
|
62
77
|
end
|
63
78
|
end
|
@@ -8,27 +8,21 @@ module Shaf
|
|
8
8
|
create_policy
|
9
9
|
end
|
10
10
|
|
11
|
-
def policy_name
|
12
|
-
n = args.first || ""
|
13
|
-
return n unless n.empty?
|
14
|
-
raise Command::ArgumentError,
|
15
|
-
"Please provide a policy name when using the policy generator!"
|
16
|
-
end
|
17
|
-
|
18
|
-
def model_class_name
|
19
|
-
Utils::model_name(policy_name)
|
20
|
-
end
|
21
|
-
|
22
11
|
def template
|
23
12
|
'api/policy.rb'
|
24
13
|
end
|
25
14
|
|
26
|
-
def
|
27
|
-
|
15
|
+
def target_dir
|
16
|
+
'api/policies'
|
17
|
+
end
|
18
|
+
|
19
|
+
def target_name
|
20
|
+
"#{name}_policy.rb"
|
28
21
|
end
|
29
22
|
|
30
23
|
def create_policy
|
31
24
|
content = render(template, opts)
|
25
|
+
content = wrap_in_module(content, module_name)
|
32
26
|
write_output(target, content)
|
33
27
|
end
|
34
28
|
|
@@ -39,7 +33,7 @@ module Shaf
|
|
39
33
|
def opts
|
40
34
|
{
|
41
35
|
policy_class_name: "#{model_class_name}Policy",
|
42
|
-
name:
|
36
|
+
name: name,
|
43
37
|
attributes: attributes,
|
44
38
|
}
|
45
39
|
end
|
@@ -8,23 +8,16 @@ module Shaf
|
|
8
8
|
create_profile
|
9
9
|
end
|
10
10
|
|
11
|
-
def profile_name
|
12
|
-
n = args.first || ""
|
13
|
-
return n unless n.empty?
|
14
|
-
raise Command::ArgumentError,
|
15
|
-
"Please provide a profile name when using the profile generator!"
|
16
|
-
end
|
17
|
-
|
18
|
-
def model_class_name
|
19
|
-
Utils::model_name(profile_name)
|
20
|
-
end
|
21
|
-
|
22
11
|
def template
|
23
12
|
'api/profile.rb'
|
24
13
|
end
|
25
14
|
|
26
|
-
def
|
27
|
-
|
15
|
+
def target_dir
|
16
|
+
'api/profiles'
|
17
|
+
end
|
18
|
+
|
19
|
+
def target_name
|
20
|
+
"#{name}.rb"
|
28
21
|
end
|
29
22
|
|
30
23
|
def attributes
|
@@ -37,14 +30,16 @@ module Shaf
|
|
37
30
|
|
38
31
|
def create_profile
|
39
32
|
content = render(template, opts)
|
33
|
+
content = wrap_in_module(content, module_name, search: 'class \w')
|
40
34
|
write_output(target, content)
|
41
35
|
end
|
42
36
|
|
43
37
|
def opts
|
44
38
|
{
|
45
|
-
profile_name:
|
39
|
+
profile_name: name,
|
46
40
|
profile_class_name: "#{model_class_name}",
|
47
41
|
attributes: attributes,
|
42
|
+
resource_name: resource_name,
|
48
43
|
}
|
49
44
|
end
|
50
45
|
end
|
@@ -6,21 +6,18 @@ module Shaf
|
|
6
6
|
usage 'generate scaffold RESOURCE_NAME [attribute:type] [..]'
|
7
7
|
|
8
8
|
def call
|
9
|
-
|
10
|
-
raise "Please provide a resource name when using the scaffold generator!"
|
11
|
-
end
|
9
|
+
check_name_arg!
|
12
10
|
|
13
11
|
options[:specs] = true if options[:specs].nil?
|
14
12
|
Generator::Factory.create('model', *args, **options).call
|
15
|
-
Generator::Factory.create('controller', *
|
13
|
+
Generator::Factory.create('controller', *args, **options).call
|
16
14
|
end
|
17
15
|
|
18
|
-
def
|
19
|
-
args.first
|
20
|
-
end
|
16
|
+
def check_name_arg!
|
17
|
+
return if args.first && !args.first.empty?
|
21
18
|
|
22
|
-
|
23
|
-
|
19
|
+
raise Command::ArgumentError,
|
20
|
+
"Please provide a name when using the scaffold generator!"
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|