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 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