shaf 2.1.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/shaf/app.rb +27 -9
  4. data/lib/shaf/command/base.rb +4 -0
  5. data/lib/shaf/command/new.rb +5 -1
  6. data/lib/shaf/command/server.rb +5 -1
  7. data/lib/shaf/command/templates/config/settings.yml.erb +9 -8
  8. data/lib/shaf/extensions/resource_uris.rb +37 -155
  9. data/lib/shaf/extensions/symbolic_routes.rb +5 -18
  10. data/lib/shaf/formable/builder.rb +58 -19
  11. data/lib/shaf/formable/form.rb +13 -10
  12. data/lib/shaf/formable.rb +10 -23
  13. data/lib/shaf/generator/base.rb +82 -0
  14. data/lib/shaf/generator/controller.rb +19 -35
  15. data/lib/shaf/generator/forms.rb +10 -14
  16. data/lib/shaf/generator/migration/add_column.rb +0 -4
  17. data/lib/shaf/generator/migration/add_index.rb +0 -4
  18. data/lib/shaf/generator/migration/base.rb +8 -0
  19. data/lib/shaf/generator/migration/create_table.rb +0 -4
  20. data/lib/shaf/generator/migration/drop_column.rb +0 -4
  21. data/lib/shaf/generator/migration/rename_column.rb +0 -4
  22. data/lib/shaf/generator/model.rb +29 -14
  23. data/lib/shaf/generator/policy.rb +8 -14
  24. data/lib/shaf/generator/profile.rb +9 -14
  25. data/lib/shaf/generator/scaffold.rb +6 -9
  26. data/lib/shaf/generator/serializer.rb +31 -30
  27. data/lib/shaf/generator/templates/api/controller.rb.erb +13 -13
  28. data/lib/shaf/generator/templates/api/forms.rb.erb +2 -2
  29. data/lib/shaf/generator/templates/api/model.rb.erb +1 -1
  30. data/lib/shaf/generator/templates/api/profile.rb.erb +1 -1
  31. data/lib/shaf/generator/templates/api/serializer.rb.erb +1 -1
  32. data/lib/shaf/generator/templates/spec/integration_spec.rb.erb +14 -14
  33. data/lib/shaf/helpers/paginate.rb +1 -1
  34. data/lib/shaf/link_relations.rb +77 -0
  35. data/lib/shaf/profile.rb +8 -8
  36. data/lib/shaf/registrable_factory.rb +62 -32
  37. data/lib/shaf/responder/problem_json.rb +1 -1
  38. data/lib/shaf/router.rb +65 -12
  39. data/lib/shaf/spec/integration_spec.rb +1 -1
  40. data/lib/shaf/tasks.rb +0 -1
  41. data/lib/shaf/upgrade/package.rb +5 -7
  42. data/lib/shaf/utils.rb +2 -2
  43. data/lib/shaf/version.rb +1 -1
  44. data/lib/shaf/yard/link_object.rb +2 -3
  45. data/templates/Rakefile +0 -6
  46. data/templates/api/controllers/base_controller.rb +0 -2
  47. data/templates/api/serializers/root_serializer.rb +0 -11
  48. data/templates/config/initializers/middleware.rb +6 -0
  49. data/templates/spec/spec_helper.rb +4 -1
  50. data/upgrades/3.0.0.tar.gz +0 -0
  51. data/yard_templates/api_doc/profile_attribute/html/attribute.erb +2 -1
  52. data/yard_templates/api_doc/resource_attribute/html/attribute.erb +2 -1
  53. data/yard_templates/api_doc/sidebar/html/profile_list.erb +2 -1
  54. data/yard_templates/api_doc/sidebar/html/serializer_list.erb +2 -1
  55. data.tar.gz.sig +0 -0
  56. metadata +34 -36
  57. metadata.gz.sig +0 -0
  58. data/lib/shaf/api_doc/comment.rb +0 -27
  59. data/lib/shaf/api_doc/document.rb +0 -137
  60. data/lib/shaf/api_doc/link_relations.rb +0 -77
  61. data/lib/shaf/middleware.rb +0 -1
  62. data/lib/shaf/tasks/api_doc_task.rb +0 -146
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2dc76b4b8ddbc8c627a2f03eb3f3f889771a21cc950de357fc6d3d50a7ba3008
4
- data.tar.gz: 5c6ab688fa85a69650e6741933b9ddbad4dd6d40693ce0998d9fb88b14e212ef
3
+ metadata.gz: c508aa7154d738ed2009c18256326f590917af8c24d60bfacfd5bb91613c4270
4
+ data.tar.gz: 49e9fec1c522764bb1a722623cfb49cf8de3d6d7e026355a09310a6099828711
5
5
  SHA512:
