flame 3.6.2 → 4.0.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
  SHA1:
3
- metadata.gz: d36bd7e8c5db7454423ff5a080c407aad30dd67e
4
- data.tar.gz: 604cd066e8145524a01d323f4c3e021445413722
3
+ metadata.gz: 3b164f4b1817723648efb5412dc308265aaa30af
4
+ data.tar.gz: dc130470827a1bb8f1c22689c605381aa97ee78d
5
5
  SHA512:
6
- metadata.gz: 4a6a22af1494cf9092ba01005e959579c93d900b6ce76d7bfb81dace1515649bf0f8b9d7bbd32b09f550120edbafeb789e71ec3a410b24aa7a9893d0692f5534
7
- data.tar.gz: 941cc3b8d7891810c44b7998592c7263ce4cf3325d654b9041e335474b2bf094446589d5abf104d304e2a3b5b758c4838b36c53822ff5ba2518f9cd211c64976
6
+ metadata.gz: 2a482215bfd58d3ca783ac1c904f171d5e09f5a2cd42245b6324bf433ffb8611827602e551099076939969fe07b23ae0defb1be6a1c68d18708a270b4b97e3f4
7
+ data.tar.gz: 5afe0a7dcd19b8ee8eb9d674211f456ea0232932fd40bc0e24f86837dce011d81216c9ecaba9ab84bd4f5cc263a1c813efd1be6a28ceba7febb60dda3ce3341e
@@ -13,6 +13,7 @@ module Flame
13
13
  self.class.config
14
14
  end
15
15
 
16
+ ## Generating application config when inherited
16
17
  def self.inherited(app)
