shaf 0.6.0 → 0.7.0

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: 5fa1ac79ab7ea9af45c8d160116ab1aee7ed964254927fe9045664930405e2c6
4
- data.tar.gz: bf9dc19468e7b25d5e0c94c8484558f89bd6ec84e47d4d00211c3d57029909fc
3
+ metadata.gz: 9123190de71ec1df3a8c53c32a8f7e26a72b42bf6255fe2e0613cd0ee5f15837
4
+ data.tar.gz: 53f39cd9d1283771a638a4f1a53f85e79e9f329b0dacb8f7dd3ce08ed54d8199
5
5
  SHA512:
6
- metadata.gz: d383a3b23dd5675fc3683a8b2c76407bcc9cf25ff17eb699b4cbd75898d053fdd1d1a2b8fb522eedf4fe8c7330a726dfc126d39508ce7c50c0a211b0ba6e8a86
7
- data.tar.gz: f03870ee03fdc20f04541c9bff9cde8a1d2fa1ef3b1a0a0a52b0a20724cee752a5abe3b6f5eb5ec330125c010f8bc1f85acd9e18eaa3f97884ff33d66fe087ea
6
+ metadata.gz: 9713237dc988ae3a336016338ad711d59766533a68f88db7bbec9da70ac349906f779abef11cf8e9fb3b3865b652120cc756f8a0bd6558d0a7406405b7122ee6
7
+ data.tar.gz: 5f80c980f49450f27e1b17b3a13b1d3b724c43c7ae75c297cce54807b1a2a99920159171be152da6dd0fa6d7c239dd0e1e42d4cd08307c3d91f393f730ec5038
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,4 +1,5 @@
1
1
  require 'shaf/extensions/resource_uris'
2
+ require 'shaf/extensions/controller_hooks'
2
3
  require 'shaf/extensions/current_user'
3
4
  require 'shaf/extensions/authorize'
4
5
  require 'shaf/extensions/symbolic_routes'
@@ -7,6 +8,7 @@ module Shaf
7
8
  def self.extensions
