flame 4.11.3.2 → 4.12.2

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
  SHA1:
3
- metadata.gz: b56a12a13e9cda2bdb36285b8f7051597d773875
4
- data.tar.gz: 8edf353e69d9254ad11ad1cff5cf8eca14519096
3
+ metadata.gz: 3b3c22d674ae570e3f8f2fd8874ec54f87dfb39b
4
+ data.tar.gz: a8ab56284dc70eb6babcf86a2dd80281757278dd
5
5
  SHA512:
6
- metadata.gz: eae397ed310ea64aaf0a07989655b0820734bffe9a9c1b62fda06ce75d6495f78496f9bc61e16ef7fe2f3de1207d76ff2f7c4c419e5c2b51ed6280e925305040
7
- data.tar.gz: 61723f2b18787782051b94bef9d4be923f93a3755d6b822576309e02f5e1b68b232025addbb9c127eae8717304c179e55eab879f06ea02b622ef847d60b265fe
6
+ metadata.gz: affe6a9c49a9eb2bd31ea0ed63540451e66a9986a35ed5a2d65cfd66363b13e0452eef7f8f194a00552203dfabfde31cd06550ac033256d04421b14d9398fe72
7
+ data.tar.gz: c40433fa6ef393e1d3630ea4817aeb490639cdb2c16934849947c88705b063c18ca452db88d5b5ee8091ab5acd3e7dee37c3e2bae946e6d74b0dc82914a95e37
data/bin/flame CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'thor'
4
5
  require 'fileutils'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack'
2
4
 
3
5
  require_relative 'flame/application'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'router'
2
4
  require_relative 'dispatcher'
3
5
 
@@ -56,7 +58,7 @@ module Flame
56
58
  ## defaults
57
59
  ## end
58
60
  def self.mount(ctrl, path = nil, &block)
59
- router.add_controller(ctrl, path, block)
61
+ router.add_controller(ctrl, path, &block)
60
62
  end
61
63
 
62
64
  ## Router for routing
@@ -71,7 +73,7 @@ module Flame
71
73
  ## Initialize default for config directories
72
74
  def self.default_config_dirs(root_dir:)
73
75
  result = { root_dir: File.realpath(root_dir) }
74
- %i(public views config tmp).each do |key|
76
+ %i[public views config tmp].each do |key|
75
77
  result[:"#{key}_dir"] = proc { File.join(config[:root_dir], key.to_s) }
76
78
  end
77
79
  result
@@ -17,7 +17,7 @@ module Flame
17
17
  def_delegators(
18
18
  :@dispatcher,
19
19
  :config, :request, :params, :halt, :session, :response, :status, :body,
20
- :default_body, :content_type
20
+ :default_body
21
21
  )
22
22
 
23
23
  ## Initialize the controller for request execution
@@ -58,12 +58,12 @@ module Flame
58
58
  # Set the Content-Disposition to "attachment" with the specified filename,
59
59
  # instructing the user agents to prompt to save.
60
60
  def attachment(filename = nil, disposition = :attachment)
61
- content_dis = 'Content-Disposition'.freeze
61
+ content_dis = 'Content-Disposition'
62
62
  response[content_dis] = disposition.to_s
63
63
  return unless filename
64
64
  response[content_dis] << "; filename=\"#{File.basename(filename)}\""
65
65
  ext = File.extname(filename)
66
- content_type(ext) unless ext.empty?
66
+ response.content_type = ext unless ext.empty?
67
67
  end
68
68
 
69
69
  ## Render a template with `Flame::Render` (based on Tilt-engine)
@@ -88,7 +88,7 @@ module Flame
88
88
  ## @param method [Symbol] name of the controller method
89
89
  def execute(method)
90
90
  # send method
91
- body send(method, *select_args(method))
91
+ body send(method, *select_args(method).values)
92
92
  end
93
93
 
94
94
  ## Default method for Internal Server Error, can be inherited
