shaf 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/iana_link_relations.csv.gz +0 -0
  5. data/lib/shaf.rb +6 -0
  6. data/lib/shaf/alps/attribute_serializer.rb +41 -0
  7. data/lib/shaf/alps/json_serializer.rb +50 -0
  8. data/lib/shaf/alps/relation_serializer.rb +70 -0
  9. data/lib/shaf/api_doc/link_relations.rb +77 -0
  10. data/lib/shaf/app.rb +12 -5
  11. data/lib/shaf/authenticator.rb +56 -0
  12. data/lib/shaf/authenticator/base.rb +161 -0
  13. data/lib/shaf/authenticator/basic_auth.rb +25 -0
  14. data/lib/shaf/authenticator/challenge.rb +32 -0
  15. data/lib/shaf/authenticator/parameter.rb +31 -0
  16. data/lib/shaf/authenticator/request.rb +17 -0
  17. data/lib/shaf/command/console.rb +1 -1
  18. data/lib/shaf/command/generate.rb +5 -2
  19. data/lib/shaf/command/new.rb +20 -7
  20. data/lib/shaf/command/templates/Gemfile.erb +1 -0
  21. data/{templates/config/settings.yml → lib/shaf/command/templates/config/settings.yml.erb} +1 -5
  22. data/lib/shaf/errors.rb +11 -0
  23. data/lib/shaf/extensions.rb +3 -3
  24. data/lib/shaf/extensions/api_routes.rb +60 -0
  25. data/lib/shaf/extensions/authorize.rb +11 -9
  26. data/lib/shaf/extensions/log.rb +1 -1
  27. data/lib/shaf/extensions/resource_uris.rb +139 -63
  28. data/lib/shaf/extensions/symbolic_routes.rb +22 -19
  29. data/lib/shaf/formable.rb +1 -2
  30. data/lib/shaf/formable/form.rb +1 -1
  31. data/lib/shaf/generator.rb +2 -0
  32. data/lib/shaf/generator/base.rb +2 -3
  33. data/lib/shaf/generator/controller.rb +11 -7
  34. data/lib/shaf/generator/doc.rb +17 -0
  35. data/lib/shaf/generator/forms.rb +1 -0
  36. data/lib/shaf/generator/helper.rb +2 -1
  37. data/lib/shaf/generator/migration/base.rb +7 -3
  38. data/lib/shaf/generator/migration/type.rb +4 -26
  39. data/lib/shaf/generator/migration/types.rb +45 -16
  40. data/lib/shaf/generator/model.rb +1 -2
  41. data/lib/shaf/generator/profile.rb +52 -0
  42. data/lib/shaf/generator/serializer.rb +38 -73
  43. data/lib/shaf/generator/templates/api/policy.rb.erb +2 -2
  44. data/lib/shaf/generator/templates/api/profile.rb.erb +16 -0
  45. data/lib/shaf/generator/templates/api/serializer.rb.erb +2 -2
  46. data/lib/shaf/generator/templates/spec/integration_spec.rb.erb +1 -2
  47. data/lib/shaf/generator/templates/spec/serializer_spec.rb.erb +5 -5
  48. data/lib/shaf/helpers.rb +4 -0
  49. data/lib/shaf/helpers/authentication.rb +79 -0
  50. data/lib/shaf/helpers/cache_control.rb +1 -2
  51. data/lib/shaf/helpers/json_html.rb +58 -18
  52. data/lib/shaf/helpers/payload.rb +27 -41
  53. data/lib/shaf/helpers/vary.rb +8 -0
  54. data/lib/shaf/logger.rb +12 -0
  55. data/lib/shaf/parser.rb +65 -0
  56. data/lib/shaf/parser/base.rb +44 -0
  57. data/lib/shaf/parser/form_data.rb +15 -0
  58. data/lib/shaf/parser/json.rb +26 -0
  59. data/lib/shaf/profile.rb +110 -0
  60. data/lib/shaf/profile/attribute.rb +29 -0
  61. data/lib/shaf/profile/evaluator.rb +46 -0
  62. data/lib/shaf/profile/relation.rb +29 -0
  63. data/lib/shaf/profile/unique_id.rb +58 -0
  64. data/lib/shaf/profiles.rb +42 -0
  65. data/lib/shaf/profiles/shaf_basic.rb +20 -0
  66. data/lib/shaf/profiles/shaf_error.rb +48 -0
  67. data/lib/shaf/profiles/shaf_form.rb +109 -0
  68. data/lib/shaf/responder.rb +41 -2
  69. data/lib/shaf/responder/alps_json.rb +25 -0
  70. data/lib/shaf/responder/base.rb +20 -17
  71. data/lib/shaf/responder/hal.rb +62 -7
  72. data/lib/shaf/responder/html.rb +65 -9
  73. data/lib/shaf/responder/problem_json.rb +1 -1
  74. data/lib/shaf/serializer.rb +31 -0
  75. data/lib/shaf/settings.rb +25 -12
  76. data/lib/shaf/spec.rb +1 -0
  77. data/lib/shaf/spec/authenticator.rb +13 -0
  78. data/lib/shaf/spec/base.rb +1 -1
  79. data/lib/shaf/spec/http_method_utils.rb +1 -1
  80. data/lib/shaf/spec/integration_spec.rb +25 -13
  81. data/lib/shaf/spec/payload_utils.rb +2 -2
  82. data/lib/shaf/supported_http_methods.rb +15 -0
  83. data/lib/shaf/tasks/api_doc_task.rb +24 -3
  84. data/lib/shaf/tasks/routes_task.rb +14 -17
  85. data/lib/shaf/upgrade/manifest.rb +11 -2
  86. data/lib/shaf/upgrade/package.rb +78 -49
  87. data/lib/shaf/upgrade/version.rb +11 -10
  88. data/lib/shaf/utils.rb +19 -5
  89. data/lib/shaf/version.rb +3 -1
  90. data/lib/shaf/yard.rb +34 -0
  91. data/lib/shaf/yard/attribute_method_handler.rb +19 -0
  92. data/lib/shaf/yard/attribute_object.rb +30 -0
  93. data/lib/shaf/yard/base_method_handler.rb +30 -0
  94. data/lib/shaf/yard/link_method_handler.rb +39 -0
  95. data/lib/shaf/yard/link_object.rb +60 -0
  96. data/lib/shaf/yard/nested_attributes.rb +37 -0
  97. data/lib/shaf/yard/parser.rb +64 -0
  98. data/lib/shaf/yard/profile_method_handler.rb +51 -0
  99. data/lib/shaf/yard/profile_object.rb +21 -0
  100. data/lib/shaf/yard/resource_object.rb +55 -0
  101. data/lib/shaf/yard/serializer_handler.rb +27 -0
  102. data/templates/api/controllers/base_controller.rb +0 -10
  103. data/templates/api/controllers/docs_controller.rb +5 -3
  104. data/templates/api/controllers/root_controller.rb +7 -1
  105. data/templates/api/policies/base_policy.rb +2 -0
  106. data/templates/api/serializers/base_serializer.rb +1 -3
  107. data/templates/api/serializers/error_serializer.rb +1 -5
  108. data/templates/api/serializers/form_serializer.rb +1 -5
  109. data/templates/api/serializers/validation_error_serializer.rb +1 -5
  110. data/templates/config.ru +1 -1
  111. data/templates/config/bootstrap.rb +1 -2
  112. data/templates/config/directories.rb +52 -44
  113. data/templates/config/helpers.rb +1 -1
  114. data/templates/config/initializers.rb +52 -8
  115. data/templates/config/initializers/authentication.rb +18 -0
  116. data/templates/config/initializers/db_migrations.rb +2 -2
  117. data/templates/config/initializers/logging.rb +2 -2
  118. data/templates/frontend/assets/css/main.css +33 -1
  119. data/templates/frontend/views/headers.erb +20 -0
  120. data/templates/frontend/views/layout.erb +7 -1
  121. data/templates/frontend/views/payload.erb +1 -0
  122. data/templates/spec/spec_helper.rb +2 -0
  123. data/upgrades/0.5.0.tar.gz +0 -0
  124. data/upgrades/1.0.4.tar.gz +0 -0
  125. data/upgrades/1.1.0.tar.gz +0 -0
  126. data/upgrades/1.6.0.tar.gz +0 -0
  127. data/upgrades/1.6.1.tar.gz +0 -0
  128. data/upgrades/2.0.0.tar.gz +0 -0
  129. data/yard_templates/api_doc/doc_index/html/body.erb +3 -0
  130. data/yard_templates/api_doc/doc_index/setup.rb +8 -0
  131. data/yard_templates/api_doc/html/css/api-doc.css +222 -0
  132. data/yard_templates/api_doc/html/favicon.ico +0 -0
  133. data/yard_templates/api_doc/html/js/switch_tab.js +17 -0
  134. data/yard_templates/api_doc/html/setup.rb +59 -0
  135. data/yard_templates/api_doc/layout/html/footer.erb +3 -0
  136. data/yard_templates/api_doc/layout/html/header.erb +7 -0
  137. data/yard_templates/api_doc/layout/html/layout.erb +13 -0
  138. data/yard_templates/api_doc/layout/setup.rb +24 -0
  139. data/yard_templates/api_doc/profile/html/attributes.erb +10 -0
  140. data/yard_templates/api_doc/profile/html/profile.erb +6 -0
  141. data/yard_templates/api_doc/profile/html/relations.erb +10 -0
  142. data/yard_templates/api_doc/profile/setup.rb +38 -0
  143. data/yard_templates/api_doc/profile_attribute/html/attribute.erb +23 -0
  144. data/yard_templates/api_doc/profile_attribute/setup.rb +21 -0
  145. data/yard_templates/api_doc/profile_relation/html/relation.erb +37 -0
  146. data/yard_templates/api_doc/profile_relation/setup.rb +41 -0
  147. data/yard_templates/api_doc/resource/html/attributes.erb +10 -0
  148. data/yard_templates/api_doc/resource/html/profile.erb +14 -0
  149. data/yard_templates/api_doc/resource/html/relations.erb +10 -0
  150. data/yard_templates/api_doc/resource/html/resource.erb +5 -0
  151. data/yard_templates/api_doc/resource/setup.rb +56 -0
  152. data/yard_templates/api_doc/resource_attribute/html/attribute.erb +23 -0
  153. data/yard_templates/api_doc/resource_attribute/setup.rb +20 -0
  154. data/yard_templates/api_doc/resource_relation/html/relation.erb +47 -0
  155. data/yard_templates/api_doc/resource_relation/setup.rb +80 -0
  156. data/yard_templates/api_doc/setup.rb +31 -0
  157. data/yard_templates/api_doc/sidebar/html/profile_list.erb +8 -0
  158. data/yard_templates/api_doc/sidebar/html/search.erb +7 -0
  159. data/yard_templates/api_doc/sidebar/html/serializer_list.erb +8 -0
  160. data/yard_templates/api_doc/sidebar/html/sidebar.erb +13 -0
  161. data/yard_templates/api_doc/sidebar/setup.rb +56 -0
  162. metadata +140 -30
  163. metadata.gz.sig +1 -2
  164. data/lib/shaf/extensions/current_user.rb +0 -48
  165. data/lib/shaf/responder/hal_serializable.rb +0 -54