6
- metadata.gz: 154deb196fe2f4583599024524bd21b06fadc039fb99971ed2360acffb65b1339c79c8b61edebbf230df558473ef9f11cc0baa54c79b52df0989c60d60e7debf
7
- data.tar.gz: 49d240389e58f852e4445ccd321f83bb501d803bb957c328816d470ac5bb64c648e293be26b5dbda07e57649fe1987b339e4dc458e4d5f27c3b56e120f14adbe
6
+ metadata.gz: d1d2ddda76cb3e76470f4cbc0297e72ef3c3b9c6119a12d101d999a50bc0aab37a442067ddd0cb4fdd3e698d0446982e65d199e633e46d875175e087f3bc9a61
7
+ data.tar.gz: 3d2c97ed1362ac58addf9c282e37d8754adad5a994c421d72779e4576dd91c8cbd1bbfc67689d20bf51bc20410270f61752383d36b11eb9dcbe28883c6552440
checksums.yaml.gz.sig CHANGED
Binary file
data/lib/shaf/app.rb CHANGED
@@ -1,25 +1,43 @@
1
- require 'shaf/middleware'
1
+ require 'sinatra'
2
2
 
3
3
  module Shaf
4
4
  class App
5
5
  class << self
6
6
  # Either call `Shaf::App.run!`
7
7
  def run!
8
- app.run!
8
+ instance.run!
9
9
  end
10
10
 
11
11
  # Or `run Shaf::App` (in config.ru)
12
12
  def call(*args)
13
- app.call(*args)
13
+ instance.call(*args)
14
14
  end
15
15
 
16
+ def instance
17
+ # This works since Sinatra includes Sinatra::Delegator into
18
+ # Rack::Builder, which means that Rack::Builder#set will be delegated
19
+ # to Sinatra::Application
20
+ @instance ||= Rack::Builder.new(app) do
21
+ set :port, Settings.port || 3000
22
+ end
23
+ end
24
+
25
+ def use(middleware, *args, **kwargs, &block)
26
+ if args.empty? && kwargs.empty?
27
+ instance.use middleware, &block
28
+ elsif kwargs.empty?
29
+ instance.use middleware, *args, &block
30
+ elsif args.empty?
31
+ instance.use middleware, **kwargs, &block
32
+ else
33
+ instance.use middleware, *args, **kwargs, &block
34
+ end
35
+ end
36
+
37
+ private
38
+
16
39
  def app
17
- @app ||=
18
- Sinatra.new.tap do |app|
19
- app.set :port, Settings.port || 3000
20
- app.use Middleware::RequestId
21
- app.use Router
22
- end
40
+ Router.new
23
41
  end
24
42
  end
25
43
  end
@@ -23,6 +23,10 @@ module Shaf
23
23
  @usage = str || block
24
24
  end
25
25
 
26
+ def identified_by
27
+ @identifiers
28
+ end
29
+
26
30
  def exit_with_error(msg, status)
27
31
  STDERR.puts msg
28
32
  exit status
@@ -47,8 +47,12 @@ module Shaf
47
47
  settings_file = 'config/settings.yml'
48
48
  template_file = File.expand_path("../templates/#{settings_file}.erb", __FILE__)
49
49
  content = File.read(template_file)
50
+ locals = {
51
+ project_name: project_name.capitalize,
52
+ default_port: "<%= ENV.fetch('PORT', 3000) %>"
53
+ }
50
54
  File.write settings_file,
