shaf 0.3.0 → 0.3.1
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.tar.gz.sig +0 -0
- data/lib/shaf/api_doc.rb +2 -123
- data/lib/shaf/api_doc/task.rb +124 -0
- data/lib/shaf/extensions/resource_uris.rb +52 -24
- data/lib/shaf/generator/controller.rb +20 -14
- data/lib/shaf/generator/model.rb +9 -6
- data/lib/shaf/generator/policy.rb +9 -5
- data/lib/shaf/generator/serializer.rb +9 -10
- data/lib/shaf/helpers/payload.rb +1 -1
- data/lib/shaf/spec.rb +2 -0
- data/lib/shaf/spec/base.rb +26 -0
- data/lib/shaf/spec/fixture.rb +62 -0
- data/lib/shaf/spec/fixtures.rb +34 -0
- data/lib/shaf/spec/integration_spec.rb +1 -13
- data/lib/shaf/spec/serializer_spec.rb +1 -14
- data/lib/shaf/tasks/db.rb +23 -3
- data/lib/shaf/utils.rb +13 -1
- data/lib/shaf/version.rb +1 -1
- data/templates/config/settings.yml +1 -0
- metadata +9 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d610f6b52c0b849399c31536099eb1aecfde8b0907ee7bb1839b3430b0ccdb12
|
4
|
+
data.tar.gz: '069c31284757c68cf40538cbf623e3767847420b67cef09084f7461360978508'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0b6fa7cf8e841b6791bfe2aa271ce3cb752c8efd603299d56c999b8b86df0d62ff03bd8b8cf00ab215bdaab17178b8ced05af25da5f7298bd998b79c404eed4
|
7
|
+
data.tar.gz: dedfaac82ee3fb083733354d41e4fb1417484868afb8ab956e072bf436b6035ac02287abb3b5a82d69af77b6d91da47e6eade4463dd13f1ef1c7ff98e72a429d
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/lib/shaf/api_doc.rb
CHANGED
@@ -1,124 +1,3 @@
|
|
1
1
|
require 'shaf/api_doc/document'
|
2
|
-
|
3
|
-
|
4
|
-
module ApiDoc
|
5
|
-
class Task
|
6
|
-
include Rake::DSL
|
7
|
-
|
8
|
-
attr_accessor :document_class, :source_dir, :html_output_dir, :yaml_output_dir
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
yield self if block_given?
|
12
|
-
validate_attributes!
|
13
|
-
@document_class ||= Document
|
14
|
-
define_tasks
|
15
|
-
end
|
16
|
-
|
17
|
-
def validate_attributes!
|
18
|
-
raise "source_dir must be set!" unless source_dir
|
19
|
-
raise "html_output_dir must be configured in ApiDocTask" unless html_output_dir
|
20
|
-
raise "yaml_output_dir must be configured in ApiDocTask" unless yaml_output_dir
|
21
|
-
end
|
22
|
-
|
23
|
-
def define_tasks
|
24
|
-
namespace :doc do
|
25
|
-
desc "Generate API documentation"
|
26
|
-
task :generate do
|
27
|
-
files = Dir.glob(File.join(source_dir, "*.rb"))
|
28
|
-
files.each do |file|
|
29
|
-
read_file file do |doc|
|
30
|
-
next unless doc.has_enough_info?
|
31
|
-
doc.write_html @html_output_dir
|
32
|
-
doc.write_yaml @yaml_output_dir
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
desc "Remove generated documentation"
|
38
|
-
task :clean do
|
39
|
-
[
|
40
|
-
Dir.glob(File.join(@yaml_output_dir, "*.yml")),
|
41
|
-
Dir.glob(File.join(@html_output_dir, "*.html"))
|
42
|
-
].flatten.each do |file|
|
43
|
-
File.unlink file
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def read_file(file)
|
50
|
-
doc = document_class.new
|
51
|
-
comment = Comment.new
|
52
|
-
|
53
|
-
File.readlines(file).each do |line|
|
54
|
-
next if empty_line?(line)
|
55
|
-
|
56
|
-
if c = comment(line)
|
57
|
-
comment << c
|
58
|
-
next
|
59
|
-
end
|
60
|
-
|
61
|
-
parse_line(line, doc, comment)
|
62
|
-
comment = Comment.new
|
63
|
-
end
|
64
|
-
|
65
|
-
return doc unless block_given?
|
66
|
-
yield doc
|
67
|
-
end
|
68
|
-
|
69
|
-
def parse_line(line, doc, comment)
|
70
|
-
if model = model(line)
|
71
|
-
doc.model = model
|
72
|
-
elsif serializer_class = serializer_class(line)
|
73
|
-
doc.serializer_class = serializer_class
|
74
|
-
elsif policy = policy(line)
|
75
|
-
doc.policy = policy
|
76
|
-
elsif attr = attribute(line)
|
77
|
-
doc.attribute(attr, comment)
|
78
|
-
elsif rel = link(line)
|
79
|
-
doc.link(rel, comment)
|
80
|
-
elsif rel = curie(line)
|
81
|
-
doc.curie(rel, comment)
|
82
|
-
elsif name = embed(line)
|
83
|
-
doc.embedded(name, comment)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def empty_line?(line)
|
88
|
-
true if line[/\A[#\s*]*\Z/]
|
89
|
-
end
|
90
|
-
|
91
|
-
def serializer_class(line)
|
92
|
-
line[/\A\s*class\s*(\w+)\Z/, 1]
|
93
|
-
end
|
94
|
-
|
95
|
-
def model(line)
|
96
|
-
line[/\A\s*model\s*(?:::)?(\w+)/, 1]
|
97
|
-
end
|
98
|
-
|
99
|
-
def policy(line)
|
100
|
-
line[/\A\s*policy\s*(?:::)?(\w+)/, 1]
|
101
|
-
end
|
102
|
-
|
103
|
-
def comment(line)
|
104
|
-
line[/\A\s*#(.*)/, 1]
|
105
|
-
end
|
106
|
-
|
107
|
-
def attribute(line)
|
108
|
-
line[/\A\s*attribute[^s]\s*\(?\s*:(\w+)/, 1]
|
109
|
-
end
|
110
|
-
|
111
|
-
def link(line)
|
112
|
-
line[/\A\s*link\s*\(?\s*:'?([-:\w]+)'?/, 1]
|
113
|
-
end
|
114
|
-
|
115
|
-
def curie(line)
|
116
|
-
line[/\A\s*curie\s*\(?\s*:'?([-\w]+)'?/, 1]
|
117
|
-
end
|
118
|
-
|
119
|
-
def embed(line)
|
120
|
-
line[/\A\s*embed\s*\(?\s*:'?([-:\w]+)'?/, 1]
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
2
|
+
require 'shaf/api_doc/comment'
|
3
|
+
require 'shaf/api_doc/task'
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'shaf/api_doc/document'
|
2
|
+
|
3
|
+
module Shaf
|
4
|
+
module ApiDoc
|
5
|
+
class Task
|
6
|
+
include Rake::DSL
|
7
|
+
|
8
|
+
attr_accessor :document_class, :source_dir, :html_output_dir, :yaml_output_dir
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
yield self if block_given?
|
12
|
+
validate_attributes!
|
13
|
+
@document_class ||= Document
|
14
|
+
define_tasks
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_attributes!
|
18
|
+
raise "source_dir must be set!" unless source_dir
|
19
|
+
raise "html_output_dir must be configured in ApiDocTask" unless html_output_dir
|
20
|
+
raise "yaml_output_dir must be configured in ApiDocTask" unless yaml_output_dir
|
21
|
+
end
|
22
|
+
|
23
|
+
def define_tasks
|
24
|
+
namespace :doc do
|
25
|
+
desc "Generate API documentation"
|
26
|
+
task :generate do
|
27
|
+
files = Dir.glob(File.join(source_dir, "*.rb"))
|
28
|
+
files.each do |file|
|
29
|
+
read_file file do |doc|
|
30
|
+
next unless doc.has_enough_info?
|
31
|
+
doc.write_html @html_output_dir
|
32
|
+
doc.write_yaml @yaml_output_dir
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Remove generated documentation"
|
38
|
+
task :clean do
|
39
|
+
[
|
40
|
+
Dir.glob(File.join(@yaml_output_dir, "*.yml")),
|
41
|
+
Dir.glob(File.join(@html_output_dir, "*.html"))
|
42
|
+
].flatten.each do |file|
|
43
|
+
File.unlink file
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def read_file(file)
|
50
|
+
doc = document_class.new
|
51
|
+
comment = Comment.new
|
52
|
+
|
53
|
+
File.readlines(file).each do |line|
|
54
|
+
next if empty_line?(line)
|
55
|
+
|
56
|
+
if c = comment(line)
|
57
|
+
comment << c
|
58
|
+
next
|
59
|
+
end
|
60
|
+
|
61
|
+
parse_line(line, doc, comment)
|
62
|
+
comment = Comment.new
|
63
|
+
end
|
64
|
+
|
65
|
+
return doc unless block_given?
|
66
|
+
yield doc
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_line(line, doc, comment)
|
70
|
+
if model = model(line)
|
71
|
+
doc.model = model
|
72
|
+
elsif serializer_class = serializer_class(line)
|
73
|
+
doc.serializer_class = serializer_class
|
74
|
+
elsif policy = policy(line)
|
75
|
+
doc.policy = policy
|
76
|
+
elsif attr = attribute(line)
|
77
|
+
doc.attribute(attr, comment)
|
78
|
+
elsif rel = link(line)
|
79
|
+
doc.link(rel, comment)
|
80
|
+
elsif rel = curie(line)
|
81
|
+
doc.curie(rel, comment)
|
82
|
+
elsif name = embed(line)
|
83
|
+
doc.embedded(name, comment)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def empty_line?(line)
|
88
|
+
true if line[/\A[#\s*]*\Z/]
|
89
|
+
end
|
90
|
+
|
91
|
+
def serializer_class(line)
|
92
|
+
line[/\A\s*class\s*(\w+)\Z/, 1]
|
93
|
+
end
|
94
|
+
|
95
|
+
def model(line)
|
96
|
+
line[/\A\s*model\s*(?:::)?(\w+)/, 1]
|
97
|
+
end
|
98
|
+
|
99
|
+
def policy(line)
|
100
|
+
line[/\A\s*policy\s*(?:::)?(\w+)/, 1]
|
101
|
+
end
|
102
|
+
|
103
|
+
def comment(line)
|
104
|
+
line[/\A\s*#(.*)/, 1]
|
105
|
+
end
|
106
|
+
|
107
|
+
def attribute(line)
|
108
|
+
line[/\A\s*attribute[^s]\s*\(?\s*:(\w+)/, 1]
|
109
|
+
end
|
110
|
+
|
111
|
+
def link(line)
|
112
|
+
line[/\A\s*link\s*\(?\s*:'?([-:\w]+)'?/, 1]
|
113
|
+
end
|
114
|
+
|
115
|
+
def curie(line)
|
116
|
+
line[/\A\s*curie\s*\(?\s*:'?([-\w]+)'?/, 1]
|
117
|
+
end
|
118
|
+
|
119
|
+
def embed(line)
|
120
|
+
line[/\A\s*embed\s*\(?\s*:'?([-:\w]+)'?/, 1]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -76,22 +76,30 @@ module Shaf
|
|
76
76
|
attr_reader :name, :base, :plural_name
|
77
77
|
|
78
78
|
def register_resources_uri
|
79
|
-
uri = "#{base}/#{plural_name}"
|
79
|
+
uri = "#{base}/#{plural_name}"
|
80
|
+
helper_name = "#{plural_name}_uri"
|
80
81
|
|
81
|
-
UriHelperMethods.register(
|
82
|
-
|
82
|
+
UriHelperMethods.register(helper_name) do |**query|
|
83
|
+
query_string = MethodBuilder.query_string(query)
|
84
|
+
"#{uri}#{query_string}".freeze
|
85
|
+
end
|
86
|
+
UriHelperMethods.register("#{helper_name}_template") { uri.freeze }
|
83
87
|
end
|
84
88
|
|
85
89
|
def register_resource_uri
|
86
90
|
uri = "#{base}/#{plural_name}"
|
91
|
+
helper_name = "#{name}_uri"
|
87
92
|
|
88
|
-
UriHelperMethods.register
|
93
|
+
UriHelperMethods.register helper_name do |resrc, **query|
|
89
94
|
id = resrc.is_a?(Integer) ? resrc : resrc&.id
|
90
|
-
|
91
|
-
|
95
|
+
query_string = MethodBuilder.query_string(query)
|
96
|
+
|
97
|
+
next "#{uri}/#{id}#{query_string}".freeze if id.is_a?(Integer)
|
98
|
+
raise ArgumentError,
|
99
|
+
"In #{helper_name}: id must be an integer! was #{id.class}"
|
92
100
|
end
|
93
101
|
|
94
|
-
UriHelperMethods.register "#{
|
102
|
+
UriHelperMethods.register "#{helper_name}_template" do
|
95
103
|
"#{uri}/:id".freeze
|
96
104
|
end
|
97
105
|
end
|
@@ -101,37 +109,52 @@ module Shaf
|
|
101
109
|
# as argument and the resources uri when no arguments are provided.
|
102
110
|
def register_resource_uri_by_arg
|
103
111
|
uri = "#{base}/#{plural_name}"
|
104
|
-
|
112
|
+
helper_name = "#{plural_name}_uri"
|
113
|
+
|
114
|
+
UriHelperMethods.register helper_name do |resrc = nil, **query|
|
115
|
+
query_string = MethodBuilder.query_string(query)
|
116
|
+
|
105
117
|
if resrc.nil?
|
106
|
-
uri.freeze
|
118
|
+
"#{uri}#{query_string}".freeze
|
107
119
|
else
|
108
120
|
id = (resrc.is_a?(Integer) ? resrc : resrc.id).to_i
|
109
|
-
|
110
|
-
"#{uri}/#{id}".freeze
|
121
|
+
|
122
|
+
next "#{uri}/#{id}#{query_string}".freeze if id.is_a?(Integer)
|
123
|
+
raise ArgumentError,
|
124
|
+
"In #{helper_name}: id must be an integer! was #{id.class}"
|
111
125
|
end
|
112
126
|
end
|
113
127
|
|
114
|
-
UriHelperMethods.register "#{
|
128
|
+
UriHelperMethods.register "#{helper_name}_template" do |collection = false|
|
115
129
|
(collection ? uri : "#{uri}/:id").freeze
|
116
130
|
end
|
117
131
|
end
|
118
132
|
|
119
133
|
def register_new_resource_uri
|
120
|
-
uri = "#{base}/#{plural_name}/form"
|
134
|
+
uri = "#{base}/#{plural_name}/form"
|
135
|
+
helper_name = "new_#{name}_uri"
|
121
136
|
|
122
|
-
UriHelperMethods.register(
|
123
|
-
|
137
|
+
UriHelperMethods.register(helper_name) do |**query|
|
138
|
+
query_string = MethodBuilder.query_string(query)
|
139
|
+
"#{uri}#{query_string}".freeze
|
140
|
+
end
|
141
|
+
UriHelperMethods.register("#{helper_name}_template") { uri.freeze }
|
124
142
|
end
|
125
143
|
|
126
144
|
def register_edit_resource_uri
|
127
145
|
uri = "#{base}/#{plural_name}"
|
146
|
+
helper_name = "edit_#{name}_uri"
|
128
147
|
|
129
|
-
UriHelperMethods.register
|
148
|
+
UriHelperMethods.register helper_name do |resrc, **query|
|
130
149
|
id = resrc.is_a?(Integer) ? resrc : resrc&.id
|
131
|
-
|
150
|
+
query_string = MethodBuilder.query_string(query)
|
151
|
+
|
152
|
+
next "#{uri}/#{id}/edit#{query_string}".freeze if id.is_a?(Integer)
|
153
|
+
raise ArgumentError,
|
154
|
+
"In #{helper_name}: id must be an integer! was #{id.class}"
|
132
155
|
end
|
133
156
|
|
134
|
-
UriHelperMethods.register "
|
157
|
+
UriHelperMethods.register "#{helper_name}_template" do
|
135
158
|
"#{uri}/:id/edit".freeze
|
136
159
|
end
|
137
160
|
end
|
@@ -149,18 +172,23 @@ module Shaf
|
|
149
172
|
|
150
173
|
def signature(name, uri)
|
151
174
|
args = extract_symbols(uri)
|
152
|
-
s = method_name(name)
|
153
|
-
s << "
|
154
|
-
|
175
|
+
s = "#{method_name(name)}("
|
176
|
+
s << (args.empty? ? "**query)" : "#{args.join(', ')}, **query)")
|
177
|
+
end
|
178
|
+
|
179
|
+
def query_string(query)
|
180
|
+
return "" unless query.any?
|
181
|
+
"?#{query.map { |key,value| "#{key}=#{value}" }.join("&")}"
|
155
182
|
end
|
156
183
|
|
157
184
|
def as_string(name, uri)
|
158
185
|
signature = signature(name, uri)
|
159
|
-
<<~
|
186
|
+
<<~Ruby
|
160
187
|
def #{signature}
|
161
|
-
|
188
|
+
query_string = MethodBuilder.query_string(query)
|
189
|
+
\"#{interpolated_uri_string(uri)}\#{query_string}\".freeze
|
162
190
|
end
|
163
|
-
|
191
|
+
Ruby
|
164
192
|
end
|
165
193
|
|
166
194
|
private
|
@@ -6,28 +6,34 @@ module Shaf
|
|
6
6
|
usage 'generate controller RESOURCE_NAME [attribute:type] [..]'
|
7
7
|
|
8
8
|
def call
|
9
|
-
if name.empty?
|
10
|
-
raise Command::ArgumentError,
|
11
|
-
"Please provide a controller name when using the controller generator!"
|
12
|
-
end
|
13
|
-
|
14
9
|
create_controller
|
15
10
|
create_integration_spec
|
16
11
|
add_link_to_root
|
17
12
|
end
|
18
13
|
|
14
|
+
def params
|
15
|
+
args[1..-1].map { |param| param.split(':')}
|
16
|
+
end
|
17
|
+
|
19
18
|
def name
|
20
|
-
args.first || ""
|
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!"
|
21
23
|
end
|
22
24
|
|
23
|
-
def
|
24
|
-
|
25
|
+
def model_class_name
|
26
|
+
Utils::model_name(name)
|
25
27
|
end
|
26
28
|
|
27
29
|
def plural_name
|
28
30
|
Utils::pluralize(name)
|
29
31
|
end
|
30
32
|
|
33
|
+
def pluralized_model_name
|
34
|
+
Utils::pluralize(model_class_name)
|
35
|
+
end
|
36
|
+
|
31
37
|
def template
|
32
38
|
'api/controller.rb'
|
33
39
|
end
|
@@ -58,10 +64,10 @@ module Shaf
|
|
58
64
|
{
|
59
65
|
name: name,
|
60
66
|
plural_name: plural_name,
|
61
|
-
serializer_class_name: "#{
|
62
|
-
model_class_name:
|
63
|
-
controller_class_name: "#{
|
64
|
-
policy_class_name: "#{
|
67
|
+
serializer_class_name: "#{model_class_name}Serializer",
|
68
|
+
model_class_name: model_class_name,
|
69
|
+
controller_class_name: "#{pluralized_model_name}Controller",
|
70
|
+
policy_class_name: "#{model_class_name}Policy",
|
65
71
|
policy_file: "policies/#{name}_policy",
|
66
72
|
params: params
|
67
73
|
}
|
@@ -94,9 +100,9 @@ module Shaf
|
|
94
100
|
# Method: GET
|
95
101
|
# Example:
|
96
102
|
# ```
|
97
|
-
# curl -H "Accept: application/json" \\
|
103
|
+
# curl -H "Accept: application/hal+json" \\
|
98
104
|
# -H "Authorization: abcdef" \\
|
99
|
-
# /#{plural_name}
|
105
|
+
# /#{plural_name}
|
100
106
|
#```
|
101
107
|
link :#{plural_name}, #{plural_name}_uri
|
102
108
|
EOS
|
data/lib/shaf/generator/model.rb
CHANGED
@@ -6,17 +6,20 @@ module Shaf
|
|
6
6
|
usage 'generate model MODEL_NAME [attribute:type] [..]'
|
7
7
|
|
8
8
|
def call
|
9
|
-
if model_name.empty?
|
10
|
-
raise "Please provide a model name when using the model generator!"
|
11
|
-
end
|
12
|
-
|
13
9
|
create_model
|
14
10
|
create_migration
|
15
11
|
create_serializer
|
16
12
|
end
|
17
13
|
|
18
14
|
def model_name
|
19
|
-
args.first || ""
|
15
|
+
n = args.first || ""
|
16
|
+
return n unless n.empty?
|
17
|
+
raise Command::ArgumentError,
|
18
|
+
"Please provide a model name when using the model generator!"
|
19
|
+
end
|
20
|
+
|
21
|
+
def model_class_name
|
22
|
+
Utils::model_name(model_name)
|
20
23
|
end
|
21
24
|
|
22
25
|
def table_name
|
@@ -48,7 +51,7 @@ module Shaf
|
|
48
51
|
def opts
|
49
52
|
{
|
50
53
|
model_name: model_name,
|
51
|
-
class_name:
|
54
|
+
class_name: model_class_name,
|
52
55
|
form_fields: form_fields
|
53
56
|
}
|
54
57
|
end
|
@@ -5,14 +5,18 @@ module Shaf
|
|
5
5
|
usage 'generate policy MODEL_NAME [attribute] [..]'
|
6
6
|
|
7
7
|
def call
|
8
|
-
if policy_name.empty?
|
9
|
-
raise "Please provide a policy name when using the policy generator!"
|
10
|
-
end
|
11
8
|
create_policy
|
12
9
|
end
|
13
10
|
|
14
11
|
def policy_name
|
15
|
-
args.first || ""
|
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)
|
16
20
|
end
|
17
21
|
|
18
22
|
def template
|
@@ -34,7 +38,7 @@ module Shaf
|
|
34
38
|
|
35
39
|
def opts
|
36
40
|
{
|
37
|
-
policy_class_name: "#{
|
41
|
+
policy_class_name: "#{model_class_name}Policy",
|
38
42
|
name: policy_name,
|
39
43
|
attributes: attributes,
|
40
44
|
}
|
@@ -5,17 +5,16 @@ module Shaf
|
|
5
5
|
usage 'generate serializer MODEL_NAME [attribute] [..]'
|
6
6
|
|
7
7
|
def call
|
8
|
-
if name.empty?
|
9
|
-
raise "Please provide a model name when using the serializer generator!"
|
10
|
-
end
|
11
|
-
|
12
8
|
create_serializer
|
13
9
|
create_serializer_spec
|
14
10
|
create_policy
|
15
11
|
end
|
16
12
|
|
17
13
|
def name
|
18
|
-
args.first || ""
|
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!"
|
19
18
|
end
|
20
19
|
|
21
20
|
def plural_name
|
@@ -23,11 +22,11 @@ module Shaf
|
|
23
22
|
end
|
24
23
|
|
25
24
|
def model_class_name
|
26
|
-
|
25
|
+
Utils::model_name(name)
|
27
26
|
end
|
28
27
|
|
29
28
|
def policy_class_name
|
30
|
-
"
|
29
|
+
"#{model_class_name}Policy"
|
31
30
|
end
|
32
31
|
|
33
32
|
def template
|
@@ -83,7 +82,7 @@ module Shaf
|
|
83
82
|
# Method: GET
|
84
83
|
# Example:
|
85
84
|
# ```
|
86
|
-
# curl -H "Accept: application/json" \\
|
85
|
+
# curl -H "Accept: application/hal+json" \\
|
87
86
|
# /doc/#{name}/rels/edit
|
88
87
|
#```
|
89
88
|
curie :doc do
|
@@ -188,7 +187,7 @@ module Shaf
|
|
188
187
|
<<~EOS.chomp
|
189
188
|
# Example:
|
190
189
|
# ```
|
191
|
-
# curl -H "Accept: application/json" \\
|
190
|
+
# curl -H "Accept: application/hal+json" \\
|
192
191
|
# -H "Authorization: abcdef" \\#{method_args}
|
193
192
|
# #{uri}
|
194
193
|
#```
|
@@ -234,7 +233,7 @@ module Shaf
|
|
234
233
|
def opts
|
235
234
|
{
|
236
235
|
name: name,
|
237
|
-
class_name: "#{
|
236
|
+
class_name: "#{model_class_name}Serializer",
|
238
237
|
model_class_name: model_class_name,
|
239
238
|
policy_class_name: policy_class_name,
|
240
239
|
policy_name: "#{name}_policy",
|
data/lib/shaf/helpers/payload.rb
CHANGED
@@ -47,7 +47,7 @@ module Shaf
|
|
47
47
|
input = read_input
|
48
48
|
return {} if input.empty?
|
49
49
|
|
50
|
-
if request.env['CONTENT_TYPE'] =~ %r(\Aapplication/json)
|
50
|
+
if request.env['CONTENT_TYPE'] =~ %r(\Aapplication/(hal\+)?json)
|
51
51
|
JSON.parse(input)
|
52
52
|
else
|
53
53
|
raise ::UnsupportedMediaTypeError.new(request: request)
|
data/lib/shaf/spec.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Shaf
|
2
|
+
module Spec
|
3
|
+
class Base < Minitest::Spec
|
4
|
+
include Minitest::Hooks
|
5
|
+
include PayloadUtils
|
6
|
+
include Fixtures
|
7
|
+
|
8
|
+
TRANSACTION_OPTIONS = {
|
9
|
+
rollback: :always,
|
10
|
+
savepoint: true,
|
11
|
+
auto_savepoint: true
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
around(:all) do |&block|
|
15
|
+
DB.transaction(TRANSACTION_OPTIONS) do
|
16
|
+
Shaf::Spec::Fixtures.load
|
17
|
+
super(&block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
around do |&block|
|
22
|
+
DB.transaction(TRANSACTION_OPTIONS) { super(&block) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'shaf/spec/fixtures'
|
2
|
+
require 'shaf/utils'
|
3
|
+
|
4
|
+
module Shaf
|
5
|
+
module Spec
|
6
|
+
class Fixture
|
7
|
+
include Fixtures
|
8
|
+
|
9
|
+
def self.define(collection_name, &block)
|
10
|
+
return unless block_given?
|
11
|
+
collection = Fixtures.add_collection(collection_name)
|
12
|
+
new(collection_name, collection, block).run
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(collection_name, collection, block)
|
16
|
+
@collection_name = collection_name
|
17
|
+
@collection = collection
|
18
|
+
@block = block
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
instance_exec(&@block)
|
23
|
+
end
|
24
|
+
|
25
|
+
def resource(name, resrc = nil, &block)
|
26
|
+
@collection[name.to_sym] = resrc || instance_exec(&block)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def method_missing(method, *args, &block)
|
32
|
+
if load_fixture_if_missing_method_is_fixture?(method, args.size)
|
33
|
+
send(method, args.first)
|
34
|
+
elsif resource_name?(args.size, block_given?)
|
35
|
+
resource(method, args.first, &block)
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def load_fixture_if_missing_method_is_fixture?(method, arg_count)
|
42
|
+
return false if arg_count > 1 # Fixtures should only be called with one argument
|
43
|
+
|
44
|
+
fixture_files = Fixtures.fixture_files
|
45
|
+
fixtures = fixture_files.map { |f| File.basename(f, ".rb") }
|
46
|
+
i = fixtures.index(method.to_s)
|
47
|
+
return false unless i
|
48
|
+
|
49
|
+
require fixture_files[i]
|
50
|
+
respond_to? method
|
51
|
+
end
|
52
|
+
|
53
|
+
def resource_name?(arg_count, block_given)
|
54
|
+
if block_given
|
55
|
+
arg_count == 0
|
56
|
+
else
|
57
|
+
arg_count == 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Shaf
|
2
|
+
module Spec
|
3
|
+
|
4
|
+
class FixtureNotFound < StandardError; end
|
5
|
+
|
6
|
+
module Fixtures
|
7
|
+
def self.load
|
8
|
+
fixture_files.map { |file| require file }
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.fixture_files
|
12
|
+
dir = Shaf::Settings.fixtures_dir || 'spec/fixtures'
|
13
|
+
Dir[File.join(dir, '**', '*.rb')]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.add_collection(collection_name)
|
17
|
+
@collections ||= {}
|
18
|
+
collection_name = collection_name.to_sym unless collection_name.is_a? Symbol
|
19
|
+
return if @collections.key? collection_name
|
20
|
+
|
21
|
+
@collections[collection_name] = {}
|
22
|
+
collection = @collections[collection_name]
|
23
|
+
create_accessor(collection, collection_name)
|
24
|
+
collection
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.create_accessor(collection, collection_name)
|
28
|
+
define_method(collection_name) do |name|
|
29
|
+
collection[name.to_sym] or raise FixtureNotFound
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,26 +1,14 @@
|
|
1
1
|
module Shaf
|
2
2
|
module Spec
|
3
|
-
class IntegrationSpec <
|
4
|
-
include Minitest::Hooks
|
3
|
+
class IntegrationSpec < Base
|
5
4
|
include HttpUtils
|
6
|
-
include PayloadUtils
|
7
5
|
include UriHelper
|
8
6
|
|
9
|
-
TRANSACTION_OPTIONS = {
|
10
|
-
rollback: :always,
|
11
|
-
savepoint: true,
|
12
|
-
auto_savepoint: true
|
13
|
-
}.freeze
|
14
|
-
|
15
7
|
register_spec_type self do |desc, args|
|
16
8
|
next unless args && args.is_a?(Hash)
|
17
9
|
args[:type]&.to_s == 'integration'
|
18
10
|
end
|
19
11
|
|
20
|
-
around do |&block|
|
21
|
-
DB.transaction(TRANSACTION_OPTIONS) { super(&block) }
|
22
|
-
end
|
23
|
-
|
24
12
|
def set_headers
|
25
13
|
if defined?(@__integration_test_auth_token) && @__integration_test_auth_token
|
26
14
|
header 'X-AUTH-TOKEN', @__integration_test_auth_token
|
@@ -1,24 +1,11 @@
|
|
1
1
|
module Shaf
|
2
2
|
module Spec
|
3
|
-
class SerializerSpec <
|
4
|
-
include Minitest::Hooks
|
5
|
-
include PayloadUtils
|
6
|
-
|
7
|
-
TRANSACTION_OPTIONS = {
|
8
|
-
rollback: :always,
|
9
|
-
savepoint: true,
|
10
|
-
auto_savepoint: true
|
11
|
-
}.freeze
|
12
|
-
|
3
|
+
class SerializerSpec < Base
|
13
4
|
register_spec_type self do |desc, args|
|
14
5
|
next true if desc.to_s =~ /Serializer$/
|
15
6
|
next unless args && args.is_a?(Hash)
|
16
7
|
args[:type]&.to_s == 'serializer'
|
17
8
|
end
|
18
|
-
|
19
|
-
around do |&block|
|
20
|
-
DB.transaction(TRANSACTION_OPTIONS) { super(&block) }
|
21
|
-
end
|
22
9
|
end
|
23
10
|
end
|
24
11
|
end
|
data/lib/shaf/tasks/db.rb
CHANGED
@@ -43,12 +43,32 @@ namespace :db do
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
desc "Perform rollback to specified
|
46
|
+
desc "Perform rollback to specified number of steps back or to the previous version"
|
47
47
|
task :rollback, :target do |t, args|
|
48
|
-
args.with_defaults(target:
|
48
|
+
args.with_defaults(target: 1)
|
49
49
|
require 'config/database'
|
50
50
|
Sequel.extension :migration
|
51
|
-
|
51
|
+
all_migrations = DB[:schema_migrations].all
|
52
|
+
target = -(args[:target].to_i + 1)
|
53
|
+
target = 0 if -target > all_migrations.size
|
54
|
+
filename = all_migrations.dig(target, :filename)
|
55
|
+
version = filename[/(\d*)_.*.rb/, 1].to_i
|
56
|
+
|
57
|
+
warn_if_rolling_back_more_than = 5
|
58
|
+
if target == 0 || -target > warn_if_rolling_back_more_than
|
59
|
+
puts "This would migrate the Database to version: #{version}. Continue [N/y]?"
|
60
|
+
next unless /\Ay/i =~ STDIN.gets.chomp&.downcase
|
61
|
+
end
|
62
|
+
Sequel::Migrator.run(DB, MIGRATIONS_DIR, target: version)
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Reset the database by deleting all rows in all columns"
|
66
|
+
task :reset do
|
67
|
+
require 'config/database'
|
68
|
+
Sequel.extension :migration
|
69
|
+
version = 0
|
70
|
+
Sequel::Migrator.run(DB, MIGRATIONS_DIR, target: version)
|
71
|
+
Sequel::Migrator.run(DB, MIGRATIONS_DIR)
|
52
72
|
end
|
53
73
|
|
54
74
|
Rake::Task["db:migrate"].enhance do
|
data/lib/shaf/utils.rb
CHANGED
@@ -2,8 +2,20 @@ module Shaf
|
|
2
2
|
module Utils
|
3
3
|
class ProjectRootNotFound < StandardError; end
|
4
4
|
|
5
|
+
# FIXME!!!
|
5
6
|
def self.pluralize(noun)
|
6
|
-
noun + 's' #FIXME
|
7
|
+
noun + 's' # FIXME!!
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.model_name(name)
|
11
|
+
name.capitalize.gsub(/[_-](\w)/) { $1.upcase }
|
12
|
+
end
|
13
|
+
|
14
|
+
# FIXME!!!
|
15
|
+
def self.singularize(noun)
|
16
|
+
return singularize(noun.to_s).to_sym if noun.is_a? Symbol
|
17
|
+
return noun unless noun.end_with? 's'
|
18
|
+
noun[0..-2]
|
7
19
|
end
|
8
20
|
|
9
21
|
def project_root
|
data/lib/shaf/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shaf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sammy Henningsson
|
@@ -31,7 +31,7 @@ cert_chain:
|
|
31
31
|
CNZdF8Vavp6xMQbPHZwqjaeZz2WRXYS7jyYSvCunjwa3OtvXtfbIEGEWE6IM+t9k
|
32
32
|
H1g6Q+B6qk9O6g==
|
33
33
|
-----END CERTIFICATE-----
|
34
|
-
date: 2018-
|
34
|
+
date: 2018-04-08 00:00:00.000000000 Z
|
35
35
|
dependencies:
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake
|
@@ -241,6 +241,7 @@ files:
|
|
241
241
|
- lib/shaf/api_doc.rb
|
242
242
|
- lib/shaf/api_doc/comment.rb
|
243
243
|
- lib/shaf/api_doc/document.rb
|
244
|
+
- lib/shaf/api_doc/task.rb
|
244
245
|
- lib/shaf/app.rb
|
245
246
|
- lib/shaf/command.rb
|
246
247
|
- lib/shaf/command/console.rb
|
@@ -284,6 +285,9 @@ files:
|
|
284
285
|
- lib/shaf/registrable_factory.rb
|
285
286
|
- lib/shaf/settings.rb
|
286
287
|
- lib/shaf/spec.rb
|
288
|
+
- lib/shaf/spec/base.rb
|
289
|
+
- lib/shaf/spec/fixture.rb
|
290
|
+
- lib/shaf/spec/fixtures.rb
|
287
291
|
- lib/shaf/spec/http_method_utils.rb
|
288
292
|
- lib/shaf/spec/integration_spec.rb
|
289
293
|
- lib/shaf/spec/model.rb
|
@@ -325,7 +329,8 @@ files:
|
|
325
329
|
homepage: https://github.com/sammyhenningsson/shaf
|
326
330
|
licenses:
|
327
331
|
- MIT
|
328
|
-
metadata:
|
332
|
+
metadata:
|
333
|
+
changelog_uri: https://github.com/sammyhenningsson/shaf/blob/master/CHANGELOG.md
|
329
334
|
post_install_message:
|
330
335
|
rdoc_options: []
|
331
336
|
require_paths:
|
@@ -334,7 +339,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
334
339
|
requirements:
|
335
340
|
- - ">="
|
336
341
|
- !ruby/object:Gem::Version
|
337
|
-
version: '
|
342
|
+
version: '2.3'
|
338
343
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
339
344
|
requirements:
|
340
345
|
- - ">="
|
metadata.gz.sig
CHANGED
Binary file
|