@@ -98,14 +98,13 @@ module Flame
98
98
 
99
99
  private
100
100
 
101
- def select_args(method)
102
- parameters = self.class.instance_method(method).parameters
103
- params_select = proc do |type|
104
- params.values_at(
105
- *parameters.select { |par| par.first == type }.map(&:last)
106
- )
101
+ def select_args(action)
102
+ # p action, params, parameters
103
+ method(action).parameters.each_with_object({}) do |parameter, result|
104
+ key = parameter.last
105
+ next if params[key].nil?
106
+ result[key] = params[key]
107
107
  end
108
- params_select.call(:req) + params_select.call(:opt).compact
109
108
  end
110
109
 
111
110
  def add_controller_class(args)
@@ -119,7 +118,7 @@ module Flame
119
118
  ## Default root path of the controller for requests
120
119
  def default_path
121
120
  modules = name.underscore.split('/')
122
- parts = modules[-1].split('_') - %w(index controller ctrl)
121
+ parts = modules[-1].split('_') - %w[index controller ctrl]
123
122
  return modules[-2] if parts.empty?
124
123
  parts.join('_')
125
124
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flame
2
4
  class Dispatcher
3
5
  ## Helper class for cookies
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'gorilla-patch/symbolize'
2
4
 
3
5
  require_relative 'cookies'
@@ -25,9 +27,9 @@ module Flame
25
27
  ## Start of execution the request
26
28
  def run!
27
29
  catch :halt do
28
- try_route ||
29
- try_static ||
30
+ try_static ||
30
31
  try_static(File.join(__dir__, '..', '..', 'public')) ||
32
+ try_route ||
31
33
  halt(404)
32
34
  end
33
35
  response.write body
@@ -76,12 +78,6 @@ module Flame
76
78
  @app.config
77
79
  end
78
80
 
79
- ## Access to Content-Type header of response
80
- def content_type(ext = nil)
81
- return response[Rack::CONTENT_TYPE] unless ext
82
- response[Rack::CONTENT_TYPE] = Rack::Mime.mime_type(ext)
83
- end
84
-
85
81
  ## Build a path to the given controller and action, with any expected params
86
82
  ##
87
83
  ## @param ctrl [Flame::Controller] class of controller
@@ -96,32 +92,30 @@ module Flame
96
92
  def path_to(ctrl, action = :index, args = {})
97
93
  route = @app.class.router.find_route(controller: ctrl, action: action)
98
94
  raise Errors::RouteNotFoundError.new(ctrl, action) unless route
99
- params = Rack::Utils.build_nested_query args.delete(:params)
95
+ query = Rack::Utils.build_nested_query args.delete(:params)
96
+ query = nil if query&.empty?
100
97
  path = route.assign_arguments(args)
101
98
  path = '/' if path.empty?
102
- path << ("?#{params}" if params).to_s
99
+ URI::Generic.build(path: path, query: query).to_s
103
100
  end
104
101
 
105
102
  ## Interrupt the execution of route, and set new optional data
106
103
  ## (otherwise using existing)
107
- ## @param new_status_or_body [Integer, String]
108
- ## set new HTTP status code or new body
109
- ## @param new_body [String] set new body
110
- ## @param new_headers [String] merge new headers
104
+ ## @param new_status [Integer, nil]
105
+ ## set new HTTP status code
106
+ ## @param new_body [String, nil] set new body
107
+ ## @param new_headers [Hash, nil] merge new headers
108
+ ## @example Halt, no change status or body
109
+ ## halt
111
110
  ## @example Halt with 500, no change body
112
111
  ## halt 500
113
112
  ## @example Halt with 404, render template
114
113
  ## halt 404, render('errors/404')
115
114
  ## @example Halt with 200, set new headers
116
115
  ## halt 200, 'Cats!', 'Content-Type' => 'animal/cat'