51
- erb(content, project_name: project_name.capitalize)
55
+ erb(content, locals)
52
56
  end
53
57
 
54
58
  def erb(content, locals = {})
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require 'rack'
2
3
 
3
4
  module Shaf
4
5
  module Command
@@ -16,7 +17,10 @@ module Shaf
16
17
  def call
17
18
  Settings.port = options[:port] if options[:port]
18
19
  bootstrap
19
- App.run!
20
+ Rack::Server.start(
21
+ app: App,
22
+ Port: Settings.port
23
+ )
20
24
  end
21
25
  end
22
26
  end
@@ -1,23 +1,24 @@
1
1
  ---
2
2
  default: &default
3
- project_name: <%= project_name %>
4
- public_folder: frontend/assets
5
- views_folder: frontend/views
3
+ default_authentication_realm: api
6
4
  documents_dir: doc/api
7
- migrations_dir: db/migrations
8
5
  fixtures_dir: spec/fixtures
9
- paginate_per_page: 25
6
+ hostname: localhost
10
7
  http_cache: on
11
8
  http_cache_max_age_long: 86400 # 60 * 60 * 24 = 1 day
12
9
  http_cache_max_age_short: 3600 # 60 * 60 = 1 hour
13
- hostname: localhost
10
+ migrations_dir: db/migrations
11
+ paginate_per_page: 25
12
+ port: <%= default_port %>
13
+ project_name: <%= project_name %>
14
14
  protocol: http
15
- port: 3000
15
+ public_folder: frontend/assets
16
+ views_folder: frontend/views
16
17
 
17
18
  production:
18
19
  <<: *default
19
- port: <%= ENV.fetch('PORT', 443) %>
20
20
  base_uri: https://my.public.shaf.api.com
21
+ port: <%= ENV.fetch('PORT', 443) %>
21
22
 
22
23
  development:
23
24
  <<: *default
@@ -106,26 +106,20 @@ module Shaf
106
106
  # edit_book_uri_template => /books/:id/edit
107
107
  #
108
108
  class CreateUriMethods
109
- def initialize(name, base: nil, plural_name: nil, only: nil, except: nil)
109
+ def initialize(name, plural_name: nil, base: nil, namespace: nil, only: nil, except: nil)
110
110
  @name = name.to_s
111
- @base = base&.sub(%r(/\Z), '') || ''
112
111
  @plural_name = plural_name&.to_s || Utils::pluralize(name.to_s)
112
+ @base = base&.sub(%r(/\Z), '') || ''
113
+ @base = "/#{namespace}" if namespace && !base
114
+ @namespace = namespace
113
115
  @only = only
114
116
  @except = except
115
117
  @added_path_methods = []
116
118
  end
117
119
 
118
120
  def call
119
- if plural_name == name
120
- # Deprecated code path
121
- # Remove this branch and only keep the `else` behavior when dropping
122
- # support for this
123
- register_resource_helper_by_arg
124
- else
125
- register_collection_helper
126
- register_resource_helper
127
- end
128
-
121
+ register_collection_helper
122
+ register_resource_helper
129
123
  register_new_resource_helper
130
124
  register_edit_resource_helper
131
125
  @added_path_methods
@@ -133,51 +127,38 @@ module Shaf
133
127
 
134
128
  private
135
129
 
136
- attr_reader :name, :base, :plural_name, :only, :except
130
+ attr_reader :name, :plural_name, :base, :namespace, :only, :except
137
131
 
138
132
  def register_collection_helper
139
133
  return if skip? :collection
140
134
 
135
+ method = method_name(plural_name, name == plural_name)
141
136
  template_uri = "#{base}/#{plural_name}".freeze
142
- method_name = plural_name
143
- method_name = "#{name}_collection" if name == @plural_name
144
- register(method_name, template_uri)
137
+ register(method, template_uri)
145
138
  end
146
139
 
147
140
  def register_resource_helper
148
141
  return if skip? :resource
149
142
 
143
+ method = method_name(name)
150
144
  template_uri = "#{base}/#{plural_name}/:id".freeze