@@ -2,32 +2,35 @@ module Shaf
2
2
  module SymbolicRoutes
3
3
  class UriHelperNotRegisterdError < Error; end
4
4
 
5
- SUPPORTED_METHODS = [
6
- :get,
7
- :put,
8
- :post,
9
- :patch,
10
- :delete,
11
- :head,
12
- :options,
13
- :link,
14
- :unlink
15
- ].freeze
16
-
17
- SUPPORTED_METHODS.each do |m|
18
- define_method m do |path, collection: false, &block|
19
- super(rewrite_path(path, collection), &block)
5
+ Shaf::SUPPORTED_HTTP_METHODS.each do |m|
6
+ define_method m do |path, **options, &block|
7
+ collection = options.delete(:collection)
8
+ path = rewrite_path(path, collection, m)
9
+ super(path, **options, &block)
20
10
  end
21
11
  end
22
12
 
23
- def rewrite_path(path, collection = nil)
13
+ def rewrite_path(path, collection, method)
24
14
  return path unless path.is_a? Symbol
25
15
 
26
- m = "#{path}_template"
27
- return send(m, collection) if respond_to? m
16
+ warn <<~DEPRECATION unless collection.nil?
17
+ Deprecated use of declaring route with collection keyword argument:
18
+ Use `#{method} :#{path.to_s.sub(/_(path|uri)/, '_collection_path')} do`
19
+ instead of `#{method} :#{path}, collection: #{collection} do`
20
+ #{caller.find { |s| s.match?(/_controller.rb/) }}
21
+
22
+ DEPRECATION
23
+
24
+ method = "#{path}_template"
25
+ send_args = [method]
26
+ send_args << collection unless collection.nil?
27
+ return send(*send_args) if respond_to? method
28
+
29
+ method = "#{path}_path_template"
30
+ return send(*send_args) if respond_to? method
28
31
 