117
- def halt(new_status_or_body = nil, new_body = nil, new_headers = {})
118
- case new_status_or_body
119
- when String then new_body = new_status_or_body
120
- when Integer then status new_status_or_body
121
- end
122
- # new_status.is_a?(String) ? () : (status new_status)
123
- body new_body if new_body
124
- default_body_of_nearest_route if body.empty?
116
+ def halt(new_status = nil, new_body = nil, new_headers = {})
117
+ status new_status if new_status
118
+ body new_body || (default_body_of_nearest_route if body.empty?)
125
119
  response.headers.merge!(new_headers)
126
120
  throw :halt
127
121
  end
@@ -134,7 +128,7 @@ module Flame
134
128
  "#{error.class} - #{error.message}:",
135
129
  *error.backtrace
136
130
  ].join("\n\t")
137
- @env['rack.errors'].puts(error_message)
131
+ @env[Rack::RACK_ERRORS].puts(error_message)
138
132
  end
139
133
 
140
134
  ## Generate default body of error page
@@ -152,17 +146,17 @@ module Flame
152
146
  path_parts: request.path_parts
153
147
  )
154
148
  return nil unless route
149
+ status 200
155
150
  execute_route(route)
156
151
  end
157
152
 
158
153
  ## Execute route
159
154
  ## @param route [Flame::Route] route that must be executed
160
- def execute_route(route)
161
- status 200
155
+ def execute_route(route, action = route.action)
162
156
  params.merge!(route.arguments(request.path_parts))
163
157
  # route.execute(self)
164
158
  controller = route.controller.new(self)
165
- controller.send(:execute, route.action)
159
+ controller.send(:execute, action)
166
160
  rescue => exception
167
161
  # p 'rescue from dispatcher'
168
162
  dump_error(exception)
@@ -182,8 +176,8 @@ module Flame
182
176
  ## or it's `default_body` method not defined
183
177
  return default_body unless route
184
178
  ## Execute `default_body` method for the founded route
185
- route.controller.new(self).send(:execute, :default_body)
186
- body default_body if body.empty?
179
+ execute_route(route, :default_body)
180
+ default_body if body.empty?
187
181
  end
188
182
  end
189
183
  end
@@ -1,60 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flame
2
4
  module Errors
3
- module RouterError
4
- ## Error for Flame::Router.compare_actions
5
- class ActionsError < StandardError
6
- def initialize(ctrl, extra_actions)
7
- @ctrl = ctrl
8
- @extra_actions = extra_actions
9
- end
10
- end
11
-
12
- ## Error if routes have more actions, than controller
13
- class ExtraRoutesActionsError < ActionsError
14
- def message
15
- "Controller '#{@ctrl}' has no methods" \
16
- " '#{@extra_actions.join(', ')}' from routes"
17
- end
18
- end
19
-
20
- ## Error if controller has not assigned in routes actions
21
- class ExtraControllerActionsError < ActionsError
22
- def message
23
- "Routes for '#{@ctrl}' has no methods" \
24
- " '#{@extra_actions.join(', ')}'"
25
- end
26
- end
27
-
28
- ## Error for Flame::Router::RouteRefine.arguments_valid?
29
- class ArgumentsError < StandardError
30
- def initialize(ctrl, action, path, extra_args)
31
- @ctrl = ctrl
32
- @action = action
33
- @path = path
34
- @extra_args = extra_args
35
- end
36
- end
37
-
38
- ## Error if path has more arguments, than controller's method
39
- class ExtraPathArgumentsError < ArgumentsError
40
- def message
41
- "Method '#{@action}' from controller '#{@ctrl}'" \
42
- " does not know arguments '#{@extra_args.join(', ')}'" \
43
- " from path '#{@path}'"
44
- end
5
+ ## Error for Route initialization
6
+ class RouteArgumentsError < StandardError
7
+ def initialize(ctrl, action, path, extra)
8
+ @ctrl = ctrl
9
+ @action = action
10
+ @path = path
11
+ @extra = extra
12
+ @extra[:type_name] = {
13
+ req: 'required',
14
+ opt: 'optional'
15
+ }[@extra[:type]]
45
16
  end
46
17
 
47
- ## Error if path has no arguments, that controller's method required
48
- class ExtraActionArgumentsError < ArgumentsError
49
- def message
50
- "Path '#{@path}' does not contain required arguments" \
51
- " '#{@extra_args.join(', ')}' of method '#{@action}'" \
52
- " from controller '#{@ctrl}'"
18
+ def message
19
+ case @extra[:place]
20
+ when :ctrl
21
+ ## Error if path has no arguments, that controller's method has
22
+ "Path '#{@path}' has no #{@extra[:type_name]}" \
23
+ " arguments #{@extra[:args].inspect}"
24
+ when :path
25
+ ## Error if path has more arguments, than controller's method
26
+ "Action '#{@ctrl}##{@action}' has no #{@extra[:type_name]}" \
27
+ " arguments #{@extra[:args].inspect}"
53
28
  end
54
29
  end
55
30
  end
56
31
 
57
- ## Error for Flame::Router.find_path
32
+ ## Error for Flame::Dispatcher.path_to
58
33
  class RouteNotFoundError < StandardError
59
34
  def initialize(ctrl, method)
60
35
  @ctrl = ctrl
@@ -63,32 +38,19 @@ module Flame
63
38
 
64
39
  def message
65
40
  "Route with controller '#{@ctrl}' and method '#{@method}'" \
66
- ' not found in application routes'
41
+ ' not found in application routes'
67
42
  end
68
43
  end
69
44
 
70
- ## Error for Flame::Controller.path_to
45
+ ## Error for Flame::Dispatcher.path_to
71
46
  class ArgumentNotAssignedError < StandardError
72
- def initialize(path, path_part)
47
+ def initialize(path, argument)
73
48
  @path = path
74
- @path_part = path_part
75
- end
76
-
77
- def message
78
- "Argument '#{@path_part}' for path '#{@path}' is not assigned"
79
- end
80
- end
81
-
82
- ## Error for Flame::Router.find_path
83
- class UnexpectedTypeOfHookError < StandardError
84
- def initialize(hook, route)
85
- @hook = hook
86
- @route = route
49
+ @argument = argument
87
50
  end
88
51
 
89
52
  def message
90
- "Unexpected hook-block class '#{@hook.class}'" \
91
- " in route '#{@route}'"
53
+ "Argument '#{@argument}' for path '#{@path}' is not assigned"
92
54
  end
93
55
  end
94
56
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
 
3
5
  require 'tilt'
@@ -94,7 +96,7 @@ module Flame
94
96
  ## Find possible directories for the controller
95
97
  def controller_dirs
96
98
  parts = @ctrl.class.underscore.split('/').map do |part|
97
- (part.split('_') - %w(controller controllers ctrl)).join('_')
99
+ (part.split('_') - %w[controller controllers ctrl]).join('_')
98
100
  end
99
101
  combine_parts(parts).map! { |path| path.join('/') }
100
102
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flame
2
4
  ## Class for requests
3
5
  class Request < Rack::Request
@@ -1,5 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flame
2
4
  ## Class for responses
3
5
  class Response < Rack::Response
6
+ ## Set Content-Type header directly or by extension
7
+ ## @param value [String] value for header or extension of file
8
+ ## @return [String] setted value
9
+ ## @example Set value directly
10
+ ## content_type = 'text/css'
11
+ ## @example Set value by file extension
12
+ ## content_type = '.css'
13
+ def content_type=(value)
14
+ value = Rack::Mime.mime_type(value) if value.start_with? '.'
15
+ set_header Rack::CONTENT_TYPE, value
16
+ end
4
17
  end
5
18
  end
@@ -1,21 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'validators'
4
+
3
5
  module Flame
4
6
  class Router