8
9
  [
9
10
  ResourceUris,
11
+ ControllerHooks,
10
12
  CurrentUser,
11
13
  Authorize,
12
14
  SymbolicRoutes
@@ -0,0 +1,47 @@
1
+ require 'sinatra/base'
2
+
3
+ module Shaf
4
+ module ControllerHooks
5
+ def before_action(method_name = nil, **options, &block)
6
+ __action_hook(:before, method_name, block, options)
7
+ end
8
+
9
+ def after_action(method_name = nil, **options, &block)
10
+ __action_hook(:after, method_name, block, options)
11
+ end
12
+
13
+ private
14
+
15
+ def __action_hook(hook, method_name, block, **options)
16
+ only = Array(options[:only]) if options.key? :only
17
+ except = Array(options[:except]) if options.key? :except
18
+
19
+ path_helpers.each do |helper|
20
+ next if only && !only.include?(helper)
21
+ next if except&.include? helper
22
+ pattern = __path_pattern(helper)
23
+
24
+ if method_name
25
+ send(hook, pattern) { send(method_name) }
26
+ elsif block
27
+ send(hook, pattern, &block)
28
+ else
29
+ log.warn <<~RUBY
30
+ #{hook}_action without block (options: #{options}).
31
+ Specify method or pass a block!
32
+ RUBY
33
+ end
34
+ end
35
+ end
36
+
37
+ def __path_pattern(path_helper)
38
+ uri_helper = path_helper.to_s.sub(/path\Z/, 'uri')
39
+ template_method = "#{uri_helper}_template".to_sym
40
+ template = send template_method
41
+ str = template.gsub(%r{:[^/]*}, '\w+')
42
+ Regexp.new("#{str}/?")
43
+ end
44
+ end
45
+
46
+ Sinatra.register ControllerHooks
47
+ end
@@ -2,14 +2,25 @@ require 'sinatra/base'
2
2
 
3
3
  module Shaf
4
4
  module ResourceUris
5
+ class UriHelperMethodAlreadyExistError < Error
6
+ def initialize(resource_name, method_name)
7
+ super(
8
+ "resource uri #{resource_name} can't be registered. " \
9
+ "Method :#{method_name} already exist!"
10
+ )
11
+ end
12
+ end
13
+
5
14
  def resource_uris_for(*args)
6
- CreateUriMethods.new(*args).call
15
+ result = CreateUriMethods.new(*args).call
16
+ UriHelperMethods.add_path_helpers(self, result)
7
17
 
8
18
  include UriHelper unless self < UriHelper
9
19
  end
10
20
 
11
21
  def register_uri(name, uri)
12
- MethodBuilder.new(name, uri).call
22
+ result = MethodBuilder.new(name, uri).call
23
+ UriHelperMethods.add_path_helpers(self, result)
13
24
 
14
25
  include UriHelper unless self < UriHelper
15
26
  end
@@ -18,12 +29,39 @@ module Shaf
18
29
  Sinatra.register ResourceUris
19
30
 
20
31
  module UriHelperMethods
21
- def self.register(name, &block)
22
- define_method(name, &block)
32
+ class << self
33
+ def register(name, &block)
34
+ define_method(name, &block)
35
+ end
36
+
37
+ def eval_method(str)
38
+ class_eval str
39
+ end
40
+
41
+ def add_path_helpers(clazz, methods)
42
+ @path_helpers ||= {}
43
+ @path_helpers[clazz] ||= []
44
+ @path_helpers[clazz].concat Array(methods)
45
+ end
46
+
47
+ def path_helpers_for(clazz = nil)
48
+ @path_helpers ||= {}
49
+ return @path_helpers unless clazz
50
+ return [] unless @path_helpers.key?(clazz)
51
+ @path_helpers[clazz] ||= []
52
+ end
53
+
54
+ # For cleaning up after tests
55
+ def remove_all
56
+ helpers = instance_methods - [:path_helpers]
57
+ remove_method(*helpers)
58
+ @path_helpers = {}
59
+ end
23
60
  end
24
61
 
25
- def self.eval_method(str)
26
- class_eval str
62
+ def path_helpers
63
+ clazz = is_a?(Class) ? self : self.class
64
+ UriHelperMethods.path_helpers_for clazz
27
65
  end
28
66
  end
29
67
 
@@ -46,13 +84,13 @@ module Shaf
46
84
  # This class register uri helper methods like:
47
85
  # books_uri => /books
48
86
  # book_uri(book) => /books/5
49
- # new_book_uri => /books/form
87
+ # new_book_uri => /book/form
50
88
  # edit_book_uri(book) => /books/5/edit
51
89
  #
52
90
  # And uri template methods:
53
91
  # books_uri_template => /books
54
92
  # book_uri_template => /books/:id
55
- # new_book_uri_template => /books/form
93
+ # new_book_uri_template => /book/form
56
94
  # edit_book_uri_template => /books/:id/edit
57
95
  #
58
96
  class CreateUriMethods
@@ -61,6 +99,7 @@ module Shaf
61
99
  @name = name.to_s
62
100
  @base = base&.sub(%r(/\Z), '') || ''
63
101
  @plural_name = plural_name&.to_s || Utils::pluralize(name.to_s)
102
+ @added_path_methods = []
64
103
  end
65
104
 
66
105
  def call
@@ -72,6 +111,7 @@ module Shaf
72
111
  end
73
112
  register_new_resource_uri
74
113
  register_edit_resource_uri
114
+ @added_path_methods
75
115
  end
76
116
 
77
117
  private
@@ -95,11 +135,12 @@ module Shaf
95
135
  resource_template_uri = "#{base}/#{plural_name}/:id"
96
136
  collection_template_uri = "#{base}/#{plural_name}"
97
137
 
98
- MethodBuilder.new(name, resource_template_uri, alt_uri: collection_template_uri).call
138
+ builder = MethodBuilder.new(name, resource_template_uri, alt_uri: collection_template_uri)
139
+ @added_path_methods << builder.call
99
140
  end
100
141
 
101
142
  def register_new_resource_uri
102
- template_uri = "#{base}/#{plural_name}/form".freeze
143
+ template_uri = "#{base}/#{name}/form".freeze
103
144
  register("new_#{name}", template_uri)
104
145
  end
105
146
 
@@ -109,7 +150,8 @@ module Shaf
109
150
  end
110
151
 
111
152
  def register(name, template_uri)
112
- MethodBuilder.new(name, template_uri).call
153
+ builder = MethodBuilder.new(name, template_uri)
154
+ @added_path_methods << builder.call
113
155
  end
114
156
  end
115
157
 
@@ -127,8 +169,8 @@ module Shaf
127
169
 
128
170
  def call
129
171
  if UriHelper.respond_to? uri_method_name
130
- raise "resource uri #{@name} can't be registered. " \
131
- "Method :#{uri_method_name} already exist!"
172
+ exception = ResourceUris::UriHelperMethodAlreadyExistError
173
+ raise exception.new(@name, uri_method_name)
132
174
  end
133
175
 
134
176
  if @alt_uri.nil?
@@ -144,12 +186,18 @@ module Shaf
144
186
  UriHelperMethods.eval_method uri_method_string
145
187
  UriHelperMethods.eval_method path_method_string
146
188
  UriHelperMethods.register(template_method_name, &template_proc)
189
+ UriHelperMethods.register(legacy_template_method_name, &template_proc)
190
+ UriHelperMethods.register(path_matcher_name, &path_matcher_proc)
191
+ path_method_name.to_sym
147
192
  end
148
193
 
149
194
  def build_methods_with_optional_arg
150
195
  UriHelperMethods.eval_method uri_method_with_optional_arg_string
151
196
  UriHelperMethods.eval_method path_method_with_optional_arg_string
152
197
  UriHelperMethods.register(template_method_name, &template_proc)
198
+ UriHelperMethods.register(legacy_template_method_name, &template_proc)
199
+ UriHelperMethods.register(path_matcher_name, &path_matcher_proc)
200
+ path_method_name.to_sym
153
201
  end
154
202
 
155
203
  def uri_method_name
@@ -160,7 +208,15 @@ module Shaf
160
208
  "#{@name}_path".freeze
161
209
  end
162
210
 
211
+ def path_matcher_name
212
+ :"#{path_method_name}?"
213
+ end
214
+
163
215
  def template_method_name
216
+ "#{path_method_name}_template".freeze
217
+ end
218
+
219
+ def legacy_template_method_name
164
220
  "#{uri_method_name}_template".freeze
165
221
  end
166
222
 
@@ -268,5 +324,32 @@ module Shaf
268
324
  ->(collection = false) { collection ? alt_uri : uri }
269
325
  end
270
326
  end
327
+
328
+ def path_mather_patterns
329
+ [
330
+ @uri.gsub(%r{:[^/]*}, '\w+'),
331
+ @alt_uri&.gsub(%r{:[^/]*}, '\w+')
332
+ ].compact.map { |str| Regexp.new("\\A#{str}\\Z") }
333
+ end
334
+
335
+ def path_matcher_proc
336
+ patterns = path_mather_patterns
337
+
338
+ lambda do |path = nil, collection: false|
339
+ unless path
340
+ r = request if respond_to? :request
341
+ path = r.path_info if r&.respond_to? :path_info
342
+
343
+ unless path
344
+ raise(
345
+ ArgumentError,
346
+ "Uri must be given (or #{self} should respond to :request)"
347
+ )
348
+ end
349
+ end
350
+ pattern = collection ? patterns.last : patterns.first
351
+ !!(pattern =~ path)
352
+ end
353
+ end
271
354
  end
272
355
  end
@@ -8,13 +8,13 @@ module Shaf
8
8
  immutable_reader :name, :type, :value, :label, :required
9
9
 
10
10
  HTML_TYPE_MAPPINGS = {
11
- 'string' => 'text',
12
- 'boolean' => 'checkbox',
11
+ string: 'text',
12
+ boolean: 'checkbox'
13
13
  }.freeze
14
14
 
15
15
  def initialize(name, params = {})
16
16
  @name = name
17
- @type = params[:type]
17
+ @type = params[:type]&.to_sym
18
18
  @label = params[:label]
19
19
  @has_value = params.key? :value
20
20
  @value = params[:value]
@@ -69,7 +69,7 @@ module Shaf
69
69
  private
70
70
 
71
71
  def name_from(action)
72
- :"#{action}-form" if action
72
+ :"#{action.to_s.tr('_', '-')}-form" if action
73
73
  end
74
74
 
75
75
  def http_method_from(action)
@@ -6,43 +6,43 @@ class <%= controller_class_name %> < BaseController
6
6
 
7
7
  resource_uris_for :<%= name %>
8
8
 
9
- get :<%= plural_name %>_uri do
9
+ get :<%= plural_name %>_path do
10
10
  authorize! :read
11
11
  collection = paginate(<%= model_class_name %>.order(:created_at).reverse)
12
12
  respond_with_collection collection, serializer: <%= serializer_class_name %>
13
13
  end
14
14
 
15
- get :new_<%= name %>_uri do
15
+ get :new_<%= name %>_path do
16
16
  authorize! :read
17
17
  cache_control(:private, http_cache_max_age: :short)
18
18
  respond_with create_form
19
19
  end
20
20
 
21
- post :<%= plural_name %>_uri do
21
+ post :<%= plural_name %>_path do
22
22
  authorize! :write
23
23
  <%= name %> = <%= model_class_name %>.create(<%= name %>_params)
24
24
  headers({ "Location" => <%= name %>_uri(<%= name %>) })
25
25
  respond_with <%= name %>, status: 201
26
26
  end
27
27
 
28
- get :<%= name %>_uri do
28
+ get :<%= name %>_path do
29
29
  authorize! :read
30
30
  respond_with <%= name %>
31
31
  end
32
32
 
33
- get :edit_<%= name %>_uri do
33
+ get :edit_<%= name %>_path do
34
34
  authorize! :read
35
35
  cache_control(:private, http_cache_max_age: :short)
36
36
  respond_with edit_form
37
37
  end
38
38
 
39
- put :<%= name %>_uri do
39
+ put :<%= name %>_path do
40
40
  authorize! :write
41
41
  <%= name %>.update(<%= name %>_params)
42
42
  respond_with <%= name %>
43
43
  end
44
44
 
45
- delete :<%= name %>_uri do
45
+ delete :<%= name %>_path do
46
46
  authorize! :write
47
47
  <%= name %>.destroy
48
48
  status 204
@@ -30,7 +30,7 @@ describe <%= model_class_name %>, type: :integration do
30
30
  <% end -%>
31
31
  end
32
32
  end
33
-
33
+ <% if params.size > 0 %>
34
34
  it "can create <%= plural_name %>" do
35
35
  get <%= plural_name %>_uri
36
36
 
@@ -88,6 +88,7 @@ describe <%= model_class_name %>, type: :integration do
88
88
  status.must_equal 200
89
89
  link_rels.must_include(:self)
90
90
  end
91
+ <% end -%>
91
92
 
92
93
  it "<%= plural_name %> can be deleted" do
93
94
  <%= name %> = <%= model_class_name %>.create
data/lib/shaf/tasks.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'shaf/tasks/test_task'
2
2
  require 'shaf/tasks/db_task'
3
3
  require 'shaf/tasks/api_doc_task'
4
+ require 'shaf/tasks/routes_task'
4
5
 
5
6
  module Shaf
6
7
  include Tasks # includes task classes rather than methods
@@ -0,0 +1,28 @@
1
+ module Shaf
2
+ module Tasks
3
+ class RoutesTask
4
+ include Rake::DSL
5
+
6
+ def initialize(*)
7
+ desc "List path helpers"
8
+ task :routes do
9
+ require 'shaf/utils'
10
+ require 'config/database'
11
+
12
+ extend Shaf::Utils
13
+ bootstrap
14
+
15
+ UriHelperMethods.path_helpers_for.each do |controller, methods|
16
+ puts "\n#{controller}:"
17
+ methods.each do |method|
18
+ template_method = "#{method}_template".to_sym
19
+ puts sprintf( "%-60s%s" , method, controller.send(template_method))
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ RoutesTask.new
27
+ end
28
+ end
data/lib/shaf/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Shaf
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
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.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sammy Henningsson
@@ -30,7 +30,7 @@ cert_chain:
30
30
  ZMhjYR7sRczGJx+GxGU2EaR0bjRsPVlC4ywtFxoOfRG3WaJcpWGEoAoMJX6Z0bRv
31
31
  M40=
32
32
  -----END CERTIFICATE-----
33
- date: 2018-11-14 00:00:00.000000000 Z
33
+ date: 2018-11-24 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rake
@@ -133,6 +133,7 @@ files:
133
133
  - lib/shaf/errors.rb
134
134
  - lib/shaf/extensions.rb
135
135
  - lib/shaf/extensions/authorize.rb
136
+ - lib/shaf/extensions/controller_hooks.rb
136
137
  - lib/shaf/extensions/current_user.rb
137
138
  - lib/shaf/extensions/resource_uris.rb
138
139
  - lib/shaf/extensions/symbolic_routes.rb
@@ -188,6 +189,7 @@ files:
188
189
  - lib/shaf/tasks.rb
189
190
  - lib/shaf/tasks/api_doc_task.rb
190
191
  - lib/shaf/tasks/db_task.rb
192
+ - lib/shaf/tasks/routes_task.rb
191
193
  - lib/shaf/tasks/test_task.rb
192
194
  - lib/shaf/upgrade.rb
193
195
  - lib/shaf/upgrade/manifest.rb
metadata.gz.sig CHANGED
Binary file