shaf 0.6.0 → 0.7.0

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