shaf 1.6.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/iana_link_relations.csv.gz +0 -0
- data/lib/shaf/alps/attribute_serializer.rb +41 -0
- data/lib/shaf/alps/json_serializer.rb +50 -0
- data/lib/shaf/alps/relation_serializer.rb +70 -0
- data/lib/shaf/app.rb +32 -7
- data/lib/shaf/authenticator/base.rb +161 -0
- data/lib/shaf/authenticator/basic_auth.rb +25 -0
- data/lib/shaf/authenticator/challenge.rb +32 -0
- data/lib/shaf/authenticator/parameter.rb +31 -0
- data/lib/shaf/authenticator/request.rb +17 -0
- data/lib/shaf/authenticator.rb +56 -0
- data/lib/shaf/command/base.rb +4 -0
- data/lib/shaf/command/console.rb +1 -1
- data/lib/shaf/command/generate.rb +5 -2
- data/lib/shaf/command/new.rb +24 -7
- data/lib/shaf/command/server.rb +5 -1
- data/lib/shaf/command/templates/Gemfile.erb +1 -0
- data/{templates/config/settings.yml → lib/shaf/command/templates/config/settings.yml.erb} +9 -12
- data/lib/shaf/errors.rb +11 -0
- data/lib/shaf/extensions/api_routes.rb +60 -0
- data/lib/shaf/extensions/authorize.rb +11 -9
- data/lib/shaf/extensions/log.rb +1 -1
- data/lib/shaf/extensions/resource_uris.rb +95 -137
- data/lib/shaf/extensions/symbolic_routes.rb +9 -19
- data/lib/shaf/extensions.rb +3 -3
- data/lib/shaf/formable/builder.rb +58 -19
- data/lib/shaf/formable/form.rb +14 -11
- data/lib/shaf/formable.rb +10 -24
- data/lib/shaf/generator/base.rb +84 -3
- data/lib/shaf/generator/controller.rb +30 -42
- data/lib/shaf/generator/doc.rb +17 -0
- data/lib/shaf/generator/forms.rb +11 -14
- data/lib/shaf/generator/helper.rb +2 -1
- 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 +15 -3
- 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/migration/type.rb +4 -26
- data/lib/shaf/generator/migration/types.rb +45 -16
- data/lib/shaf/generator/model.rb +29 -15
- data/lib/shaf/generator/policy.rb +8 -14
- data/lib/shaf/generator/profile.rb +47 -0
- data/lib/shaf/generator/scaffold.rb +6 -9
- data/lib/shaf/generator/serializer.rb +64 -98
- 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/policy.rb.erb +2 -2
- data/lib/shaf/generator/templates/api/profile.rb.erb +16 -0
- data/lib/shaf/generator/templates/api/serializer.rb.erb +3 -3
- data/lib/shaf/generator/templates/spec/integration_spec.rb.erb +15 -16
- data/lib/shaf/generator/templates/spec/serializer_spec.rb.erb +5 -5
- data/lib/shaf/generator.rb +2 -0
- data/lib/shaf/helpers/authentication.rb +79 -0
- data/lib/shaf/helpers/paginate.rb +1 -1
- data/lib/shaf/helpers/payload.rb +14 -34
- data/lib/shaf/helpers/vary.rb +8 -0
- data/lib/shaf/helpers.rb +4 -0
- data/lib/shaf/logger.rb +12 -0
- data/lib/shaf/parser/base.rb +44 -0
- data/lib/shaf/parser/form_data.rb +15 -0
- data/lib/shaf/parser/json.rb +26 -0
- data/lib/shaf/parser.rb +65 -0
- data/lib/shaf/profile/attribute.rb +29 -0
- data/lib/shaf/profile/evaluator.rb +46 -0
- data/lib/shaf/profile/relation.rb +29 -0
- data/lib/shaf/profile/unique_id.rb +58 -0
- data/lib/shaf/profile.rb +115 -0
- data/lib/shaf/profiles/shaf_basic.rb +20 -0
- data/lib/shaf/profiles/shaf_error.rb +49 -0
- data/lib/shaf/profiles/shaf_form.rb +110 -0
- data/lib/shaf/profiles.rb +46 -0
- data/lib/shaf/registrable_factory.rb +62 -32
- data/lib/shaf/responder/alps_json.rb +25 -0
- data/lib/shaf/responder/base.rb +20 -17
- data/lib/shaf/responder/hal.rb +66 -5
- data/lib/shaf/responder/html.rb +43 -16
- data/lib/shaf/responder/problem_json.rb +2 -2
- data/lib/shaf/responder.rb +41 -2
- data/lib/shaf/router.rb +65 -12
- data/lib/shaf/serializer.rb +35 -0
- data/lib/shaf/settings.rb +25 -12
- data/lib/shaf/spec/authenticator.rb +13 -0
- data/lib/shaf/spec/base.rb +1 -1
- data/lib/shaf/spec/http_method_utils.rb +1 -1
- data/lib/shaf/spec/integration_spec.rb +26 -14
- data/lib/shaf/spec/payload_utils.rb +2 -2
- data/lib/shaf/spec.rb +1 -0
- data/lib/shaf/supported_http_methods.rb +15 -0
- data/lib/shaf/tasks/routes_task.rb +14 -17
- data/lib/shaf/tasks.rb +0 -1
- data/lib/shaf/upgrade/manifest.rb +11 -2
- data/lib/shaf/upgrade/package.rb +73 -45
- data/lib/shaf/upgrade/version.rb +11 -10
- data/lib/shaf/utils.rb +19 -5
- data/lib/shaf/version.rb +3 -1
- data/lib/shaf/yard/attribute_method_handler.rb +19 -0
- data/lib/shaf/yard/attribute_object.rb +30 -0
- data/lib/shaf/yard/base_method_handler.rb +30 -0
- data/lib/shaf/yard/link_method_handler.rb +39 -0
- data/lib/shaf/yard/link_object.rb +60 -0
- data/lib/shaf/yard/nested_attributes.rb +37 -0
- data/lib/shaf/yard/parser.rb +64 -0
- data/lib/shaf/yard/profile_method_handler.rb +51 -0
- data/lib/shaf/yard/profile_object.rb +21 -0
- data/lib/shaf/yard/resource_object.rb +55 -0
- data/lib/shaf/yard/serializer_handler.rb +27 -0
- data/lib/shaf/yard.rb +34 -0
- data/lib/shaf.rb +6 -0
- data/templates/Rakefile +0 -6
- data/templates/api/controllers/base_controller.rb +0 -12
- data/templates/api/controllers/docs_controller.rb +5 -3
- data/templates/api/controllers/root_controller.rb +7 -1
- data/templates/api/policies/base_policy.rb +2 -0
- data/templates/api/serializers/base_serializer.rb +1 -3
- data/templates/api/serializers/error_serializer.rb +1 -5
- data/templates/api/serializers/form_serializer.rb +1 -5
- data/templates/api/serializers/root_serializer.rb +0 -11
- data/templates/api/serializers/validation_error_serializer.rb +1 -5
- data/templates/config/bootstrap.rb +1 -2
- data/templates/config/directories.rb +52 -44
- data/templates/config/helpers.rb +1 -1
- data/templates/config/initializers/authentication.rb +18 -0
- data/templates/config/initializers/db_migrations.rb +2 -2
- data/templates/config/initializers/logging.rb +2 -2
- data/templates/config/initializers/middleware.rb +6 -0
- data/templates/config/initializers.rb +52 -8
- data/templates/config.ru +1 -1
- data/templates/spec/spec_helper.rb +5 -0
- data/upgrades/0.5.0.tar.gz +0 -0
- data/upgrades/1.0.4.tar.gz +0 -0
- data/upgrades/1.1.0.tar.gz +0 -0
- data/upgrades/1.6.1.tar.gz +0 -0
- data/upgrades/2.0.0.tar.gz +0 -0
- data/upgrades/3.0.0.tar.gz +0 -0
- data/yard_templates/api_doc/doc_index/html/body.erb +3 -0
- data/yard_templates/api_doc/doc_index/setup.rb +8 -0
- data/yard_templates/api_doc/html/css/api-doc.css +222 -0
- data/yard_templates/api_doc/html/favicon.ico +0 -0
- data/yard_templates/api_doc/html/js/switch_tab.js +17 -0
- data/yard_templates/api_doc/html/setup.rb +59 -0
- data/yard_templates/api_doc/layout/html/footer.erb +3 -0
- data/yard_templates/api_doc/layout/html/header.erb +7 -0
- data/yard_templates/api_doc/layout/html/layout.erb +13 -0
- data/yard_templates/api_doc/layout/setup.rb +24 -0
- data/yard_templates/api_doc/profile/html/attributes.erb +10 -0
- data/yard_templates/api_doc/profile/html/profile.erb +6 -0
- data/yard_templates/api_doc/profile/html/relations.erb +10 -0
- data/yard_templates/api_doc/profile/setup.rb +38 -0
- data/yard_templates/api_doc/profile_attribute/html/attribute.erb +23 -0
- data/yard_templates/api_doc/profile_attribute/setup.rb +21 -0
- data/yard_templates/api_doc/profile_relation/html/relation.erb +37 -0
- data/yard_templates/api_doc/profile_relation/setup.rb +41 -0
- data/yard_templates/api_doc/resource/html/attributes.erb +10 -0
- data/yard_templates/api_doc/resource/html/profile.erb +14 -0
- data/yard_templates/api_doc/resource/html/relations.erb +10 -0
- data/yard_templates/api_doc/resource/html/resource.erb +5 -0
- data/yard_templates/api_doc/resource/setup.rb +56 -0
- data/yard_templates/api_doc/resource_attribute/html/attribute.erb +23 -0
- data/yard_templates/api_doc/resource_attribute/setup.rb +20 -0
- data/yard_templates/api_doc/resource_relation/html/relation.erb +47 -0
- data/yard_templates/api_doc/resource_relation/setup.rb +80 -0
- data/yard_templates/api_doc/setup.rb +31 -0
- data/yard_templates/api_doc/sidebar/html/profile_list.erb +8 -0
- data/yard_templates/api_doc/sidebar/html/search.erb +7 -0
- data/yard_templates/api_doc/sidebar/html/serializer_list.erb +8 -0
- data/yard_templates/api_doc/sidebar/html/sidebar.erb +13 -0
- data/yard_templates/api_doc/sidebar/setup.rb +56 -0
- data.tar.gz.sig +2 -2
- metadata +143 -38
- 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/extensions/current_user.rb +0 -48
- data/lib/shaf/middleware.rb +0 -1
- data/lib/shaf/responder/hal_serializable.rb +0 -64
- data/lib/shaf/tasks/api_doc_task.rb +0 -125
@@ -1,11 +1,56 @@
|
|
1
|
+
require 'forwardable'
|
1
2
|
require 'shaf/formable/form'
|
3
|
+
require 'shaf/immutable_attr'
|
2
4
|
|
3
5
|
module Shaf
|
4
6
|
module Formable
|
5
7
|
class Builder
|
6
|
-
InstanceAccessorType = Struct.new(:prefill?)
|
7
8
|
DELEGATES = %i[title name action method type submit fields].freeze
|
8
9
|
|
10
|
+
class FormWrapper
|
11
|
+
extend Forwardable
|
12
|
+
extend Shaf::ImmutableAttr
|
13
|
+
|
14
|
+
attr_accessor :instance_accessor
|
15
|
+
immutable_reader :form
|
16
|
+
|
17
|
+
WRITER_DELEGATES = DELEGATES.map { |method| :"#{method}=" }
|
18
|
+
def_delegators :@form, :add_field, *WRITER_DELEGATES
|
19
|
+
|
20
|
+
def initialize(form, method_name: nil, instance_accessor: nil)
|
21
|
+
@form = form&.dup || Formable::Form.new
|
22
|
+
@method_name = method_name
|
23
|
+
@form.action = action_from(method_name) unless @form.action
|
24
|
+
@instance_accessor = instance_accessor
|
25
|
+
end
|
26
|
+
|
27
|
+
def action_from(method_name)
|
28
|
+
return unless method_name
|
29
|
+
|
30
|
+
(method_name.to_s.delete_suffix('_form')).to_sym
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_name
|
34
|
+
name = @method_name || form.action
|
35
|
+
|
36
|
+
if name.nil?
|
37
|
+
nil
|
38
|
+
elsif name.to_s.end_with? '_form'
|
39
|
+
name.to_sym
|
40
|
+
else
|
41
|
+
:"#{name}_form"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def instance_accessor?
|
46
|
+
[:empty, :prefill].include? instance_accessor
|
47
|
+
end
|
48
|
+
|
49
|
+
def prefill?
|
50
|
+
instance_accessor == :prefill
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
9
54
|
attr_reader :forms
|
10
55
|
|
11
56
|
def initialize(&block)
|
@@ -15,48 +60,42 @@ module Shaf
|
|
15
60
|
exec_with_form(block)
|
16
61
|
end
|
17
62
|
|
18
|
-
def instance_accessor_for(form)
|
19
|
-
@instance_accessors[form.action]
|
20
|
-
end
|
21
|
-
|
22
63
|
private
|
23
64
|
|
24
|
-
attr_reader :
|
65
|
+
attr_reader :current
|
25
66
|
|
26
|
-
def exec_with_form(block,
|
27
|
-
|
28
|
-
form.action = action if action
|
67
|
+
def exec_with_form(block, method_name: nil)
|
68
|
+
prev, @current = current, new_form(method_name)
|
29
69
|
instance_exec(&block)
|
30
70
|
ensure
|
31
|
-
@
|
71
|
+
@current = prev
|
32
72
|
end
|
33
73
|
|
34
|
-
def new_form
|
35
|
-
(form
|
74
|
+
def new_form(method_name)
|
75
|
+
FormWrapper.new(current&.form, method_name: method_name).tap { |f| @forms << f }
|
36
76
|
end
|
37
77
|
|
38
78
|
def instance_accessor(prefill: true)
|
39
|
-
|
40
|
-
@instance_accessors[form.action] = acc
|
79
|
+
current.instance_accessor = prefill ? :prefill : :empty
|
41
80
|
end
|
42
81
|
|
43
82
|
DELEGATES.each do |name|
|
44
83
|
define_method(name) do |arg|
|
45
|
-
|
84
|
+
current.send(:"#{name}=", arg)
|
46
85
|
end
|
47
86
|
end
|
48
87
|
|
49
88
|
def field(name, opts = {})
|
50
|
-
|
89
|
+
current.add_field(name, opts)
|
51
90
|
end
|
52
91
|
|
53
92
|
def method_missing(method, *args, &block)
|
54
93
|
return super unless args.empty? && block
|
55
|
-
exec_with_form(block,
|
94
|
+
exec_with_form(block, method_name: method)
|
56
95
|
end
|
57
96
|
|
58
|
-
def respond_to_missing?(
|
59
|
-
true
|
97
|
+
def respond_to_missing?(method, _include_private = false)
|
98
|
+
method.to_s.end_with?('_form') ? true : super
|
60
99
|
end
|
61
100
|
end
|
62
101
|
end
|
data/lib/shaf/formable/form.rb
CHANGED
@@ -12,14 +12,15 @@ module Shaf
|
|
12
12
|
DEFAULT_SUBMIT = 'save'.freeze
|
13
13
|
|
14
14
|
attr_accessor :resource
|
15
|
-
|
16
|
-
|
15
|
+
attr_writer :name, :action
|
16
|
+
immutable_accessor :title, :href, :type, :submit, :self_link
|
17
|
+
immutable_reader :fields
|
17
18
|
|
18
19
|
def initialize(params = {})
|
19
20
|
@title = params[:title]
|
20
21
|
@action = params[:action]
|
21
|
-
@name = params[:name]
|
22
|
-
@method = params[:method]
|
22
|
+
@name = params[:name]
|
23
|
+
@method = params[:method]
|
23
24
|
@type = params[:type] || DEFAULT_TYPE
|
24
25
|
@submit = params[:submit] || DEFAULT_SUBMIT
|
25
26
|
@fields = (params[:fields] || {}).map do |name, args|
|
@@ -27,23 +28,25 @@ module Shaf
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
31
|
+
def name
|
32
|
+
(@name || name_from(action))&.to_sym
|
33
|
+
end
|
34
|
+
|
30
35
|
def method=(http_method)
|
31
36
|
@method = http_method.to_s.upcase
|
32
37
|
end
|
33
38
|
|
34
39
|
def method
|
35
|
-
|
36
|
-
|
40
|
+
_method = @method || http_method_from(action)
|
41
|
+
_method.to_s.upcase if _method
|
37
42
|
end
|
38
43
|
|
39
44
|
def fields=(fields)
|
40
45
|
@fields = fields.map { |name, args| Field.new(name, args) }
|
41
46
|
end
|
42
47
|
|
43
|
-
def action
|
44
|
-
@action
|
45
|
-
@name ||= name_from action
|
46
|
-
@method ||= http_method_from action
|
48
|
+
def action
|
49
|
+
@action&.to_sym
|
47
50
|
end
|
48
51
|
|
49
52
|
def add_field(name, opts)
|
@@ -112,7 +115,7 @@ module Shaf
|
|
112
115
|
end
|
113
116
|
|
114
117
|
def submit_element
|
115
|
-
%Q(<div class="form--input-group"><input type="submit" class="button" value="
|
118
|
+
%Q(<div class="form--input-group"><input type="submit" class="button" value="#{submit}"</div>)
|
116
119
|
end
|
117
120
|
end
|
118
121
|
end
|
data/lib/shaf/formable.rb
CHANGED
@@ -3,44 +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
|
-
return unless defined? $logger
|
22
|
-
|
23
|
-
$logger.info <<~MSG
|
24
|
-
|
25
|
-
|
26
|
-
DEPRECATED method ::form in #{self}
|
27
|
-
Declare forms in a separate class extending Shaf::Formable with the class method forms_for!
|
28
|
-
MSG
|
29
|
-
end
|
30
|
-
|
31
|
-
# New way of writing forms in a separate class/file
|
32
18
|
def forms_for(clazz, &block)
|
33
19
|
builder = Formable::Builder.new(&block)
|
34
|
-
builder.forms.each do |
|
35
|
-
|
36
|
-
|
20
|
+
builder.forms.each do |form_wrapper|
|
21
|
+
method_name = form_wrapper.method_name
|
22
|
+
next unless method_name
|
37
23
|
|
38
|
-
|
24
|
+
form = form_wrapper.form
|
39
25
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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?)
|
44
30
|
end
|
45
31
|
end
|
46
32
|
alias form_for forms_for
|
data/lib/shaf/generator/base.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'fileutils'
|
4
4
|
require 'erb'
|
5
|
+
require 'file_transactions'
|
5
6
|
require 'shaf/generator/helper'
|
6
7
|
|
7
8
|
module Shaf
|
@@ -22,6 +23,10 @@ module Shaf
|
|
22
23
|
@usage = str || block
|
23
24
|
end
|
24
25
|
|
26
|
+
def identified_by
|
27
|
+
@identifiers
|
28
|
+
end
|
29
|
+
|
25
30
|
def options(option_parser, options); end
|
26
31
|
end
|
27
32
|
|
@@ -32,6 +37,60 @@ module Shaf
|
|
32
37
|
|
33
38
|
def call; end
|
34
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
|
+
|
35
94
|
def template_dir
|
36
95
|
File.expand_path('templates', __dir__)
|
37
96
|
end
|
@@ -55,10 +114,32 @@ module Shaf
|
|
55
114
|
raise
|
56
115
|
end
|
57
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
|
+
|
58
141
|
def write_output(file, content)
|
59
|
-
|
60
|
-
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
61
|
-
File.write(file, content)
|
142
|
+
FileTransactions::CreateFileCommand.execute(file) { content }
|
62
143
|
puts "Added: #{file}"
|
63
144
|
end
|
64
145
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'file_transactions'
|
2
|
+
|
1
3
|
module Shaf
|
2
4
|
module Generator
|
3
5
|
class Controller < Base
|
@@ -11,24 +13,7 @@ module Shaf
|
|
11
13
|
add_link_to_root
|
12
14
|
end
|
13
15
|
|
14
|
-
|
15
|
-
args[1..-1].map { |param| param.split(':')}
|
16
|
-
end
|
17
|
-
|
18
|
-
def name
|
19
|
-
n = args.first || ''
|
20
|
-
return n unless n.empty?
|
21
|
-
raise Command::ArgumentError,
|
22
|
-
'Please provide a controller name when using the controller generator!'
|
23
|
-
end
|
24
|
-
|
25
|
-
def model_class_name
|
26
|
-
Utils.model_name(name)
|
27
|
-
end
|
28
|
-
|
29
|
-
def plural_name
|
30
|
-
Utils.pluralize(name)
|
31
|
-
end
|
16
|
+
private
|
32
17
|
|
33
18
|
def pluralized_model_name
|
34
19
|
Utils.pluralize(model_class_name)
|
@@ -42,21 +27,31 @@ module Shaf
|
|
42
27
|
'spec/integration_spec.rb'
|
43
28
|
end
|
44
29
|
|
45
|
-
def
|
46
|
-
|
30
|
+
def target_dir
|
31
|
+
'api/controllers'
|
32
|
+
end
|
33
|
+
|
34
|
+
def target_name
|
35
|
+
"#{plural_name}_controller.rb"
|
47
36
|
end
|
48
37
|
|
49
38
|
def spec_target
|
50
|
-
|
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)
|
51
44
|
end
|
52
45
|
|
53
46
|
def create_controller
|
54
47
|
content = render(template, opts)
|
48
|
+
content = wrap_in_module(content, module_name)
|
55
49
|
write_output(target, content)
|
56
50
|
end
|
57
51
|
|
58
52
|
def create_integration_spec
|
59
53
|
content = render(spec_template, opts)
|
54
|
+
content = wrap_in_module(content, module_name, search: "describe #{model_class_name}")
|
60
55
|
write_output(spec_target, content)
|
61
56
|
end
|
62
57
|
|
@@ -64,11 +59,14 @@ module Shaf
|
|
64
59
|
{
|
65
60
|
name: name,
|
66
61
|
plural_name: plural_name,
|
62
|
+
resource_name: resource_name,
|
63
|
+
collection_name: collection_name,
|
67
64
|
serializer_class_name: "#{model_class_name}Serializer",
|
68
65
|
model_class_name: model_class_name,
|
69
66
|
controller_class_name: "#{pluralized_model_name}Controller",
|
70
67
|
policy_class_name: "#{model_class_name}Policy",
|
71
|
-
policy_file:
|
68
|
+
policy_file: policy_file,
|
69
|
+
namespace: namespace,
|
72
70
|
params: params
|
73
71
|
}
|
74
72
|
end
|
@@ -81,31 +79,21 @@ module Shaf
|
|
81
79
|
end
|
82
80
|
added = false
|
83
81
|
content = []
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
82
|
+
FileTransactions::ChangeFileCommand.execute(file) do
|
83
|
+
File.readlines(file).reverse_each do |line|
|
84
|
+
if match = !added && line.match(/^(\s*)link /)
|
85
|
+
content.unshift link_content(match[1].to_s)
|
86
|
+
added = true
|
87
|
+
end
|
88
|
+
content.unshift(line)
|
88
89
|
end
|
89
|
-
|
90
|
+
File.open(file, 'w') { |f| f.puts content }
|
91
|
+
puts "Modified: #{file}"
|
90
92
|
end
|
91
|
-
File.open(file, 'w') { |f| f.puts content }
|
92
|
-
puts "Modified: #{file}"
|
93
93
|
end
|
94
94
|
|
95
95
|
def link_content(indentation = '')
|
96
|
-
|
97
|
-
|
98
|
-
# Auto generated doc:
|
99
|
-
# Link to the collection of #{plural_name}.
|
100
|
-
# Method: GET
|
101
|
-
# Example:
|
102
|
-
# ```
|
103
|
-
# curl -H "Accept: application/hal+json" \\
|
104
|
-
# -H "Authorization: abcdef" \\
|
105
|
-
# /#{plural_name}
|
106
|
-
#```
|
107
|
-
link :#{plural_name}, #{plural_name}_uri
|
108
|
-
DOC
|
96
|
+
"#{indentation}link :#{plural_name}, #{collection_name}_uri"
|
109
97
|
end
|
110
98
|
end
|
111
99
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Shaf
|
4
|
+
module Generator
|
5
|
+
class Doc < Base
|
6
|
+
identifier %r{\Adoc(\b|umentation)\Z}
|
7
|
+
usage 'generate doc [SERIALIZER_NAME] [..]'
|
8
|
+
|
9
|
+
def call
|
10
|
+
require 'shaf/yard'
|
11
|
+
name = String(args[0]).strip
|
12
|
+
Shaf::Yard::Parser.call(name: name)
|
13
|
+
YARD::Templates::Engine.render(template: :api_doc, format: :html)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
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,18 +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)
|
32
|
+
# FIXME: Append if file exists!
|
36
33
|
write_output(target, content)
|
37
34
|
end
|
38
35
|
|
39
36
|
def opts
|
40
37
|
{
|
41
|
-
model_name:
|
38
|
+
model_name: name,
|
42
39
|
class_name: class_name,
|
43
40
|
model_class_name: model_class_name,
|
44
41
|
fields: fields
|
@@ -10,7 +10,8 @@ module Shaf
|
|
10
10
|
|
11
11
|
def print(lines, indent_level = 2)
|
12
12
|
strip_blank(lines).inject do |result, line|
|
13
|
-
|
13
|
+
indent = i(indent_level) unless line.empty?
|
14
|
+
result + "\n#{indent}#{line}"
|
14
15
|
end.chomp
|
15
16
|
end
|
16
17
|
|
@@ -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
|
@@ -42,9 +50,13 @@ module Shaf
|
|
42
50
|
|
43
51
|
def column_def(str, create: true)
|
44
52
|
_, col_type = str.split(':')
|
45
|
-
type =
|
46
|
-
|
47
|
-
|
53
|
+
type = Types.find(col_type)
|
54
|
+
return type.build(str, create: create, alter: !create) if type
|
55
|
+
|
56
|
+
raise <<~ERR
|
57
|
+
No supported DB column types for: #{col_type}
|
58
|
+
Supported types: #{Types.all.map(&:name).join(', ')}
|
59
|
+
ERR
|
48
60
|
end
|
49
61
|
|
50
62
|
def target(name)
|
@@ -4,34 +4,12 @@ module Shaf
|
|
4
4
|
class Type
|
5
5
|
attr_reader :name, :create_template, :alter_template, :validator
|
6
6
|
|
7
|
-
class << self
|
8
|
-
def add(name, **kwargs)
|
9
|
-
new(name, **kwargs).tap do |type|
|
10
|
-
types[type.name] = type
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def find(str)
|
15
|
-
name, _ = str.to_s.split(',', 2)
|
16
|
-
types[name.to_sym]
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def types
|
22
|
-
@types ||= {}
|
23
|
-
end
|
24
|
-
|
25
|
-
def clear
|
26
|
-
@types.clear if defined? @types
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
7
|
def initialize(str, create_template:, alter_template:, validator: nil)
|
31
8
|
@name = str.downcase.to_sym
|
32
|
-
@create_template = create_template
|
33
|
-
@alter_template = alter_template
|
34
|
-
@validator = validator
|
9
|
+
@create_template = create_template.freeze
|
10
|
+
@alter_template = alter_template.freeze
|
11
|
+
@validator = validator.freeze
|
12
|
+
freeze
|
35
13
|
end
|
36
14
|
|
37
15
|
def build(str, create: false, alter: false)
|