29
32
  raise UriHelperNotRegisterdError, <<~RUBY
30
- Undefined method '#{m}'. Did you forget to register a uri helper for #{path}?
33
+ Undefined method '#{method}'. Did you forget to register a uri helper for #{path}?
31
34
  RUBY
32
35
  end
33
36
  end
data/lib/shaf/formable.rb CHANGED
@@ -18,9 +18,8 @@ module Shaf
18
18
  # Deprecated legacy way of specifying forms inside models
19
19
  def form(&block)
20
20
  forms_for(self, &block)
21
- return unless defined? $logger
22
21
 
23
- $logger.info <<~MSG
22
+ Shaf.log.info <<~MSG
24
23
 
25
24
 
26
25
  DEPRECATED method ::form in #{self}
@@ -112,7 +112,7 @@ module Shaf
112
112
  end
113
113
 
114
114
  def submit_element
115
- %Q(<div class="form--input-group"><input type="submit" class="button" value="Submit"</div>)
115
+ %Q(<div class="form--input-group"><input type="submit" class="button" value="#{submit}"</div>)
116
116
  end
117
117
  end
118
118
  end
@@ -10,9 +10,11 @@ end
10
10
 
11
11
  require 'shaf/generator/base'
12
12
  require 'shaf/generator/controller'