17
18
  app.config = Config.new(
18
19
  app,
@@ -26,32 +27,38 @@ module Flame
26
27
 
27
28
  def initialize(app = nil)
28
29
  @app = app
29
- router.routes.map! do |route|
30
- route[:hooks] = router.find_hooks(route)
31
- route.freeze
32
- end
33
- router.freeze
34
30
  end
35
31
 
36
- ## Init function
32
+ ## Request recieving method
37
33
  def call(env)
38
34
  @app.call(env) if @app.respond_to? :call
39
35
  Flame::Dispatcher.new(self, env).run!
40
36
  end
41
37
 
38
+ ## Make available `run Application` without `.new` for `rackup`
42
39
  def self.call(env)
43
40
  @app ||= new
44
41
  @app.call env
45
42
  end
46
43
 
44
+ ## Mount controller in application class
45
+ ## @param ctrl [Flame::Controller] the mounted controller class
46
+ ## @param path [String, nil] root path for the mounted controller
47
+ ## @yield refine defaults pathes for a methods of the mounted controller
48
+ ## @example Mount controller with defaults
49
+ ## mount ArticlesController
50
+ ## @example Mount controller with specific path
51
+ ## mount HomeController, '/welcome'
52
+ ## @example Mount controller with specific path of methods
53
+ ## mount HomeController do
54
+ ## get '/bye', :goodbye
55
+ ## post '/greetings', :new
56
+ ## defaults
57
+ ## end
47
58
  def self.mount(ctrl, path = nil, &block)
48
59
  router.add_controller(ctrl, path, block)
49
60
  end
50
61
 
51
- def self.helpers(*modules)
52
- modules.empty? ? (@helpers ||= []) : helpers.concat(modules).uniq!
53
- end
54
-
55
62
  ## Router for routing
56
63
  def self.router
57
64
  @router ||= Flame::Router.new(self)
@@ -61,6 +68,7 @@ module Flame
61
68
  self.class.router
62
69
  end
63
70
 
71
+ ## Initialize default for config directories
64
72
  def self.default_config_dirs(root_dir:)
65
73
  {
66
74
  root_dir: File.realpath(root_dir),
@@ -5,6 +5,8 @@ module Flame
5
5
  ## Class initialize when Dispatcher found route with it
6
6
  ## For new request and response
7
7
  class Controller
8
+ ## Initialize the controller for request execution
9
+ ## @param dispatcher [Flame::Dispatcher] dispatcher object
8
10
  def initialize(dispatcher)
9
11
  @dispatcher = dispatcher
10
12
  end
@@ -15,12 +17,27 @@ module Flame
15
17
  @dispatcher.path_to(*args)
16
18
  end
17
19
 
20
+ ## Redirect for response
21
+ ## @overload redirect(path)
22
+ ## Redirect to the string path
23
+ ## @param path [String] path
24
+ ## @example Redirect to '/hello'
25
+ ## redirect '/hello'
26
+ ## @overload redirect(*args)
27
+ ## Redirect to the path of `path_to` method
28
+ ## @param args arguments for `path_to` method
29
+ ## @example Redirect to `show` method of `ArticlesController` with id = 2
30
+ ## redirect ArticlesController, :show, id: 2
18
31
  def redirect(*params)
19
32
  response.redirect(
20
33
  params[0].is_a?(String) ? params[0] : path_to(*params)
21
34
  )
22
35
  end
23
36
 
37
+ ## Render a template with `Flame::Render` (based on Tilt-engine)
38
+ ## @param path [Symbol, nil] path to the template file
39
+ ## @param options [Hash] options for the `Flame::Render` rendering
40
+ ## @return [String] rendered template
24
41
  def view(path = nil, options = {})
25
42
  template = Flame::Render.new(
26
43
  self,
@@ -31,7 +48,26 @@ module Flame
31
48
  end
32
49
  alias render view
33
50
 
34
- ## Helpers from Flame::Dispatcher
51
+ ## Execute the method of the controller with hooks (may be overloaded)
52
+ ## @param method [Symbol] name of the controller method
53
+ def execute(method)
54
+ # send method
55
+ body send(
56
+ method,
57
+ *params.values_at(
58
+ *self.class.instance_method(method).parameters.map { |par| par[1] }
59
+ )
60
+ )
61
+ rescue => exception
62
+ # p 'rescue from controller'
63
+ status 500
64
+ dump_error(exception)
65
+
66
+ ## Re-raise exception for inherited controllers or `Flame::Dispatcher`
67
+ raise exception
68
+ end
69
+
70
+ ## Call helpers methods from `Flame::Dispatcher`
35
71
  def method_missing(m, *args, &block)
36
72
  return super unless @dispatcher.respond_to?(m)
37
73
  @dispatcher.send(m, *args, &block)
@@ -40,6 +76,7 @@ module Flame
40
76
  class << self
41
77
  using GorillaPatch::StringExt
42
78
 
79
+ ## Default root path of the controller for requests
43
80
  def default_path(last = false)
44
81
  (name.split('::').last.underscore.split('_') - %w(index controller ctrl))
45
82
  .join('/').split('/')
data/lib/flame/cookies.rb CHANGED
@@ -6,10 +6,19 @@ module Flame
6
6
  @response = response
7
7
  end
8
8
 
9
+ ## Get request cookies
10
+ ## @param key [String, Symbol] name of cookie
9
11
  def [](key)
10
12
  @request_cookies[key.to_s]
11
13
  end
12
14
 
15
+ ## Set (or delete) cookies for response
16
+ ## @param key [String, Symbol] name of cookie
17
+ ## @param new_value [Object, nil] value of cookie
18
+ ## @example Set new value to `cat` cookie
19
+ ## cookies['cat'] = 'nice cat'
20
+ ## @example Delete `cat` cookie
21
+ ## cookies['cat'] = nil
13
22
  def []=(key, new_value)
14
23
  return @response.delete_cookie(key.to_s, path: '/') if new_value.nil?
15
24
  @response.set_cookie(key.to_s, value: new_value, path: '/')
@@ -14,6 +14,9 @@ module Flame
14
14
 
15
15
  include Flame::Dispatcher::Static
16
16
 
17
+ ## Initialize Dispatcher from Application#call
18
+ ## @param app [Flame::Application] application object
19
+ ## @param env Rack-environment object
17
20
  def initialize(app, env)
18
21
  @app = app
19
22
  @env = env
@@ -21,43 +24,66 @@ module Flame
21
24
  @response = Flame::Response.new
22
25
  end
23
26
 
27
+ ## Start of execution the request
24
28
  def run!
25
29
  catch :halt do
26
30
  try_route ||
27
31
  try_static ||
28
32
  try_static(File.join(__dir__, '..', '..', 'public')) ||
29
- try_error(404)
33
+ not_found
30
34
  end
31
35
  response.write body
32
36
  response.finish
33
37
  end
34
38
 
39
+ ## Acccess to the status of response
40
+ ## @param value [Ineger, nil] integer value for new status
41
+ ## @return [Integer] current status
42
+ ## @example Set status value
43
+ ## status 200
35
44
  def status(value = nil)
36
45
  response.status ||= 200
37
46
  response.headers['X-Cascade'] = 'pass' if value == 404
38
47
  value ? response.status = value : response.status
39
48
  end
40
49
 
50
+ ## Acccess to the body of response
51
+ ## @param value [String, nil] string value for new body
52
+ ## @return [String] current body
53
+ ## @example Set body value
54
+ ## body 'Hello World!'
41
55
  def body(value = nil)
42
56
  value ? @body = value : @body ||= ''
43
57
  end
44
58
 
59
+ ## Parameters of the request
45
60
  def params
46
61
  @params ||= request.params.merge(request.params.keys_to_sym)
47
62
  end
48
63
 
64
+ ## Session object as Hash
49
65
  def session
50
66
  request.session
51
67
  end
52
68
 
69
+ ## Cookies object as Hash
53
70
  def cookies
54
71
  @cookies ||= Cookies.new(request.cookies, response)
55
72
  end
56
73
 
74
+ ## Application-config object as Hash
57
75
  def config
58
76
  @app.config
59
77
  end
60
78
 
79
+ ## Get path for controller and action.
80
+ ##
81
+ ## @param ctrl [Flame::Controller] class of controller
82
+ ## @param action [Symbol] method of controller
83
+ ## @param args [Hash] parameters for method of controller
84
+ ## @return [String] path for requested method, controller and parameters
85
+ ## @example Path for `show(id)` method of `ArticlesController` with `id: 2`
86
+ ## path_to ArticlesController, :show, id: 2 # => "/articles/show/2"
61
87
  def path_to(ctrl, action = :index, args = {})
62
88
  route = @app.class.router.find_route(controller: ctrl, action: action)
63
89
  fail RouteNotFoundError.new(ctrl, action) unless route
@@ -65,10 +91,22 @@ module Flame
65
91
  path.empty? ? '/' : path
66
92
  end
67
93
 
68
- def halt(new_status = nil, new_body = nil, new_headers = {})
69
- case new_status
70
- when String then new_body = new_status
71
- when Integer then status new_status
94
+ ## Interrupt the execution of route, and set new optional data
95
+ ## (otherwise using existing)
96
+ ## @param new_status_or_body [Integer, String]
97
+ ## set new HTTP status code or new body
98
+ ## @param new_body [String] set new body
99
+ ## @param new_headers [String] merge new headers
100
+ ## @example Halt with 500, no change body
101
+ ## halt 500
102
+ ## @example Halt with 404, render template
103
+ ## halt 404, render('errors/404')
104
+ ## @example Halt with 200, set new headers
105
+ ## halt 200, 'Cats!', 'Content-Type' => 'animal/cat'
106
+ def halt(new_status_or_body = nil, new_body = nil, new_headers = {})
107
+ case new_status_or_body
108
+ when String then new_body = new_status_or_body
109
+ when Integer then status new_status_or_body
72
110
  end
73
111
  # new_status.is_a?(String) ? () : (status new_status)
74
112
  new_body = default_body if new_body.nil? && body.empty?
@@ -77,20 +115,27 @@ module Flame
77
115
  throw :halt
78
116
  end
79
117
 
118
+ ## Add error's backtrace to @env['rack.errors'] (terminal or file)
119
+ ## @param error [Exception] exception for class, message and backtrace
120
+ def dump_error(error)
121
+ msg = [
122
+ "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - " \
123
+ "#{error.class} - #{error.message}:",
124
+ *error.backtrace
125
+ ].join("\n\t")
126
+ @env['rack.errors'].puts(msg)
127
+ end
128
+
80
129
  private
81
130
 
82
131
  ## Generate default body of error page
83
132
  def default_body
133
+ ## Return nil if must be no body for current HTTP status
84
134
  return if Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status)
85
135
  response.headers[Rack::CONTENT_TYPE] = 'text/html'
86
136
  "<h1>#{Rack::Utils::HTTP_STATUS_CODES[status]}</h1>"
87
137
  end
88
138
 
89
- ## Find nearest route
90
- def nearest_route_for_request
91
- @app.router.find_nearest_route(request.path_parts)
92
- end
93
-
94
139
  ## Find route and try execute it
95
140
  def try_route
96
141
  route = @app.class.router.find_route(
@@ -98,39 +143,36 @@ module Flame
98
143
  path_parts: request.path_parts
99
144
  )
100
145
  return nil unless route
101
- status 200
102
- params.merge!(route.arguments(request.path_parts))
103
- # route.execute(self)
104
146
  execute_route(route)
105
147
  end
106
148
 
149
+ ## Execute route
150
+ ## @param route [Flame::Route] route that must be executed
107
151
  def execute_route(route)
108
- exec_route = route.executable(self)
109
- exec_route.run!
110
- rescue => exception
111
- dump_error(exception)
112
- # status 500
113
- # exec_route.execute_errors(status)
114
- try_error(500, exec_route)
115
- end
116
-
117
- def try_error(error_status = nil, exec_route = nil)
118
- status error_status if error_status
119
- unless exec_route
120
- route = nearest_route_for_request unless exec_route
121
- exec_route = route.executable(self) if route
122
- end
123
- exec_route.execute_errors(status) if exec_route
124
- halt
125
- end
126
-
127
- def dump_error(error)
128
- msg = [
129
- "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - " \
130
- "#{error.class} - #{error.message}:",
131
- *error.backtrace
132
- ].join("\n\t")
133
- @env['rack.errors'].puts(msg)
152
+ status 200
153
+ params.merge!(route.arguments(request.path_parts))
154
+ # route.execute(self)
155
+ route[:controller].new(self).execute(route[:action])
156
+ rescue => _exception
157
+ # p 'rescue from dispatcher'
158
+ halt 500
159
+
160
+ # p 're raise exception from dispatcher'
161
+ # raise exception
162
+ end
163
+
164
+ ## Generate a response if the route is not found
165
+ def not_found
166
+ # p 'not found from dispatcher'
167
+ ## Change the status of response to 404
168
+ status 404
169
+ ## Find the nearest route by the parts of requested path
170
+ route = @app.router.find_nearest_route(request.path_parts)
171
+ ## Halt with default body if the route not found
172
+ ## or it's `not_found` method not defined
173
+ return halt unless route && route[:controller].method_defined?(:not_found)
174
+ ## Execute `not_found` method for the founded route
175
+ route[:controller].new(self).execute(:not_found)
134
176
  end
135
177
  end
136
178
  end
data/lib/flame/render.rb CHANGED
@@ -20,6 +20,8 @@ module Flame
20
20
  @layout = nil if File.basename(@filename)[0] == '_'
21
21
  end
22
22
 
23
+ ## Render template
24
+ ## @param cache [Boolean] cache compiles or not
23
25
  def render(cache: true)
24
26
  ## Compile Tilt to instance hash
25
27
  tilt = cache ? self.class.tilts[@filename] ||= compile : compile
@@ -39,19 +41,16 @@ module Flame
39
41
 
40
42
  using GorillaPatch::StringExt
41
43
 
44
+ ## Compile file with Tilt engine
45
+ ## @param filename [String] filename
42
46
  def compile(filename = @filename)
43
47
  Tilt.new(filename)
44
48
  end
45
49
 
46
- ## TODO: Add `views_dir` for Application and Controller
47
- ## TODO: Add `layout` method for Controller
50
+ ## @todo Add `views_dir` for Application and Controller
51
+ ## @todo Add `layout` method for Controller
48
52
  def find_file(path)
49
53
  ## Get full filename
50
- # p Dir[File.join(
51
- # @ctrl.config[:views_dir],
52
- # "{#{controller_dirs.join(',')},}",
53
- # "#{path}.*"
54
- # )].uniq
55
54
  Dir[File.join(
56
55
  @ctrl.config[:views_dir],
57
56
  "{#{controller_dirs.join(',')},}",
@@ -61,18 +60,21 @@ module Flame
61
60
  end
62
61
  end
63
62
 
63
+ ## Find possible directories for the controller
64
64
  def controller_dirs
65
- ## Build controller_dirs
66
- controller_dir = (
67
- @ctrl.class.name.underscore.split('_') - %w(controller ctrl)
68
- ).join('_')
69
- controller_dir_parts = controller_dir.split('/')
65
+ controller_dir_parts = @ctrl.class.name.underscore.split('/').map do |part|
66
+ (part.split('_') - %w(controller controllers ctrl)).join('_')
67
+ end
68
+ controller_dir = controller_dir_parts.join('/')
70
69
  [controller_dir,
71
70
  controller_dir_parts[1..-1].join('/'),
72
71
  controller_dir_parts[1..-2].join('/'),
73
72
  controller_dir_parts.last]
74
73
  end
75
74
 
75
+ ## Render the layout with template
76
+ ## @param result [String] result of template rendering
77
+ ## @param cache [Boolean] cache compiles or not
76
78
  def layout_render(result, cache: true)
77
79
  layout_file = find_file(@layout)
78
80
  ## Compile layout to hash
data/lib/flame/request.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  module Flame
2
2
  ## Class for requests
3
3
  class Request < Rack::Request
4
+ ## Split path of the request to parts (Array of String)
4
5
  def path_parts
5
6
  @path_parts ||= path_info.to_s.split('/').reject(&:empty?)
6
7
  end
7
8
 
9
+ ## Override HTTP-method of the request if the param '_method' found
8
10
  def http_method
9
11
  params['_method'] || request_method
10
12
  end
data/lib/flame/route.rb CHANGED
@@ -5,24 +5,26 @@ module Flame
5
5
 
6
6
  def initialize(attrs = {})
7
7
  @attributes = attrs.merge(
8
- path_parts: attrs[:path].to_s.split('/').reject(&:empty?)
8
+ ## Split path to parts (Array of String)
9
+ path_parts: attrs[:path].to_s.split('/').reject(&:empty?).freeze
9
10
  )
10
11
  end
11
12
 
13
+ ## Get the attribute of route
14
+ ## @param key [Symbol] name of attribute
12
15
  def [](key)
13
16
  @attributes[key]
14
17
  end
15
18
 
19
+ ## Set the attribute of route
20
+ ## @param key [Symbol] name of attribute
21
+ ## @param value [Object] value of attribute
16
22
  def []=(key, value)
17
23
  @attributes[key] = value
18
24
  end
19
25
 
20
- ## Create Executable object (route)
21
- def executable(dispatcher)
22
- Executable.new(self, dispatcher)
23
- end
24
-
25
26
  ## Compare attributes for `Router.find_route`
27
+ ## @param attrs [Hash] Hash of attributes for comparing
26
28
  def compare_attributes(attrs)
27
29
  attrs.each do |name, value|
28
30
  next true if compare_attribute(name, value)
@@ -31,6 +33,7 @@ module Flame
31
33
  end
32
34
 
33
35
  ## Assign arguments to path for `Controller.path_to`
36
+ ## @param args [Hash] arguments for assigning
34
37
  def assign_arguments(args = {})
35
38
  self[:path_parts]
36
39
  .map { |path_part| assign_argument(path_part, args) }
@@ -38,6 +41,7 @@ module Flame
38
41
  end
39
42
 
40
43
  ## Extract arguments from request_parts for `execute`
44
+ ## @param request_parts [Array] parts of the request (Array of String)
41
45
  def arguments(request_parts)
42
46
  self[:path_parts].each_with_index.with_object({}) do |(path_part, i), args|
43
47
  request_part = request_parts[i]
@@ -93,59 +97,5 @@ module Flame
93
97
  ## All is ok
94
98
  param
95
99
  end
96
-
97
- ## Class for Route execution
98
- class Executable
99
- ## Create executable route with dispatcher
100
- def initialize(route, dispatcher)
101
- @route = route
102
- @ctrl = @route[:controller].new(dispatcher)
103
- end
104
-
105
- ## Execute route
106
- def run!
107
- execute_hooks(:before)
108
- @ctrl.body @ctrl.send(@route[:action], *arranged_params)
109
- execute_hooks(:after)
110
- end
111
-
112
- def execute_errors(status = 500)
113
- execute_hooks(:error, status)
114
- end
115
-
116
- private
117
-
118
- ## Arguments in order as parameters of method of controller
119
- def arranged_params
120
- # action_parameters.each_with_object([]) do |par, arr|
121
- # arr << @ctrl.params[par[1]] if par[0] == :req || @ctrl.params[par[1]]
122
- # end
123
- @ctrl.params.values_at(*action_parameters.map { |par| par[1] })
124
- end
125
-
126
- ## Method parameters of route controller#action
127
- def action_parameters
128
- @route[:controller].instance_method(@route[:action]).parameters
129
- end
130
-
131
- ## Execute before, after or error hook of Symbol, String or Proc
132
- def execute_hook(hook)
133
- case hook
134
- when Symbol, String
135
- @ctrl.send(hook.to_sym)
136
- when Proc
137
- @ctrl.instance_exec(&hook)
138
- else
139
- fail UnexpectedTypeOfHookError.new(hook, @route)
140
- end
141
- end
142
-
143
- ## Execute before, after or error hooks
144
- def execute_hooks(*keys)
145
- hooks = @route[:hooks].dig(*keys)
146
- # p hooks
147
- hooks.each { |hook| execute_hook(hook) } if hooks
148
- end
149
- end
150
100
  end
151
101
  end
data/lib/flame/router.rb CHANGED
@@ -4,30 +4,36 @@ require_relative 'validators'
4
4
  module Flame
5
5
  ## Router class for routing
6
6
  class Router
7
- attr_reader :app, :routes, :hooks
7
+ attr_reader :app, :routes
8
8
 
9
9
  def initialize(app)
10
10
  @app = app
11
11
  @routes = []
12
- @hooks = {}
13
12
  end
14
13
 
14
+ ## Add the controller with it's methods to routes
15
+ ## @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
15
18
  def add_controller(ctrl, path, block = nil)
16
- ## TODO: Add Regexp paths
19
+ ## @todo Add Regexp paths
17
20
 
18
21
  ## Add routes from controller to glob array
19
- ctrl.include(*@app.helpers)
20
22
  route_refine = RouteRefine.new(self, ctrl, path, block)
21
23
  concat_routes(route_refine) if ActionsValidator.new(route_refine).valid?
22
24
  end
23
25
 
24
26
  ## Find route by any attributes
27
+ ## @param attrs [Hash] attributes for comparing
28
+ ## @return [Flame::Route, nil] return the found route, otherwise `nil`
25
29
  def find_route(attrs)
26
30
  route = routes.find { |r| r.compare_attributes(attrs) }
27
31
  route.dup if route
28
32
  end
29
33
 
30
34
  ## Find the nearest route by path parts
35
+ ## @param path_parts [Array] parts of path for route finding
36
+ ## @return [Flame::Route, nil] return the found nearest route, otherwise `nil`
31
37
  def find_nearest_route(path_parts)
32
38
  while path_parts.size >= 0
33
39
  route = find_route(path_parts: path_parts)
@@ -37,38 +43,24 @@ module Flame
37
43
  route
38
44
  end
39
45
 
40
- ## Find hooks by Route
41
- def find_hooks(route)
42
- result = {}
43
- hooks[route[:controller]].each do |type, hash|
44
- if type == :error
45
- result[type] = hash
46
- else
47
- result[type] = (hash[route[:action]] || []) | (hash[:*] || [])
48
- end
49
- end
50
- # p result
51
- result
52
- end
53
-
54
46
  private
55
47
 
48
+ ## Add `RouteRefine` routes to the routes of `Flame::Router`
49
+ ## @param route_refine [Flame::Router::RouteRefine] `RouteRefine` with routes
56
50
  def concat_routes(route_refine)
57
51
  routes.concat(route_refine.routes)
58
- hooks[route_refine.ctrl] = route_refine.hooks
59
52
  end
60
53
 
61
- ## Helper module for routing refine
54
+ ## Helper class for controller routing refine
62
55
  class RouteRefine
63
56
  attr_accessor :rest_routes
64
- attr_reader :ctrl, :routes, :hooks
65
-
66
- HOOK_TYPES = [:before, :after, :error].freeze
57
+ attr_reader :ctrl, :routes
67
58
 
68
59
  def self.http_methods
69
60
  [:GET, :POST, :PUT, :DELETE]
70
61
  end
71
62
 
63
+ ## Defaults REST routes (methods, pathes, controllers actions)
72
64
  def rest_routes
73
65
  @rest_routes ||= [
74
66
  { method: :GET, path: '/', action: :index },
@@ -84,11 +76,22 @@ module Flame
84
76
  @ctrl = ctrl
85
77
  @path = path || @ctrl.default_path
86
78
  @routes = []
87
- @hooks = HOOK_TYPES.each_with_object({}) { |type, hash| hash[type] = {} }
88
79
  execute(&block)
89
80
  end
90
81
 
91
82
  http_methods.each do |request_method|
83
+ ## Define refine methods for all HTTP methods
84
+ ## @overload post(path, action)
85
+ ## Execute action on requested path and HTTP method
86
+ ## @param path [String] path of method for the request
87
+ ## @param action [Symbol] name of method for the request
88
+ ## @example Set path to '/bye' and method to :POST for action `goodbye`
89
+ ## post '/bye', :goodbye
90
+ ## @overload post(action)
91
+ ## Execute action on requested HTTP method
92
+ ## @param action [Symbol] name of method for the request
93
+ ## @example Set method to :POST for action `goodbye`
94
+ ## post :goodbye
92
95
  define_method(request_method.downcase) do |path, action = nil|
93
96
  if action.nil?
94
97
  action = path.to_sym
@@ -99,14 +102,8 @@ module Flame
99
102
  end
100
103
  end
101
104
 
102
- HOOK_TYPES.each do |type|
103
- default_actions = (type == :error ? 500 : :*)
104
- define_method(type) do |actions = default_actions, action = nil, &block|
105
- actions = [actions] unless actions.is_a?(Array)
106
- actions.each { |a| (@hooks[type][a] ||= []).push(action || block) }
107
- end
108
- end
109
-
105
+ ## Assign remaining methods of the controller
106
+ ## to defaults pathes and HTTP methods
110
107
  def defaults
111
108
  rest
112
109
  @ctrl.public_instance_methods(false).each do |action|
@@ -115,6 +112,7 @@ module Flame
115
112
  end
116
113
  end
117
114
 
115
+ ## Assign methods of the controller to REST architecture
118
116
  def rest
119
117
  rest_routes.each do |rest_route|
120
118
  action = rest_route[:action]
@@ -125,6 +123,10 @@ module Flame
125
123
  end
126
124
  end
127
125
 
126
+ ## Mount controller inside other (parent) controller
127
+ ## @param ctrl [Flame::Controller] class of mounting controller
128
+ ## @param path [String, nil] root path for mounting controller
129
+ ## @yield Block of code for routes refine
128
130
  def mount(ctrl, path = nil, &block)
129
131
  path = path_merge(
130
132
  @path,
@@ -135,15 +137,18 @@ module Flame
135
137
 
136
138
  private
137
139
 
140
+ ## Execute block of refinings end sorting routes
138
141
  def execute(&block)
139
142
  block.nil? ? defaults : instance_exec(&block)
140
- @router.app.helpers.each do |helper|
141
- instance_exec(&helper.mount) if helper.respond_to?(:mount)
142
- end
143
+ # instance_exec(&@ctrl.mounted) if @ctrl.respond_to? :mounted
144
+ # @router.app.helpers.each do |helper|
145
+ # instance_exec(&helper.mount) if helper.respond_to?(:mount)
146
+ # end
143
147
  # p @routes
144
148
  @routes.sort! { |a, b| b[:path] <=> a[:path] }
145
149
  end
146
150
 
151
+ ## Build path for the action of controller
147
152
  def make_path(path, action = nil, force_params = false)
148
153
  ## TODO: Add :arg:type support (:id:num, :name:str, etc.)
149
154
  unshifted = force_params ? path : action_path(action)
@@ -59,8 +59,6 @@ module Flame
59
59
  class ActionsValidator
60
60
  def initialize(route_refine)
61
61
  @routes_actions = route_refine.routes.map { |route| route[:action] }
62
- @hooks_actions = route_refine.hooks.values.map(&:values).flatten
63
- @hooks_actions.select! { |action| action.is_a? Symbol }
64
62
  @ctrl = route_refine.ctrl
65
63
  @ctrl_actions = {
66
64
  public: @ctrl.public_instance_methods(false),
@@ -69,9 +67,7 @@ module Flame
69
67
  end
70
68
 
71
69
  def valid?
72
- no_extra_routes_actions? &&
73
- no_extra_hooks_actions? &&
74
- no_extra_controller_actions?
70
+ no_extra_routes_actions? && no_extra_controller_actions?
75
71
  end
76
72
 
77
73
  private
@@ -84,14 +80,6 @@ module Flame
84
80
  )
85
81
  end
86
82
 
87
- def no_extra_hooks_actions?
88
- extra_hooks_actions = @hooks_actions - @ctrl_actions[:all]
89
- return true if extra_hooks_actions.empty?
90
- fail RouterError::ExtraRoutesActionsError.new(
91
- @ctrl, extra_hooks_actions
92
- )
93
- end
94
-
95
83
  def no_extra_controller_actions?
96
84
  extra_ctrl_actions = @ctrl_actions[:public] - @routes_actions
97
85
  return true if extra_ctrl_actions.empty?
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: 3.6.2
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Popov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-26 00:00:00.000000000 Z
11
+ date: 2016-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack