shaf 1.6.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/iana_link_relations.csv.gz +0 -0
  4. data/lib/shaf/alps/attribute_serializer.rb +41 -0
  5. data/lib/shaf/alps/json_serializer.rb +50 -0
  6. data/lib/shaf/alps/relation_serializer.rb +70 -0
  7. data/lib/shaf/app.rb +32 -7
  8. data/lib/shaf/authenticator/base.rb +161 -0
  9. data/lib/shaf/authenticator/basic_auth.rb +25 -0
  10. data/lib/shaf/authenticator/challenge.rb +32 -0
  11. data/lib/shaf/authenticator/parameter.rb +31 -0
  12. data/lib/shaf/authenticator/request.rb +17 -0
  13. data/lib/shaf/authenticator.rb +56 -0
  14. data/lib/shaf/command/base.rb +4 -0
  15. data/lib/shaf/command/console.rb +1 -1
  16. data/lib/shaf/command/generate.rb +5 -2
  17. data/lib/shaf/command/new.rb +24 -7
  18. data/lib/shaf/command/server.rb +5 -1
  19. data/lib/shaf/command/templates/Gemfile.erb +1 -0
  20. data/{templates/config/settings.yml → lib/shaf/command/templates/config/settings.yml.erb} +9 -12
  21. data/lib/shaf/errors.rb +11 -0
  22. data/lib/shaf/extensions/api_routes.rb +60 -0
  23. data/lib/shaf/extensions/authorize.rb +11 -9
  24. data/lib/shaf/extensions/log.rb +1 -1
  25. data/lib/shaf/extensions/resource_uris.rb +95 -137
  26. data/lib/shaf/extensions/symbolic_routes.rb +9 -19
  27. data/lib/shaf/extensions.rb +3 -3
  28. data/lib/shaf/formable/builder.rb +58 -19
  29. data/lib/shaf/formable/form.rb +14 -11
  30. data/lib/shaf/formable.rb +10 -24
  31. data/lib/shaf/generator/base.rb +84 -3
  32. data/lib/shaf/generator/controller.rb +30 -42
  33. data/lib/shaf/generator/doc.rb +17 -0
  34. data/lib/shaf/generator/forms.rb +11 -14
  35. data/lib/shaf/generator/helper.rb +2 -1
  36. data/lib/shaf/generator/migration/add_column.rb +0 -4
  37. data/lib/shaf/generator/migration/add_index.rb +0 -4
  38. data/lib/shaf/generator/migration/base.rb +15 -3
  39. data/lib/shaf/generator/migration/create_table.rb +0 -4
  40. data/lib/shaf/generator/migration/drop_column.rb +0 -4
  41. data/lib/shaf/generator/migration/rename_column.rb +0 -4
  42. data/lib/shaf/generator/migration/type.rb +4 -26
  43. data/lib/shaf/generator/migration/types.rb +45 -16
  44. data/lib/shaf/generator/model.rb +29 -15
  45. data/lib/shaf/generator/policy.rb +8 -14
  46. data/lib/shaf/generator/profile.rb +47 -0
  47. data/lib/shaf/generator/scaffold.rb +6 -9
  48. data/lib/shaf/generator/serializer.rb +64 -98
  49. data/lib/shaf/generator/templates/api/controller.rb.erb +13 -13
  50. data/lib/shaf/generator/templates/api/forms.rb.erb +2 -2
  51. data/lib/shaf/generator/templates/api/model.rb.erb +1 -1
  52. data/lib/shaf/generator/templates/api/policy.rb.erb +2 -2
  53. data/lib/shaf/generator/templates/api/profile.rb.erb +16 -0
  54. data/lib/shaf/generator/templates/api/serializer.rb.erb +3 -3
  55. data/lib/shaf/generator/templates/spec/integration_spec.rb.erb +15 -16
  56. data/lib/shaf/generator/templates/spec/serializer_spec.rb.erb +5 -5
  57. data/lib/shaf/generator.rb +2 -0
  58. data/lib/shaf/helpers/authentication.rb +79 -0
  59. data/lib/shaf/helpers/paginate.rb +1 -1
  60. data/lib/shaf/helpers/payload.rb +14 -34
  61. data/lib/shaf/helpers/vary.rb +8 -0
  62. data/lib/shaf/helpers.rb +4 -0
  63. data/lib/shaf/logger.rb +12 -0
  64. data/lib/shaf/parser/base.rb +44 -0
  65. data/lib/shaf/parser/form_data.rb +15 -0
  66. data/lib/shaf/parser/json.rb +26 -0
  67. data/lib/shaf/parser.rb +65 -0
  68. data/lib/shaf/profile/attribute.rb +29 -0
  69. data/lib/shaf/profile/evaluator.rb +46 -0
  70. data/lib/shaf/profile/relation.rb +29 -0
  71. data/lib/shaf/profile/unique_id.rb +58 -0
  72. data/lib/shaf/profile.rb +115 -0
  73. data/lib/shaf/profiles/shaf_basic.rb +20 -0
  74. data/lib/shaf/profiles/shaf_error.rb +49 -0
  75. data/lib/shaf/profiles/shaf_form.rb +110 -0
  76. data/lib/shaf/profiles.rb +46 -0
  77. data/lib/shaf/registrable_factory.rb +62 -32
  78. data/lib/shaf/responder/alps_json.rb +25 -0
  79. data/lib/shaf/responder/base.rb +20 -17
  80. data/lib/shaf/responder/hal.rb +66 -5
  81. data/lib/shaf/responder/html.rb +43 -16
  82. data/lib/shaf/responder/problem_json.rb +2 -2
  83. data/lib/shaf/responder.rb +41 -2
  84. data/lib/shaf/router.rb +65 -12
  85. data/lib/shaf/serializer.rb +35 -0
  86. data/lib/shaf/settings.rb +25 -12
  87. data/lib/shaf/spec/authenticator.rb +13 -0
  88. data/lib/shaf/spec/base.rb +1 -1
  89. data/lib/shaf/spec/http_method_utils.rb +1 -1
  90. data/lib/shaf/spec/integration_spec.rb +26 -14
  91. data/lib/shaf/spec/payload_utils.rb +2 -2
  92. data/lib/shaf/spec.rb +1 -0
  93. data/lib/shaf/supported_http_methods.rb +15 -0
  94. data/lib/shaf/tasks/routes_task.rb +14 -17
  95. data/lib/shaf/tasks.rb +0 -1
  96. data/lib/shaf/upgrade/manifest.rb +11 -2
  97. data/lib/shaf/upgrade/package.rb +73 -45
  98. data/lib/shaf/upgrade/version.rb +11 -10
  99. data/lib/shaf/utils.rb +19 -5
  100. data/lib/shaf/version.rb +3 -1
  101. data/lib/shaf/yard/attribute_method_handler.rb +19 -0
  102. data/lib/shaf/yard/attribute_object.rb +30 -0
  103. data/lib/shaf/yard/base_method_handler.rb +30 -0
  104. data/lib/shaf/yard/link_method_handler.rb +39 -0
  105. data/lib/shaf/yard/link_object.rb +60 -0
  106. data/lib/shaf/yard/nested_attributes.rb +37 -0
  107. data/lib/shaf/yard/parser.rb +64 -0
  108. data/lib/shaf/yard/profile_method_handler.rb +51 -0
  109. data/lib/shaf/yard/profile_object.rb +21 -0
  110. data/lib/shaf/yard/resource_object.rb +55 -0
  111. data/lib/shaf/yard/serializer_handler.rb +27 -0
  112. data/lib/shaf/yard.rb +34 -0
  113. data/lib/shaf.rb +6 -0
  114. data/templates/Rakefile +0 -6
  115. data/templates/api/controllers/base_controller.rb +0 -12
  116. data/templates/api/controllers/docs_controller.rb +5 -3
  117. data/templates/api/controllers/root_controller.rb +7 -1
  118. data/templates/api/policies/base_policy.rb +2 -0
  119. data/templates/api/serializers/base_serializer.rb +1 -3
  120. data/templates/api/serializers/error_serializer.rb +1 -5
  121. data/templates/api/serializers/form_serializer.rb +1 -5
  122. data/templates/api/serializers/root_serializer.rb +0 -11
  123. data/templates/api/serializers/validation_error_serializer.rb +1 -5
  124. data/templates/config/bootstrap.rb +1 -2
  125. data/templates/config/directories.rb +52 -44
  126. data/templates/config/helpers.rb +1 -1
  127. data/templates/config/initializers/authentication.rb +18 -0
  128. data/templates/config/initializers/db_migrations.rb +2 -2
  129. data/templates/config/initializers/logging.rb +2 -2
  130. data/templates/config/initializers/middleware.rb +6 -0
  131. data/templates/config/initializers.rb +52 -8
  132. data/templates/config.ru +1 -1
  133. data/templates/spec/spec_helper.rb +5 -0
  134. data/upgrades/0.5.0.tar.gz +0 -0
  135. data/upgrades/1.0.4.tar.gz +0 -0
  136. data/upgrades/1.1.0.tar.gz +0 -0
  137. data/upgrades/1.6.1.tar.gz +0 -0
  138. data/upgrades/2.0.0.tar.gz +0 -0
  139. data/upgrades/3.0.0.tar.gz +0 -0
  140. data/yard_templates/api_doc/doc_index/html/body.erb +3 -0
  141. data/yard_templates/api_doc/doc_index/setup.rb +8 -0
  142. data/yard_templates/api_doc/html/css/api-doc.css +222 -0
  143. data/yard_templates/api_doc/html/favicon.ico +0 -0
  144. data/yard_templates/api_doc/html/js/switch_tab.js +17 -0
  145. data/yard_templates/api_doc/html/setup.rb +59 -0
  146. data/yard_templates/api_doc/layout/html/footer.erb +3 -0
  147. data/yard_templates/api_doc/layout/html/header.erb +7 -0
  148. data/yard_templates/api_doc/layout/html/layout.erb +13 -0
  149. data/yard_templates/api_doc/layout/setup.rb +24 -0
  150. data/yard_templates/api_doc/profile/html/attributes.erb +10 -0
  151. data/yard_templates/api_doc/profile/html/profile.erb +6 -0
  152. data/yard_templates/api_doc/profile/html/relations.erb +10 -0
  153. data/yard_templates/api_doc/profile/setup.rb +38 -0
  154. data/yard_templates/api_doc/profile_attribute/html/attribute.erb +23 -0
  155. data/yard_templates/api_doc/profile_attribute/setup.rb +21 -0
  156. data/yard_templates/api_doc/profile_relation/html/relation.erb +37 -0
  157. data/yard_templates/api_doc/profile_relation/setup.rb +41 -0
  158. data/yard_templates/api_doc/resource/html/attributes.erb +10 -0
  159. data/yard_templates/api_doc/resource/html/profile.erb +14 -0
  160. data/yard_templates/api_doc/resource/html/relations.erb +10 -0
  161. data/yard_templates/api_doc/resource/html/resource.erb +5 -0
  162. data/yard_templates/api_doc/resource/setup.rb +56 -0
  163. data/yard_templates/api_doc/resource_attribute/html/attribute.erb +23 -0
  164. data/yard_templates/api_doc/resource_attribute/setup.rb +20 -0
  165. data/yard_templates/api_doc/resource_relation/html/relation.erb +47 -0
  166. data/yard_templates/api_doc/resource_relation/setup.rb +80 -0
  167. data/yard_templates/api_doc/setup.rb +31 -0
  168. data/yard_templates/api_doc/sidebar/html/profile_list.erb +8 -0
  169. data/yard_templates/api_doc/sidebar/html/search.erb +7 -0
  170. data/yard_templates/api_doc/sidebar/html/serializer_list.erb +8 -0
  171. data/yard_templates/api_doc/sidebar/html/sidebar.erb +13 -0
  172. data/yard_templates/api_doc/sidebar/setup.rb +56 -0
  173. data.tar.gz.sig +2 -2
  174. metadata +143 -38
  175. metadata.gz.sig +0 -0
  176. data/lib/shaf/api_doc/comment.rb +0 -27
  177. data/lib/shaf/api_doc/document.rb +0 -137
  178. data/lib/shaf/extensions/current_user.rb +0 -48
  179. data/lib/shaf/middleware.rb +0 -1
  180. data/lib/shaf/responder/hal_serializable.rb +0 -64
  181. data/lib/shaf/tasks/api_doc_task.rb +0 -125