13
+ require 'shaf/generator/doc'
13
14
  require 'shaf/generator/forms'
14
15
  require 'shaf/generator/migration'
15
16
  require 'shaf/generator/model'
16
17
  require 'shaf/generator/policy'
17
18
  require 'shaf/generator/scaffold'
18
19
  require 'shaf/generator/serializer'
20
+ require 'shaf/generator/profile'
@@ -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
@@ -56,9 +57,7 @@ module Shaf
56
57
  end
57
58
 
58
59
  def write_output(file, content)
59
- dir = File.dirname(file)
60
- FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
61
- File.write(file, content)
60
+ FileTransactions::CreateFileCommand.execute(file) { content }
62
61
  puts "Added: #{file}"
63
62
  end
64
63
  end
@@ -1,3 +1,5 @@
1
+ require 'file_transactions'
2
+
1
3
  module Shaf
2
4
  module Generator
3
5
  class Controller < Base
@@ -81,15 +83,17 @@ module Shaf
81
83
  end
82
84
  added = false
83
85
  content = []
84
- File.readlines(file).reverse_each do |line|
85
- if match = !added && line.match(/^(\s*)link /)
86
- content.unshift link_content(match[1].to_s)
87
- added = true
86
+ FileTransactions::ChangeFileCommand.execute(file) do
87
+ File.readlines(file).reverse_each do |line|
88
+ if match = !added && line.match(/^(\s*)link /)
89
+ content.unshift link_content(match[1].to_s)
90
+ added = true
91
+ end
92
+ content.unshift(line)
88
93
  end
89
- content.unshift(line)
94
+ File.open(file, 'w') { |f| f.puts content }
95
+ puts "Modified: #{file}"
90
96
  end
91
- File.open(file, 'w') { |f| f.puts content }
92
- puts "Modified: #{file}"
93
97
  end
94
98
 
95
99
  def link_content(indentation = '')
@@ -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
@@ -33,6 +33,7 @@ module Shaf
33
33
 
34
34
  def create_forms
35
35
  content = render(template, opts)
36
+ # FIXME: Append if file exists!
36
37
  write_output(target, content)
37
38
  end
38
39
 
@@ -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
- result + "\n#{i(indent_level) unless line.empty?}#{line}"
13
+ indent = i(indent_level) unless line.empty?
14
+ result + "\n#{indent}#{line}"
14
15
  end.chomp
15
16
  end
16
17
 
@@ -42,9 +42,13 @@ module Shaf
42
42
 
43
43
  def column_def(str, create: true)
44
44
  _, col_type = str.split(':')