151
- register(name, template_uri)
152
- end
153
-
154
- # If a resource has the same singular and plural names, then this method
155
- # should be used. It will return the resource uri when a resource is given
156
- # as argument and the resources uri when no arguments are provided.
157
- def register_resource_helper_by_arg
158
- return register_resource_helper if skip? :collection
159
- register_collection_helper
160
- return if skip? :new
161
-
162
- resource_template_uri = "#{base}/#{plural_name}/:id"
163
- collection_template_uri = "#{base}/#{plural_name}"
164
-
165
- builder = MethodBuilder.new(name, resource_template_uri, alt_uri: collection_template_uri)
166
- @added_path_methods << builder.call
145
+ register(method, template_uri)
167
146
  end
168
147
 
169
148
  def register_new_resource_helper
170
149
  return if skip? :new
171
150
 
151
+ method = method_name(name)
172
152
  template_uri = "#{base}/#{name}/form".freeze
173
- register("new_#{name}", template_uri)
153
+ register("new_#{method}", template_uri)
174
154
  end
175
155
 
176
156
  def register_edit_resource_helper
177
157
  return if skip? :edit
178
158
 
159
+ method = method_name(name)
179
160
  template_uri = "#{base}/#{plural_name}/:id/edit".freeze
180
- register("edit_#{name}", template_uri)
161
+ register("edit_#{method}", template_uri)
181
162
  end
182
163
 
183
164
  def register(name, template_uri)
@@ -194,11 +175,14 @@ module Shaf
194
175
  false
195
176
  end
196
177
  end
178
+
179
+ def method_name(name, collection = false)
180
+ collection_str = "collection" if collection
181
+ [namespace, name, collection_str].compact.join('_')
182
+ end
197
183
  end
198
184
 
199
185
  class MethodBuilder
200
- NO_GIVEN_VALUE = Object.new
201
-
202
186
  def self.query_string(query)
203
187
  return '' unless query&.any?
204
188
 
@@ -211,10 +195,9 @@ module Shaf
211
195
  [query_str, fragment_str].join
212
196
  end
213
197
 
214
- def initialize(name, uri, alt_uri: nil)
198
+ def initialize(name, uri)
215
199
  @name = name
216
200
  @uri = uri.dup.freeze
217
- @alt_uri = alt_uri.dup.freeze
218
201
  end
219
202
 
220
203
  def call
@@ -223,16 +206,12 @@ module Shaf
223
206
  raise exception.new(name, uri_method_name)
224
207
  end
225
208
 
226
- if alt_uri.nil?
227
- build_methods
228
- else
229
- build_methods_with_optional_arg
230
- end
209
+ build_methods
231
210
  end
232
211
 
233
212
  private
234
213
 
235
- attr_reader :name, :uri, :alt_uri
214
+ attr_reader :name, :uri
236
215
 
237
216
  def build_methods
238
217
  UriHelperMethods.eval_method uri_method_string
@@ -243,15 +222,6 @@ module Shaf
243
222
  path_method_name.to_sym
244
223
  end
245
224
 
246
- def build_methods_with_optional_arg
247
- UriHelperMethods.eval_method uri_method_with_optional_arg_string
248
- UriHelperMethods.eval_method path_method_with_optional_arg_string
249
- UriHelperMethods.register(template_method_name, &template_proc)
250
- UriHelperMethods.register(legacy_template_method_name, &template_proc)
251
- UriHelperMethods.register(path_matcher_name, &path_matcher_proc)
252
- path_method_name.to_sym
253
- end
254
-
255
225
  def uri_method_name
256
226
  "#{name}_uri".freeze
257
227
  end
@@ -309,53 +279,6 @@ module Shaf
309
279
  RUBY
310
280
  end
311
281
 