5
- ARG_CHAR = ':'.freeze
6
- ARG_CHAR_OPT = '?'.freeze
7
+ ARG_CHAR = ':'
8
+ ARG_CHAR_OPT = '?'
7
9
 
8
10
  ## Class for Route in Router.routes
9
11
  class Route
10
12
  attr_reader :method, :controller, :action, :path, :path_parts
11
13
 
12
- def initialize(controller, action, method, path)
14
+ def initialize(controller, action, method, ctrl_path, action_path)
15
+ ## Merge action path with controller path
16
+ path = self.class.path_merge(ctrl_path, action_path)
13
17
  @controller = controller
14
18
  @action = action
15
19
  @method = method.to_sym.upcase
16
20
  ## MAKE PATH
17
21
  @path = path
18
- Validators::ArgumentsValidator.new(@controller, @path, @action).valid?
22
+ Validators::RouteArgumentsValidator.new(
23
+ @controller, action_path, @action
24
+ ).valid?
19
25
  @path_parts = @path.to_s.split('/').reject(&:empty?)
20
26
  freeze
21
27
  end
@@ -38,24 +44,38 @@ module Flame
38
44
  ## Assign arguments to path for `Controller.path_to`
39
45
  ## @param args [Hash] arguments for assigning
40
46
  def assign_arguments(args = {})
41
- parts = @path_parts.map { |part| assign_argument(part, args) }
42
- self.class.path_merge(parts.unshift(''))
47
+ parts = @path_parts.map { |part| assign_argument(part, args) }.compact
48
+ self.class.path_merge(parts.unshift(nil))
43
49
  end
44
50
 
45
51
  ## Extract arguments from request_parts for `execute`
46
52
  ## @param request_parts [Array] parts of the request (Array of String)
47
53
  def arguments(request_parts)
48
54
  @path_parts.each_with_index.with_object({}) do |(path_part, i), args|
49
- request_part = request_parts[i]
55
+ request_part = request_parts[i].to_s
50
56
  path_part_opt = path_part[1] == ARG_CHAR_OPT
51
57
  next args unless path_part[0] == ARG_CHAR
52
- break args if path_part_opt && request_part.nil?
58
+ break args if path_part_opt && request_part.empty?
53
59
  args[
54
60
  path_part[(path_part_opt ? 2 : 1)..-1].to_sym
55
61
  ] = URI.decode(request_part)
56
62
  end
57
63
  end
58
64
 
65
+ ## Method for Routes comparison
66
+ def ==(other)
67
+ %i[controller action method path_parts].reduce(true) do |result, method|
68
+ result && (
69
+ public_send(method) == other.public_send(method)
70
+ )
71
+ end
72
+ end
73
+
74
+ ## Compare by path parts count (more is matter)
75
+ def <=>(other)
76
+ other.path_parts.size <=> path_parts.size
77
+ end
78
+
59
79
  def self.path_merge(*parts)
60
80
  parts.join('/').gsub(%r{\/{2,}}, '/')
61
81
  end
@@ -79,19 +99,28 @@ module Flame
79
99
  end
80
100
 
81
101
  def compare_path_parts(request_parts)
82
- # p route_path
83
- req_path_parts = @path_parts.select { |part| part[1] != ARG_CHAR_OPT }
84
- return false if request_parts.count < req_path_parts.count
85
- # compare_parts(request_parts, self[:path_parts])
86
- request_parts.each_with_index do |request_part, i|
87
- path_part = @path_parts[i]
88
- # p request_part, path_part
89
- break false unless path_part
90
- next if path_part[0] == ARG_CHAR
91
- break false unless request_part == path_part
102
+ return false unless request_contain_required_path_parts?(request_parts)
103
+ [request_parts.size, @path_parts.size].max.times do |i|
104
+ break false unless compare_parts request_parts[i], @path_parts[i]
92
105
  end
93
106
  end
94
107
 
