shaf 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|