312
- def uri_method_with_optional_arg_string
313
- base_uri = UriHelper.base_uri
314
- arg_no = extract_symbols(alt_uri).size
315
- <<~RUBY
316
- def #{uri_signature(uri: alt_uri, optional_args: 1)}
317
- query_str = Shaf::MethodBuilder.query_string(query)
318
- if arg#{arg_no}.nil?
319
- warn <<~DEPRECATION
320
-
321
- Deprecated use of collection uri helper:
322
- To get the collection uri use ##{name}_collection_uri instead of ##{uri_method_name}.
323
- Or pass an argument to ##{uri_method_name} to get the uri to a resource.
324
- \#{caller.find { |s| !s.match? %r{lib/shaf/extensions/resource_uris.rb} }}
325
-
326
- DEPRECATION
327
-
328
- \"#{base_uri}#{interpolated_uri_string(alt_uri)}\#{query_str}\".freeze
329
- else
330
- \"#{base_uri}#{interpolated_uri_string(uri)}\#{query_str}\".freeze
331
- end
332
- end
333
- RUBY
334
- end
335
-
336
- def path_method_with_optional_arg_string
337
- arg_no = extract_symbols(alt_uri).size
338
- <<~RUBY
339
- def #{path_signature(uri: alt_uri, optional_args: 1)}
340
- query_str = Shaf::MethodBuilder.query_string(query)
341
- if arg#{arg_no}.nil?
342
- warn <<~DEPRECATION
343
-
344
- Deprecated use of collection path helper:
345
- To get the collection path use ##{name}_collection_path instead of ##{path_method_name}.
346
- Or pass an argument to ##{path_method_name} to get the path to a resource.
347
- \#{caller.find { |s| !s.match? %r{lib/shaf/extensions} }}
348
-
349
- DEPRECATION
350
-
351
- \"#{interpolated_uri_string(alt_uri)}\#{query_str}\".freeze
352
- else
353
- \"#{interpolated_uri_string(uri)}\#{query_str}\".freeze
354
- end
355
- end
356
- RUBY
357
- end
358
-
359
282
  def extract_symbols(uri = @uri)
360
283
  uri.split('/').grep(/\A:.+/).map { |t| t[1..-1].to_sym }
361
284
  end
@@ -384,70 +307,29 @@ module Shaf
384
307
  end
385
308
 
386
309
  def template_proc
387
- uri, alt_uri = @uri, @alt_uri
388
-
389
- if alt_uri.nil?
390
- -> { uri }
391
- else
392
- deprecated_method = template_method_name
393
- replacing_method = "#{name}_collection_path_template"
394
-
395
- lambda do |collection = NO_GIVEN_VALUE|
396
- if collection != NO_GIVEN_VALUE
397
- warn <<~DEPRECATION
398
-
399
- Deprecated use of uri template helper with `collection` argument:
400
- Use #{replacing_method} instead of #{deprecated_method}"
401
- #{caller.find { |s| !s.match? %r{lib/shaf/extensions} }}
402
-
403
- DEPRECATION
404
- else
405
- collection = false
406
- end
407
-
408
- collection ? alt_uri : uri
409
- end
410
- end
310
+ uri = @uri
311
+ -> { uri }
411
312
  end
412
313
 
413
- def path_mather_patterns
414
- [
415
- uri.gsub(%r{:[^/]*}, '\w+'),
416
- alt_uri&.gsub(%r{:[^/]*}, '\w+')
417
- ].compact.map { |str| Regexp.new("\\A#{str}\\Z") }
314
+ def path_mather_pattern
315
+ pattern = uri.gsub(%r{:[^/]*}, '\w+')
316
+ Regexp.new("\\A#{pattern}\\Z")
418
317
  end
419
318
 
420
319
  def path_matcher_proc
421
- patterns = path_mather_patterns
422
-
423
- deprecated_method = path_matcher_name
424
- replacing_method = "#{name}_collection_path?"
425
-
426
- lambda do |path = nil, collection: NO_GIVEN_VALUE|
427
- if collection != NO_GIVEN_VALUE
428
- warn <<~DEPRECATION
429
-
430
- Deprecated use of uri predicate helper with `collection` argument:
431
- Use #{replacing_method} instead of #{deprecated_method}(collection: true)
432
- #{caller.find { |s| !s.match? %r{lib/shaf/extensions} }}
433
-
434
- DEPRECATION
435
- else
436
- collection = false
437
- end
320
+ pattern = path_mather_pattern
438
321
 