108
+ def compare_parts(request_part, path_part)
109
+ # p request_part, path_part
110
+ return unless path_part
111
+ return if request_part.nil? && path_part[1] != ARG_CHAR_OPT
112
+ # p request_part, path_part
113
+ return true if path_part[0] == ARG_CHAR
114
+ return true if request_part == path_part
115
+ end
116
+
117
+ def request_contain_required_path_parts?(request_parts)
118
+ req_path_parts = @path_parts.reject { |part| part[1] == ARG_CHAR_OPT }
119
+ fixed_path_parts = @path_parts.reject { |part| part[0] == ARG_CHAR }
120
+ (request_parts & fixed_path_parts) == fixed_path_parts &&
121
+ request_parts.count >= req_path_parts.count
122
+ end
123
+
95
124
  ## Helpers for `assign_arguments`
96
125
  def assign_argument(path_part, args = {})
97
126
  ## Not argument
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'route'
2
- require_relative 'validators'
3
4
 
4
5
  module Flame
5
6
  ## Router class for routing
@@ -13,14 +14,13 @@ module Flame
13
14
 
14
15
  ## Add the controller with it's methods to routes
15
16
  ## @param ctrl [Flame::Controller] class of the controller which will be added
16
- ## @param path [String] root path for controller's methods
17
- ## @param block [Proc, nil] block for routes refine
18
- def add_controller(ctrl, path, block = nil)
17
+ ## @param path [String, nil] root path for controller's methods
18
+ ## @yield block for routes refine
19
+ def add_controller(ctrl, path = nil, &block)
19
20
  ## @todo Add Regexp paths
20
21
 
21
22
  ## Add routes from controller to glob array
22
23
  route_refine = RouteRefine.new(self, ctrl, path, block)
23
- return unless Validators::ActionsValidator.new(route_refine).valid?
24
24
  concat_routes(route_refine)
25
25
  end
26
26
 
@@ -76,7 +76,7 @@ module Flame
76
76
  execute(&block)
77
77
  end
78
78
 
79
- %i(GET POST PUT PATCH DELETE).each do |request_method|
79
+ %i[GET POST PUT PATCH DELETE].each do |request_method|
80
80
  ## Define refine methods for all HTTP methods
81
81
  ## @overload post(path, action)
82
82
  ## Execute action on requested path and HTTP method
@@ -98,10 +98,11 @@ module Flame
98
98
  end
99
99
  ## Make path by controller method with parameners
100
100
  path = default_action_path(action, path) if prefix || path.nil?
101
- ## Merge action path with controller path
102
- path = Route.path_merge(@path, path)
103
- route = Route.new(@ctrl, action, method, path)
101
+ ## Init new Route
102
+ route = Route.new(@ctrl, action, method, @path, path)
103
+ ## Try to find route with the same action
104
104
  index = find_route_index(action: action)
105
+ ## Overwrite route if needed
105
106
  index ? @routes[index] = route : @routes.push(route)
106
107
  end
107
108
  end
@@ -132,7 +133,7 @@ module Flame
132
133
  ## @yield Block of code for routes refine
133
134
  def mount(ctrl, path = nil, &block)
134
135
  path = Route.path_merge(@path, path || ctrl.default_path)
135
- @router.add_controller(ctrl, path, block)
136
+ @router.add_controller(ctrl, path, &block)
136
137
  end
137
138
 
138
139
  private
@@ -141,7 +142,7 @@ module Flame
141
142
  def execute(&block)
142
143
  instance_exec(&block) if block
143
144
  defaults
144
- @routes.sort! { |a, b| b.path <=> a.path }
145
+ @routes.sort!
145
146
  end
146
147
 
147
148
  def find_route_index(attrs)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flame
2
4
  class Dispatcher
3
5
  ## Module for working with static files
@@ -19,7 +21,7 @@ module Flame
19
21
  def return_static(file)
20
22
  file_time = File.mtime(file)
21
23
  halt 304 if static_cached?(file_time)