45
- type = Type.find(col_type)
46
- raise "No supported DB column types for: #{col_type}" unless type
47
- type.build(str, create: create, alter: !create)
45
+ type = Types.find(col_type)
46
+ return type.build(str, create: create, alter: !create) if type
47
+
48
+ raise <<~ERR
49
+ No supported DB column types for: #{col_type}
50
+ Supported types: #{Types.all.map(&:name).join(', ')}
51
+ ERR
48
52
  end
49
53
 
50
54
  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)
@@ -3,22 +3,51 @@ require 'shaf/generator/migration/type'
3
3
  module Shaf
4
4
  module Generator
5
5
  module Migration
6
- Type.add :integer, create_template: 'Integer :%s', alter_template: 'add_column :%s, Integer'
7
- Type.add :varchar, create_template: 'String %s', alter_template: 'add_column :%s, String'
8
- Type.add :string, create_template: 'String :%s', alter_template: 'add_column :%s, String'
9
- Type.add :text, create_template: 'String :%s, text: true', alter_template: 'add_column :%s, String, text: true'
10
- Type.add :blob, create_template: 'File :%s', alter_template: 'add_column :%s, File'
11
- Type.add :bigint, create_template: 'Bignum :%s', alter_template: 'add_column :%s, Bignum'
12
- Type.add :double, create_template: 'Float :%s', alter_template: 'add_column :%s, Float'
13
- Type.add :numeric, create_template: 'BigDecimal :%s', alter_template: 'add_column :%s, BigDecimal'
14
- Type.add :date, create_template: 'Date :%s', alter_template: 'add_column :%s, Date'
15
- Type.add :timestamp, create_template: 'DateTime :%s', alter_template: 'add_column :%s, DateTime'
16
- Type.add :time, create_template: 'Time :%s', alter_template: 'add_column :%s, Time'
17
- Type.add :bool, create_template: 'TrueClass :%s', alter_template: 'add_column :%s, TrueClass'
18
- Type.add :boolean, create_template: 'TrueClass :%s', alter_template: 'add_column :%s, TrueClass'
19
- Type.add :index, create_template: 'index :%s, unique: true', alter_template: 'add_index :%s'
20
-
21
- Type.add :foreign_key,
6
+ module Types
7
+ class << self
8
+ def add(name, **kwargs)
9
+ Type.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
+ def all
20
+ types.values
21
+ end
22
+
23
+ private
24
+
25
+ def types
26
+ @types ||= {}
27
+ end
28
+
29
+ def clear
30
+ @types.clear if defined? @types
31
+ end
32
+ end
33
+ end
34
+
35
+ Types.add :integer, create_template: 'Integer :%s', alter_template: 'add_column :%s, Integer'
36
+ Types.add :varchar, create_template: 'String %s', alter_template: 'add_column :%s, String'
37
+ Types.add :string, create_template: 'String :%s', alter_template: 'add_column :%s, String'
38
+ Types.add :text, create_template: 'String :%s, text: true', alter_template: 'add_column :%s, String, text: true'
39
+ Types.add :blob, create_template: 'File :%s', alter_template: 'add_column :%s, File'
40
+ Types.add :bigint, create_template: 'Bignum :%s', alter_template: 'add_column :%s, Bignum'
41
+ Types.add :double, create_template: 'Float :%s', alter_template: 'add_column :%s, Float'
42
+ Types.add :numeric, create_template: 'BigDecimal :%s', alter_template: 'add_column :%s, BigDecimal'
43
+ Types.add :date, create_template: 'Date :%s', alter_template: 'add_column :%s, Date'
44
+ Types.add :timestamp, create_template: 'DateTime :%s', alter_template: 'add_column :%s, DateTime'
45
+ Types.add :time, create_template: 'Time :%s', alter_template: 'add_column :%s, Time'
46
+ Types.add :bool, create_template: 'TrueClass :%s', alter_template: 'add_column :%s, TrueClass'
47
+ Types.add :boolean, create_template: 'TrueClass :%s', alter_template: 'add_column :%s, TrueClass'
48
+ Types.add :index, create_template: 'index :%s, unique: true', alter_template: 'add_index :%s'
49
+
50
+ Types.add :foreign_key,
22
51
  create_template: 'foreign_key :%s, :%s',
23
52
  alter_template: 'add_foreign_key :%s, :%s',