322
+ lambda do |path = nil|
439
323
  unless path
440
324
  r = request if respond_to? :request
441
- path = r.path_info if r&.respond_to? :path_info
442
-
443
- unless path
444
- raise(
445
- ArgumentError,
446
- "Uri must be given (or #{self} should respond to :request)"
447
- )
448
- end
325
+ path = r.path_info if r.respond_to? :path_info
326
+
327
+ raise(
328
+ ArgumentError,
329
+ "Uri must be given (or #{self} should respond to :request)"
330
+ ) unless path
449
331
  end
450
- pattern = collection ? patterns.last : patterns.first
332
+
451
333
  !!(pattern =~ path)
452
334
  end
453
335
  end
@@ -4,30 +4,17 @@ module Shaf
4
4
 
5
5
  Shaf::SUPPORTED_HTTP_METHODS.each do |m|
6
6
  define_method m do |path, **options, &block|
7
- collection = options.delete(:collection)
8
- path = rewrite_path(path, collection, m)
7
+ path = rewrite_path(path, m)
9
8
  super(path, **options, &block)
10
9
  end
11
10
  end
12
11
 
13
- def rewrite_path(path, collection, method)
12
+ def rewrite_path(path, method)
14
13
  return path unless path.is_a? Symbol
15
14
 
16
- warn <<~DEPRECATION unless collection.nil?
17
- Deprecated use of declaring route with collection keyword argument:
18
- Use `#{method} :#{path.to_s.sub(/_(path|uri)/, '_collection_path')} do`
19
- instead of `#{method} :#{path}, collection: #{collection} do`
20
- #{caller.find { |s| s.match?(/_controller.rb/) }}
21
-
22
- DEPRECATION
23
-
24
- method = "#{path}_template"
25
- send_args = [method]
26
- send_args << collection unless collection.nil?
27
- return send(*send_args) if respond_to? method
28
-
29
- method = "#{path}_path_template"
30
- return send(*send_args) if respond_to? method
15
+ ["#{path}_template", "#{path}_path_template"].each do |method|
16
+ return send(method) if respond_to? method
17
+ end
31
18
 
32
19
  raise UriHelperNotRegisterdError, <<~RUBY
33
20
  Undefined method '#{method}'. Did you forget to register a uri helper for #{path}?
@@ -1,11 +1,56 @@
1
+ require 'forwardable'
1
2
  require 'shaf/formable/form'
3
+ require 'shaf/immutable_attr'
2
4
 
3
5
  module Shaf
4
6
  module Formable
5
7
  class Builder
6
- InstanceAccessorType = Struct.new(:prefill?)
7
8
  DELEGATES = %i[title name action method type submit fields].freeze
8
9
 
10
+ class FormWrapper
11
+ extend Forwardable
12
+ extend Shaf::ImmutableAttr
13
+
14
+ attr_accessor :instance_accessor
15
+ immutable_reader :form
16
+
17
+ WRITER_DELEGATES = DELEGATES.map { |method| :"#{method}=" }
18
+ def_delegators :@form, :add_field, *WRITER_DELEGATES
19
+
20
+ def initialize(form, method_name: nil, instance_accessor: nil)
21
+ @form = form&.dup || Formable::Form.new
22
+ @method_name = method_name
23
+ @form.action = action_from(method_name) unless @form.action
24
+ @instance_accessor = instance_accessor
25
+ end
26
+
27
+ def action_from(method_name)
28
+ return unless method_name
29
+
30
+ (method_name.to_s.delete_suffix('_form')).to_sym
31
+ end
32
+
33
+ def method_name
34
+ name = @method_name || form.action
35
+
36
+ if name.nil?
37
+ nil
38
+ elsif name.to_s.end_with? '_form'
39
+ name.to_sym
40
+ else
41
+ :"#{name}_form"
42
+ end
43
+ end
44
+
45
+ def instance_accessor?
46
+ [:empty, :prefill].include? instance_accessor
47
+ end
48
+
49
+ def prefill?
50
+ instance_accessor == :prefill
51
+ end
52
+ end
53
+
9
54
  attr_reader :forms