22
- content_type File.extname(file)
24
+ response.content_type = File.extname(file)
23
25
  response[Rack::CACHE_CONTROL] = 'no-cache'
24
26
  response['Last-Modified'] = file_time.httpdate
25
27
  body File.read(file)
@@ -1,10 +1,11 @@
1
- require_relative 'route'
1
+ # frozen_string_literal: true
2
+
2
3
  require_relative 'errors'
3
4
 
4
5
  module Flame
5
6
  module Validators
6
7
  ## Compare arguments from path and from controller's action
7
- class ArgumentsValidator
8
+ class RouteArgumentsValidator
8
9
  def initialize(ctrl, path, action)
9
10
  @ctrl = ctrl
10
11
  @path = path
@@ -12,81 +13,54 @@ module Flame
12
13
  end
13
14
 
14
15
  def valid?
15
- ## Break path for ':arg' arguments
16
- @path_args = path_arguments(@path)
17
- ## Take all and required arguments from Controller#action
18
- @action_args = action_arguments(@action)
19
- ## Compare arguments from path and arguments from method
20
- no_extra_path_arguments? && no_extra_action_arguments?
16
+ ## Get hash of any extra arguments
17
+ extra = %i[req opt].find do |type|
18
+ found = extra_arguments(type).find do |place, args|
19
+ break { place: place, type: type, args: args } if args.any?
20
+ end
21
+ break found if found
22
+ end
23
+ ## Return true if no any extra argument
24
+ return true unless extra
25
+ ## Raise error with extra arguments
26
+ raise Errors::RouteArgumentsError.new(@ctrl, @action, @path, extra)
21
27
  end
22
28
 
23
29
  private
24
30
 
25
31
  ## Split path to args array
26
- def path_arguments(path)
27
- args = path.split('/').select { |part| part[0] == Router::ARG_CHAR }
28
- args.map do |arg|
29
- opt_arg = arg[1] == Router::ARG_CHAR_OPT
30
- arg[(opt_arg ? 2 : 1)..-1].to_sym
31
- end
32
+ def path_arguments
33
+ @path_arguments ||= @path.split('/')
34
+ .each_with_object(req: [], opt: []) do |part, hash|
35
+ ## Take only argument parts
36
+ next if part[0] != Router::ARG_CHAR
37
+ ## Clean argument from special chars
38
+ clean_part = part.delete(
39
+ Router::ARG_CHAR + Router::ARG_CHAR_OPT
40
+ ).to_sym
41
+ ## Memorize arguments
42
+ hash[part[1] != Router::ARG_CHAR_OPT ? :req : :opt] << clean_part
43
+ end
32
44
  end
33
45
 
34
46
  ## Take args from controller's action
35
- def action_arguments(action)
36
- parameters = @ctrl.instance_method(action).parameters
37
- req_parameters = parameters.select { |par| par[0] == :req }
38
- {
39
- all: parameters.map { |par| par[1] },
40
- req: req_parameters.map { |par| par[1] }
41
- }
47
+ def action_arguments
48
+ return @action_arguments if @action_arguments
49
+ ## Get all parameters (arguments) from method
50
+ ## Than collect and sort parameters into hash
51
+ @ctrl.instance_method(@action).parameters
52
+ .each_with_object(req: [], opt: []) do |param, hash|
53
+ ## Only required parameters must be in `:req`
54
+ hash[param[0]] << param[1]
55
+ end
42
56
  end
43
57
 