24
53
  validator: ->(type, *args) {
@@ -52,8 +52,7 @@ module Shaf
52
52
  end
53
53
 
54
54
  def create_serializer
55
- serializer_args = %W(serializer #{model_name})
56
- serializer_args += args[1..-1].map { |arg| arg.split(':').first }
55
+ serializer_args = %W(serializer #{model_name}) + args[1..-1]
57
56
  Generator::Factory.create(*serializer_args, **options).call
58
57
  end
59
58
 
@@ -0,0 +1,52 @@
1
+ module Shaf
2
+ module Generator
3
+ class Profile < Base
4
+ identifier :profile
5
+ usage 'generate profile NAME [attribute:type] [..]'
6
+
7
+ def call
8
+ create_profile
9
+ end
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
+ def template
23
+ 'api/profile.rb'
24
+ end
25
+
26
+ def target
27
+ "api/profiles/#{profile_name}.rb"
28
+ end
29
+
30
+ def attributes
31
+ args[1..-1].map do |attr|
32
+ name, type = attr.split(':')
33
+ type ||= 'String'
34
+ [name, type.capitalize]
35
+ end
36
+ end
37
+
38
+ def create_profile
39
+ content = render(template, opts)
40
+ write_output(target, content)
41
+ end
42
+
43
+ def opts
44
+ {
45
+ profile_name: profile_name,
46
+ profile_class_name: "#{model_class_name}",
47
+ attributes: attributes,
48
+ }
49
+ end
50
+ end
51
+ end
52
+ end
@@ -2,12 +2,13 @@ module Shaf
2
2
  module Generator
3
3
  class Serializer < Base
4
4
  identifier :serializer
5
- usage 'generate serializer MODEL_NAME [attribute] [..]'
5
+ usage 'generate serializer MODEL_NAME [attribute[:type]] [..]'
6
6
 
7
7
  def call
8
8
  create_serializer
9
9
  create_serializer_spec if options[:specs]
10
10
  create_policy
11
+ create_profile
11
12
  end
12
13
 
13
14
  def name
@@ -56,40 +57,33 @@ module Shaf
56
57
  end
57
58
 
58
59
  def attributes
59
- args[1..-1].map { |attr| ":#{attr}" }
60
+ args[1..-1]
61
+ end
62
+
63
+ def attribute_names
64
+ attributes.map { |arg| arg.split(':').first }
60
65
  end
61
66
 
62
67
  def attributes_with_doc
63
- attributes.map do |attr|
64
- [
65
- "# FIXME: Write documentation for attribute #{attr}",
66
- "attribute #{attr}"
67
- ]
68
- end
68
+ attribute_names.map { |attr| ["attribute :#{attr}"] }
69
69
  end
70
70
 
71
- def links
71
+ def link_relations
72
72
  %w(collection self edit-form doc:delete)
73
73
  end
74
74
 
75
- def curies_with_doc
76
- [
77
- <<~EOS.split("\n")
78
- # Auto generated doc:
79
- # Link to the documentation for a given relation of the #{name} resource.
80
- # This link is templated, which means that {rel} must be replaced by the
81
- # appropriate relation name.
82
- # Method: GET
83
- # Example:
84
- # ```
85
- # curl -H "Accept: application/hal+json" \\
86
- # /doc/#{name}/rels/delete
87
- #```
88
- curie :doc do
89
- doc_curie_uri('#{name}')
90
- end
91
- EOS
92
- ]
75
+ def profile_with_doc
76
+ doc = <<~DOC
77
+ # Adds a link to the '#{name}' profile and a curie. By default the
78
+ # curie prefix is 'doc', use the `curie_prefix` keyword argument to
79
+ # change this.
80
+ # Note: the target of the profile link and the curie will be set to
81
+ # `profile_uri('#{name}')` resp. `doc_curie_uri('#{name}')`. To
82
+ # create links for external profiles or curies, delete the next line
83
+ # and use `::link` and/or `::curie` instead.
84
+ DOC
85
+
86
+ doc.split("\n") << %Q(profile #{Utils.symbol_string(name)})
93
87
  end
94
88
 
95
89
  def links_with_doc
@@ -104,20 +98,14 @@ module Shaf
104
98
  def collection_link
105
99
  link(
106
100
  rel: "collection",
107
- desc: "Link to the collection of all #{plural_name}. " \
108
- "Send a POST request to this uri to create a new #{name}",
109
- method: "GET or POST",
110
- uri: "/#{plural_name}",
111
101
  uri_helper: "#{plural_name}_uri",
112
- kwargs: ', embed_depth: 0'
102
+ kwargs: {embed_depth: 0}
113
103
  )
114
104
  end
115
105
 
116
106
  def self_link
117
107
  link(
118
108
  rel: "self",
119
- desc: "Link to this #{name}",
120
- uri: "/#{plural_name}/5",
121
109
  uri_helper: "#{name}_uri(resource)"
122
110
  )
123
111
  end
@@ -125,8 +113,6 @@ module Shaf
125
113
  def edit_link
126
114
  link(
127
115
  rel: "edit-form",
128
- desc: "Link to a form to edit this resource",
129
- uri: "/#{plural_name}/5/edit",
130
116
  uri_helper: "edit_#{name}_uri(resource)"
131
117
  )
132
118
  end
@@ -134,56 +120,30 @@ module Shaf
134
120
  def delete_link
135
121
  link(
136
122
  rel: "delete",
137
- desc: "Link to delete this #{name}",
138
- method: "DELETE",
139
- uri: "/#{plural_name}/5",
140
123
  uri_helper: "#{name}_uri(resource)",
141
- kwargs: ", curie: :doc"
124
+ kwargs: {curie: :doc}
142
125
  )
143
126
  end
144
127
 
145
128
  def create_link
146
129
  link(
147
130
  rel: "create-form",
148
- desc: "Link to a form used to create new #{name} resources",
149
- uri: "/#{plural_name}/form",
150
131
  uri_helper: "new_#{name}_uri"
151
132
  )
152
133
  end
153
134
 
154
- def link(rel:, method: "GET", desc:, uri:, uri_helper:, kwargs: "")
135
+ def link(rel:, uri_helper:, kwargs: {})
136
+ kwargs_str = kwargs.inject('') do |s, (k,v)|
137
+ "#{s}, #{k}: #{Utils.symbol_or_quoted_string(v)}"
138
+ end
139
+
155
140
  <<~EOS.split("\n")
156
- # Auto generated doc:
157
- # #{desc}.
158
- # Method: #{method}
159
- #{example(method, uri)}
160
- link #{Utils.symbol_string(rel)}#{kwargs} do
141
+ link #{Utils.symbol_string(rel)}#{kwargs_str} do
161
142
  #{uri_helper}
162
143
  end
163
144
  EOS
164
145
  end
165
146
 
166
- def example(method, uri)
167
- curl_args = +'-H "Authorization: abcdef \\"'
168
- case method
169
- when "POST"
170
- curl_args << "\n# -d@payload \\"
171
- when "PUT"
172
- curl_args << "\n# -X PUT -d@payload \\"
173
- when "DELETE"
174
- curl_args << "\n# -X DELETE \\"
175
- end
176
-
177
- <<~EOS.chomp
178
- # Example:
179
- # ```
180
- # curl -H "Accept: application/hal+json" \\
181
- # #{curl_args}
182
- # #{uri}
183
- #```
184
- EOS
185
- end
186
-
187
147
  def collection_with_doc
188
148
  <<~EOS.split("\n")
189
149
  collection of: '#{plural_name}' do
@@ -204,19 +164,24 @@ module Shaf
204
164
  model_class_name: model_class_name,
205
165
  policy_class_name: policy_class_name,
206
166
  policy_name: "#{name}_policy",
207
- attributes: attributes,
208
- links: links,
167
+ attribute_names: attribute_names,
168
+ link_relations: link_relations,
169
+ profile_with_doc: profile_with_doc,
209
170
  attributes_with_doc: attributes_with_doc,
210
- curies_with_doc: curies_with_doc,
211
171
  links_with_doc: links_with_doc,
212
172
  collection_with_doc: collection_with_doc
213
173
  }
214
174
  end
215
175
 
216
176
  def create_policy
217
- policy_args = ["policy", name, *args[1..-1]]
177
+ policy_args = ["policy", name, *attribute_names]
218
178
  Generator::Factory.create(*policy_args, **options).call
219
179
  end
180
+
181
+ def create_profile
182
+ profile_args = ["profile", name, *attributes]
183
+ Generator::Factory.create(*profile_args, **options).call
184
+ end
220
185
  end
221
186
  end
222
187
  end