@@ -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) {
@@ -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
- def model_name
16
- n = args.first || ''
17
- return n unless n.empty?
18
- raise Command::ArgumentError,
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 model_class_name
23
- Utils.model_name(model_name)
31
+ def skip_migration?
32
+ options[:skip_migration] || skip_model?
24
33
  end
25
34
 
26
35
  def table_name
27
- Utils.pluralize model_name
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 target
35
- "api/models/#{model_name}.rb"
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,13 +67,12 @@ module Shaf
52
67
  end
53
68
 
54
69
  def create_serializer
55
- serializer_args = %W(serializer #{model_name})
56
- serializer_args += args[1..-1].map { |arg| arg.split(':').first }
70
+ serializer_args = %W(serializer #{name_arg}) + args[1..-1]
57
71
  Generator::Factory.create(*serializer_args, **options).call
58
72
  end
59
73
 
60
74
  def create_forms
61
- form_args = %W(forms #{model_name}) + args[1..-1]
75
+ form_args = %W(forms #{name_arg}) + args[1..-1]
62
76
  Generator::Factory.create(*form_args, **options).call
63
77
  end
64
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 target
27
- "api/policies/#{policy_name}_policy.rb"
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: policy_name,
36
+ name: name,
43
37
  attributes: attributes,
44
38
  }
45
39
  end
@@ -0,0 +1,47 @@
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 template
12
+ 'api/profile.rb'
13
+ end
14
+
15
+ def target_dir
16
+ 'api/profiles'
17
+ end
18
+
19
+ def target_name
20
+ "#{name}.rb"
21
+ end
22
+
23
+ def attributes
24
+ args[1..-1].map do |attr|
25
+ name, type = attr.split(':')
26
+ type ||= 'String'
27
+ [name, type.capitalize]
28
+ end
29
+ end
30
+
31
+ def create_profile
32
+ content = render(template, opts)
33
+ content = wrap_in_module(content, module_name, search: 'class \w')
34
+ write_output(target, content)
35
+ end
36
+
37
+ def opts
38
+ {
39
+ profile_name: name,
40
+ profile_class_name: "#{model_class_name}",
41
+ attributes: attributes,
42
+ resource_name: resource_name,
43
+ }
44
+ end
45
+ end
46
+ end
47
+ end
@@ -6,21 +6,18 @@ module Shaf
6
6
  usage 'generate scaffold RESOURCE_NAME [attribute:type] [..]'
7
7
 
8
8
  def call
9
- if name.empty?
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', *controller_args, **options).call
13
+ Generator::Factory.create('controller', *args, **options).call
16
14
  end
17
15
 
18
- def name
19
- args.first || ""
20
- end
16
+ def check_name_arg!
17
+ return if args.first && !args.first.empty?
21
18
 
22
- def controller_args
23
- [name] + args[1..-1]
19
+ raise Command::ArgumentError,
20
+ "Please provide a name when using the scaffold generator!"
24
21
  end
25
22
  end
26
23
  end
@@ -2,27 +2,17 @@ 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
- def name
14
- n = args.first || ""
15
- return n unless n.empty?
16
- raise Command::ArgumentError,
17
- "Please provide a model name when using the serializer generator!"
18
- end
19
-
20
- def plural_name
21
- Utils.pluralize(name)
22
- end
23
-
24
- def model_class_name
25
- Utils.model_name(name)
14
+ def serializer_class_name
15
+ "#{model_class_name}Serializer"
26
16
  end
27
17
 
28
18
  def policy_class_name
@@ -37,59 +27,62 @@ module Shaf
37
27
  'spec/serializer_spec.rb'
38
28
  end
39
29
 
40
- def target
41
- "api/serializers/#{name}_serializer.rb"
30
+ def target_dir
31
+ 'api/serializers'
32
+ end
33
+
34
+ def target_name
35
+ "#{name}_serializer.rb"
42
36
  end
43
37
 
44
38
  def spec_target
45
- "spec/serializers/#{name}_serializer_spec.rb"
39
+ target(directory: 'spec/serializers', name: "#{name}_serializer_spec.rb")
40
+ end
41
+
42
+ def policy_file
43
+ File.join(['policies', namespace, "#{name}_policy"].compact)
46
44
  end
47
45
 
48
46
  def create_serializer
49
47
  content = render(template, opts)
48
+ content = wrap_in_module(content, module_name)
50
49
  write_output(target, content)
51
50
  end
52
51
 
53
52
  def create_serializer_spec
54
53
  content = render(spec_template, opts)
54
+ content = wrap_in_module(content, module_name, search: "describe #{serializer_class_name}")
55
55
  write_output(spec_target, content)
56
56
  end
57
57
 
58
58
  def attributes
59
- args[1..-1].map { |attr| ":#{attr}" }
59
+ args[1..-1]
60
+ end
61
+
62
+ def attribute_names
63
+ attributes.map { |arg| arg.split(':').first }
60
64
  end
61
65
 
62
66
  def attributes_with_doc
63
- attributes.map do |attr|
64
- [
65
- "# FIXME: Write documentation for attribute #{attr}",
66
- "attribute #{attr}"
67
- ]
68
- end
67
+ attribute_names.map { |attr| ["attribute :#{attr}"] }
69
68
  end
70
69
 
71
- def links
70
+ def link_relations
72
71
  %w(collection self edit-form doc:delete)
73
72
  end
74
73
 
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
- ]
74
+ def profile_with_doc
75
+ doc = <<~DOC
76
+ # Adds a link to the '#{resource_name}' profile and a curie. By default the
77
+ # curie prefix is 'doc', use the `curie_prefix` keyword argument to
78
+ # change this.
79
+ # Note: the target of the profile link and the curie will be set to
80
+ # `profile_uri('#{resource_name}')` resp. `doc_curie_uri('#{resource_name}')`. To
81
+ # create links for external profiles or curies, delete the next line
82
+ # and use `::link` and/or `::curie` instead.
83
+ DOC
84
+
85
+ doc.split("\n") << %Q(profile #{Utils.symbol_string(resource_name)})
93
86
  end
94
87
 
95
88
  def links_with_doc
@@ -104,92 +97,58 @@ module Shaf
104
97
  def collection_link
105
98
  link(
106
99
  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
- uri_helper: "#{plural_name}_uri",
112
- kwargs: ', embed_depth: 0'
100
+ uri_helper: "#{collection_name}_uri",
101
+ kwargs: {embed_depth: 0}
113
102
  )
114
103
  end
115
104
 
116
105
  def self_link
117
106
  link(
118
107
  rel: "self",
119
- desc: "Link to this #{name}",
120
- uri: "/#{plural_name}/5",
121
- uri_helper: "#{name}_uri(resource)"
108
+ uri_helper: "#{resource_name}_uri(resource)"
122
109
  )
123
110
  end
124
111
 
125
112
  def edit_link
126
113
  link(
127
114
  rel: "edit-form",
128
- desc: "Link to a form to edit this resource",
129
- uri: "/#{plural_name}/5/edit",
130
- uri_helper: "edit_#{name}_uri(resource)"
115
+ uri_helper: "edit_#{resource_name}_uri(resource)"
131
116
  )
132
117
  end
133
118
 
134
119
  def delete_link
135
120
  link(
136
121
  rel: "delete",
137
- desc: "Link to delete this #{name}",
138
- method: "DELETE",
139
- uri: "/#{plural_name}/5",
140
- uri_helper: "#{name}_uri(resource)",
141
- kwargs: ", curie: :doc"
122
+ uri_helper: "#{resource_name}_uri(resource)",
123
+ kwargs: {curie: :doc}
142
124
  )
143
125
  end
144
126
 
145
127
  def create_link
146
128
  link(
147
129
  rel: "create-form",
148
- desc: "Link to a form used to create new #{name} resources",
149
- uri: "/#{plural_name}/form",
150
- uri_helper: "new_#{name}_uri"
130
+ uri_helper: "new_#{resource_name}_uri"
151
131
  )
152
132
  end
153
133
 
154
- def link(rel:, method: "GET", desc:, uri:, uri_helper:, kwargs: "")
134
+ def link(rel:, uri_helper:, kwargs: {})
135
+ kwargs_str = kwargs.inject('') do |s, (k,v)|
136
+ "#{s}, #{k}: #{Utils.symbol_or_quoted_string(v)}"
137
+ end
138
+
155
139
  <<~EOS.split("\n")
156
- # Auto generated doc:
157
- # #{desc}.
158
- # Method: #{method}
159
- #{example(method, uri)}
160
- link #{Utils.symbol_string(rel)}#{kwargs} do
140
+ link #{Utils.symbol_string(rel)}#{kwargs_str} do
161
141
  #{uri_helper}
162
142
  end
163
143
  EOS
164
144
  end
165
145
 
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
146
  def collection_with_doc
188
147
  <<~EOS.split("\n")
189
148
  collection of: '#{plural_name}' do
190
- curie(:doc) { doc_curie_uri('#{name}') }
149
+ curie(:doc) { doc_curie_uri('#{resource_name}') }
191
150
 
192
- link :self, #{plural_name}_uri
151
+ link :self, #{collection_name}_uri
193
152
  link :up, root_uri
194
153
 
195
154
  #{create_link.join("\n ")}
@@ -200,23 +159,30 @@ module Shaf
200
159
  def opts
201
160
  {
202
161
  name: name,
203
- class_name: "#{model_class_name}Serializer",
162
+ resource_name: resource_name,
163
+ collection_name: collection_name,
164
+ class_name: serializer_class_name,
204
165
  model_class_name: model_class_name,
205
166
  policy_class_name: policy_class_name,
206
- policy_name: "#{name}_policy",
207
- attributes: attributes,
208
- links: links,
167
+ policy_file: policy_file,
168
+ attribute_names: attribute_names,
169
+ link_relations: link_relations,
170
+ profile_with_doc: profile_with_doc,
209
171
  attributes_with_doc: attributes_with_doc,
210
- curies_with_doc: curies_with_doc,
211
172
  links_with_doc: links_with_doc,
212
173
  collection_with_doc: collection_with_doc
213
174
  }
214
175
  end
215
176
 
216
177
  def create_policy
217
- policy_args = ["policy", name, *args[1..-1]]
178
+ policy_args = ["policy", name_arg, *attribute_names]
218
179
  Generator::Factory.create(*policy_args, **options).call
219
180
  end
181
+
182
+ def create_profile
183
+ profile_args = ["profile", name_arg, *attributes]
184
+ Generator::Factory.create(*profile_args, **options).call
185
+ end
220
186
  end
221
187
  end
222
188
  end
@@ -4,45 +4,45 @@ class <%= controller_class_name %> < BaseController
4
4
 
5
5
  authorize_with <%= policy_class_name %>
6
6
 
7
- resource_uris_for :<%= name %>
7
+ resource_uris_for :<%= name %><%= namespace ? ", namespace: '#{namespace}'" : "" %>
8
8
 
9
- get :<%= plural_name %>_path do
9
+ get :<%= collection_name %>_path do
10
10
  authorize! :read
11
11
  collection = paginate(<%= model_class_name %>.order(:created_at).reverse)
12
12
  respond_with_collection collection, serializer: <%= serializer_class_name %>
13
13
  end
14
14
 
15
- get :new_<%= name %>_path do
15
+ get :new_<%= resource_name %>_path do
16
16
  authorize! :read
17
17
  cache_control(:private, http_cache_max_age: :short)
18
18
  respond_with create_form
19
19
  end
20
20
 
21
- post :<%= plural_name %>_path do
21
+ post :<%= collection_name %>_path do
22
22
  authorize! :write
23
23
  <%= name %> = <%= model_class_name %>.create(<%= name %>_params)
24
- headers('Location' => <%= name %>_uri(<%= name %>))
24
+ headers('Location' => <%= resource_name %>_uri(<%= name %>))
25
25
  respond_with <%= name %>, status: 201
26
26
  end
27
27
 
28
- get :<%= name %>_path do
28
+ get :<%= resource_name %>_path do
29
29
  authorize! :read
30
30
  respond_with <%= name %>
31
31
  end
32
32
 
33
- get :edit_<%= name %>_path do
33
+ get :edit_<%= resource_name %>_path do
34
34
  authorize! :write
35
35
  cache_control(:private, http_cache_max_age: :short)
36
36
  respond_with edit_form
37
37
  end
38
38
 
39
- put :<%= name %>_path do
39
+ put :<%= resource_name %>_path do
40
40
  authorize! :write
41
41
  <%= name %>.update(<%= name %>_params)
42
42
  respond_with <%= name %>
43
43
  end
44
44
 
45
- delete :<%= name %>_path do
45
+ delete :<%= resource_name %>_path do
46
46
  authorize! :write
47
47
  <%= name %>.destroy
48
48
  status 204
@@ -62,15 +62,15 @@ class <%= controller_class_name %> < BaseController
62
62
 
63
63
  def create_form
64
64
  <%= model_class_name %>.create_form.tap do |form|
65
- form.self_link = new_<%= name %>_uri
66
- form.href = <%= plural_name %>_uri
65
+ form.self_link = new_<%= resource_name %>_uri
66
+ form.href = <%= collection_name %>_uri
67
67
  end
68
68
  end
69
69
 
70
70
  def edit_form
71
71
  <%= name %>.edit_form.tap do |form|
72
- form.self_link = edit_<%= name %>_uri(<%= name %>)
73
- form.href = <%= name %>_uri(<%= name %>)
72
+ form.self_link = edit_<%= resource_name %>_uri(<%= name %>)
73
+ form.href = <%= resource_name %>_uri(<%= name %>)
74
74
  end
75
75
  end
76
76
  end
@@ -4,12 +4,12 @@ class <%= class_name %>
4
4
  forms_for(<%= model_class_name %>) do
5
5
  <%= fields.join("\n ") %>
6
6
 
7
- create do
7
+ create_form do
8
8
  title 'Create <%= model_class_name %>'
9
9
  name 'create-<%= model_name %>'
10
10
  end
11
11
 
12
- edit do
12
+ edit_form do
13
13
  instance_accessor
14
14
  title 'Update <%= model_class_name %>'
15
15
  name 'update-<%= model_name %>'
@@ -1,4 +1,4 @@
1
- class <%= class_name %> < Sequel::Model
1
+ class <%= class_name %> < Sequel::Model(:<%= table_name %>)
2
2
 
3
3
  end
4
4
 
@@ -8,9 +8,9 @@ class <%= policy_class_name %> < BasePolicy
8
8
 
9
9
  <%= attributes.join("\n ") %>
10
10
 
11
- link :collection
11
+ link :collection, :up, :proflie
12
12
 
13
- link :'create-form', :'edit-form', :delete do
13
+ link :create_form, :edit_form, :delete do
14
14
  write?
15
15
  end
16
16
 
@@ -0,0 +1,16 @@
1
+ module Profiles
2
+ class <%= profile_class_name %> < Shaf::Profile
3
+ name '<%= resource_name %>'
4
+
5
+ doc 'FIXME: replace this with a description of the <%= profile_name %> profile'
6
+
7
+ use :delete, from: Shaf::Profiles::ShafBasic
8
+
9
+ <% attributes.each do |name, type| %>
10
+ attribute :<%= name %>,
11
+ type: '<%= type %>',
12
+ doc: 'FIXME: Write documentation for <%= name %>'
13
+
14
+ <% end %>
15
+ end
16
+ end