44
- def no_extra_path_arguments?
45
- ## Subtraction action args from path args
46
- extra_path_args = @path_args - @action_args[:all]
47
- return true if extra_path_args.empty?
48
- raise Errors::RouterError::ExtraPathArgumentsError.new(
49
- @ctrl, @action, @path, extra_path_args
50
- )
51
- end
52
-
53
- def no_extra_action_arguments?
54
- ## Subtraction path args from action required args
55
- extra_action_args = @action_args[:req] - @path_args
56
- return true if extra_action_args.empty?
57
- raise Errors::RouterError::ExtraActionArgumentsError.new(
58
- @ctrl, @action, @path, extra_action_args
59
- )
60
- end
61
- end
62
-
63
- ## Compare actions from routes and from controller
64
- class ActionsValidator
65
- def initialize(route_refine)
66
- @routes_actions = route_refine.routes.map(&:action)
67
- @ctrl = route_refine.ctrl
68
- end
69
-
70
- def valid?
71
- no_extra_routes_actions? && no_extra_controller_actions?
72
- end
73
-
74
- private
75
-
76
- def no_extra_routes_actions?
77
- extra_routes_actions = @routes_actions - @ctrl.actions
78
- return true if extra_routes_actions.empty?
79
- raise Errors::RouterError::ExtraRoutesActionsError.new(
80
- @ctrl, extra_routes_actions
81
- )
82
- end
83
-
84
- def no_extra_controller_actions?
85
- extra_ctrl_actions = @ctrl.actions - @routes_actions
86
- return true if extra_ctrl_actions.empty?
87
- raise Errors::RouterError::ExtraControllerActionsError.new(
88
- @ctrl, extra_ctrl_actions
89
- )
58
+ ## Calculate path and action extra arguments
59
+ def extra_arguments(type)
60
+ {
61
+ ctrl: action_arguments[type] - path_arguments[type],
62
+ path: path_arguments[type] - action_arguments[type]
63
+ }
90
64
  end
91
65
  end
92
66
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flame
4
- VERSION = '4.11.3.2'.freeze
4
+ VERSION = '4.12.2'
5
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  ## Framework
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  namespace :db do
2
4
  ## Require libs and config
3
5
  require 'sequel'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module <%= @module_name %>
2
4
  ## Class for application (mounting controllers)
3
5
  class Application
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## Require gems
2
4
  require 'bundler'
3
5
  Bundler.require
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
 
3
5
  ## Database initialize for Sequel
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module <%= @module_name %>
2
4
  ## Base controller for any others controllers
3
5
  class Controller < Flame::Controller
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  ## Functons
4
5
  def show_usage
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flame
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.11.3.2
4
+ version: 4.12.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Popov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-27 00:00:00.000000000 Z
11
+ date: 2017-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -80,6 +80,104 @@ dependencies:
80
80
  version: '0'
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: rubocop
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '0.48'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '0.48'
95
+ - !ruby/object:Gem::Dependency
96
+ name: rake
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '12'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '12'
109
+ - !ruby/object:Gem::Dependency
110
+ name: bacon
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '1'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '1'
123
+ - !ruby/object:Gem::Dependency
124
+ name: bacon-colored_output
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '1.1'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '1.1'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rack-test
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ - !ruby/object:Gem::Dependency
152
+ name: simplecov
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ - !ruby/object:Gem::Dependency
166
+ name: codecov
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - "~>"
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ type: :development
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ - !ruby/object:Gem::Dependency
180
+ name: pry
83
181
  requirement: !ruby/object:Gem::Requirement
84
182
  requirements:
85
183
  - - "~>"
@@ -92,6 +190,20 @@ dependencies:
92
190
  - - "~>"
93
191
  - !ruby/object:Gem::Version
94
192
  version: '0'
193
+ - !ruby/object:Gem::Dependency
194
+ name: pry-byebug
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - "~>"
198
+ - !ruby/object:Gem::Version
199
+ version: '3'
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - "~>"
205
+ - !ruby/object:Gem::Version
206
+ version: '3'
95
207
  description: Use controller's classes with instance methods as routing actions, mounting
96
208
  its in application class.
97
209
  email:
@@ -155,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
267
  version: '0'
156
268
  requirements: []
157
269
  rubyforge_project:
158
- rubygems_version: 2.6.10
270
+ rubygems_version: 2.6.11
159
271
  signing_key:
160
272
  specification_version: 4
161
273
  summary: Web-framework, based on MVC-pattern