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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45e90f32663688a63993bcf1aa79c6c9b8667d11dbfc9a5fdba50141e983ea53
4
- data.tar.gz: 919292b331cc09ce95031e4d1e723371114fef9e86b6d97c2e90e816befb0d77
3
+ metadata.gz: d610f6b52c0b849399c31536099eb1aecfde8b0907ee7bb1839b3430b0ccdb12
4
+ data.tar.gz: '069c31284757c68cf40538cbf623e3767847420b67cef09084f7461360978508'
5
5
  SHA512:
6
- metadata.gz: 788b01fd3f933f9e86ef99c9b51c14768208f73c5dc3cf4fe0a39fcb19078f82eb7eaaa2a1dcfc33d4d1a44980dc66254693a240b2e2b28d4a6e6b0d0383b676
7
- data.tar.gz: a07510311e28e5008991d5461f9c2e97485640cd146a8304874bc216888eb722c941c266dc74b59b184ca3ea302b6a508a315421ed040dd64c2d111ea80548c7
6
+ metadata.gz: b0b6fa7cf8e841b6791bfe2aa271ce3cb752c8efd603299d56c999b8b86df0d62ff03bd8b8cf00ab215bdaab17178b8ced05af25da5f7298bd998b79c404eed4
7
+ data.tar.gz: dedfaac82ee3fb083733354d41e4fb1417484868afb8ab956e072bf436b6035ac02287abb3b5a82d69af77b6d91da47e6eade4463dd13f1ef1c7ff98e72a429d
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,124 +1,3 @@
1
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
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}".freeze
79
+ uri = "#{base}/#{plural_name}"
80
+ helper_name = "#{plural_name}_uri"
80
81
 
81
- UriHelperMethods.register("#{plural_name}_uri") { uri }
82
- UriHelperMethods.register("#{plural_name}_uri_template") { uri }
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 "#{name}_uri" do |resrc|
93
+ UriHelperMethods.register helper_name do |resrc, **query|
89
94
  id = resrc.is_a?(Integer) ? resrc : resrc&.id
90
- raise ArgumentError, "id must be an integer! was #{id.class}" unless id.is_a?(Integer)
91
- "#{uri}/#{id}".freeze
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 "#{name}_uri_template" do
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
- UriHelperMethods.register "#{plural_name}_uri" do |resrc = nil|
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
- raise ArgumentError, "id must be an integer! was #{id.class}" unless id.is_a?(Integer)
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 "#{plural_name}_uri_template" do |collection = false|
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".freeze
134
+ uri = "#{base}/#{plural_name}/form"
135
+ helper_name = "new_#{name}_uri"
121
136
 
122
- UriHelperMethods.register("new_#{name}_uri") { uri }
123
- UriHelperMethods.register("new_#{name}_uri_template") { uri }
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 "edit_#{name}_uri" do |resrc|
148
+ UriHelperMethods.register helper_name do |resrc, **query|
130
149
  id = resrc.is_a?(Integer) ? resrc : resrc&.id
131
- "#{uri}/#{id}/edit".freeze unless id.nil?
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 "edit_#{name}_uri_template" do
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 << "(#{args.join(', ')})" unless args.empty?
154
- s
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
- <<~EOM
186
+ <<~Ruby
160
187
  def #{signature}
161
- \"#{interpolated_uri_string(uri)}\".freeze
188
+ query_string = MethodBuilder.query_string(query)
189
+ \"#{interpolated_uri_string(uri)}\#{query_string}\".freeze
162
190
  end
163
- EOM
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 params
24
- args[1..-1].map { |param| param.split(':')}
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: "#{name.capitalize}Serializer",
62
- model_class_name: name.capitalize,
63
- controller_class_name: "#{plural_name.capitalize}Controller",
64
- policy_class_name: "#{name.capitalize}Policy",
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}/5
105
+ # /#{plural_name}
100
106
  #```
101
107
  link :#{plural_name}, #{plural_name}_uri
102
108
  EOS
@@ -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: model_name.capitalize,
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: "#{policy_name.capitalize}Policy",
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
- "::#{name.capitalize}"
25
+ Utils::model_name(name)
27
26
  end
28
27
 
29
28
  def policy_class_name
30
- "::#{name.capitalize}Policy"
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: "#{name.capitalize}Serializer",
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",
@@ -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)
@@ -2,5 +2,7 @@ require 'minitest/autorun'
2
2
  require 'minitest/hooks'
3
3
  require 'shaf/spec/http_method_utils'
4
4
  require 'shaf/spec/payload_utils'
5
+ require 'shaf/spec/fixture'
6
+ require 'shaf/spec/base'
5
7
  require 'shaf/spec/integration_spec'
6
8
  require 'shaf/spec/serializer_spec'
@@ -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 < Minitest::Spec
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 < Minitest::Spec
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
@@ -43,12 +43,32 @@ namespace :db do
43
43
  end
44
44
  end
45
45
 
46
- desc "Perform rollback to specified target or full rollback as default"
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: 0)
48
+ args.with_defaults(target: 1)
49
49
  require 'config/database'
50
50
  Sequel.extension :migration
51
- Sequel::Migrator.run(DB, MIGRATIONS_DIR, target: args[:target].to_i)
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Shaf
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -5,6 +5,7 @@ default: &default
5
5
  views_folder: frontend/views
6
6
  documents_dir: doc/api
7
7
  migrations_dir: db/migrations
8
+ fixtures_dir: spec/fixtures
8
9
  paginate_per_page: 25
9
10
 
10
11
  production:
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.0
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-03-26 00:00:00.000000000 Z
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: '0'
342
+ version: '2.3'
338
343
  required_rubygems_version: !ruby/object:Gem::Requirement
339
344
  requirements:
340
345
  - - ">="
metadata.gz.sig CHANGED
Binary file