10
55
 
11
56
  def initialize(&block)
@@ -15,48 +60,42 @@ module Shaf
15
60
  exec_with_form(block)
16
61
  end
17
62
 
18
- def instance_accessor_for(form)
19
- @instance_accessors[form.action]
20
- end
21
-
22
63
  private
23
64
 
24
- attr_reader :form
65
+ attr_reader :current
25
66
 
26
- def exec_with_form(block, action: nil)
27
- current, @form = form, new_form
28
- form.action = action if action
67
+ def exec_with_form(block, method_name: nil)
68
+ prev, @current = current, new_form(method_name)
29
69
  instance_exec(&block)
30
70
  ensure
31
- @form = current
71
+ @current = prev
32
72
  end
33
73
 
34
- def new_form
35
- (form&.dup || Formable::Form.new).tap { |f| @forms << f }
74
+ def new_form(method_name)
75
+ FormWrapper.new(current&.form, method_name: method_name).tap { |f| @forms << f }
36
76
  end
37
77
 
38
78
  def instance_accessor(prefill: true)
39
- acc = InstanceAccessorType.new(prefill)
40
- @instance_accessors[form.action] = acc
79
+ current.instance_accessor = prefill ? :prefill : :empty
41
80
  end
42
81
 
43
82
  DELEGATES.each do |name|
44
83
  define_method(name) do |arg|
45
- form.send(:"#{name}=", arg)
84
+ current.send(:"#{name}=", arg)
46
85
  end
47
86
  end
48
87
 
49
88
  def field(name, opts = {})
50
- form.add_field(name, opts)
89
+ current.add_field(name, opts)
51
90
  end
52
91
 
53
92
  def method_missing(method, *args, &block)
54
93
  return super unless args.empty? && block
55
- exec_with_form(block, action: method)
94
+ exec_with_form(block, method_name: method)
56
95
  end
57
96
 
58
- def respond_to_missing?(*)
59
- true
97
+ def respond_to_missing?(method, _include_private = false)
98
+ method.to_s.end_with?('_form') ? true : super
60
99
  end
61
100
  end
62
101
  end
@@ -12,14 +12,15 @@ module Shaf
12
12
  DEFAULT_SUBMIT = 'save'.freeze
13
13
 
14
14
  attr_accessor :resource
15
- immutable_accessor :title, :name, :href, :type, :submit, :self_link
16
- immutable_reader :fields, :action
15
+ attr_writer :name, :action
16
+ immutable_accessor :title, :href, :type, :submit, :self_link
17
+ immutable_reader :fields
17
18
 
18
19
  def initialize(params = {})
19
20
  @title = params[:title]
20
21
  @action = params[:action]
21
- @name = params[:name]&.to_sym || name_from(@action)
22
- @method = params[:method] ||= http_method_from(@action)
22
+ @name = params[:name]
23
+ @method = params[:method]
23
24
  @type = params[:type] || DEFAULT_TYPE
24
25
  @submit = params[:submit] || DEFAULT_SUBMIT
25
26
  @fields = (params[:fields] || {}).map do |name, args|
@@ -27,23 +28,25 @@ module Shaf
27
28
  end
28
29
  end
29
30
 
31
+ def name
32
+ (@name || name_from(action))&.to_sym
33
+ end
34
+
30
35
  def method=(http_method)
31
36
  @method = http_method.to_s.upcase
32
37
  end
33
38
 
34
39
  def method
35
- return unless @method
36
- @method.to_s.upcase
40
+ _method = @method || http_method_from(action)
41
+ _method.to_s.upcase if _method
37
42
  end
38
43
 
39
44
  def fields=(fields)
40
45
  @fields = fields.map { |name, args| Field.new(name, args) }
41
46
  end
42
47
 
43
- def action=(action)
44
- @action = action
45
- @name ||= name_from action
46
- @method ||= http_method_from action
48
+ def action
49
+ @action&.to_sym
47
50
  end
48
51
 
49
52
  def add_field(name, opts)