flame 4.18.1 → 5.0.0.rc1
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 +4 -4
- data/bin/flame +7 -62
- data/lib/flame.rb +1 -0
- data/lib/flame/application.rb +75 -17
- data/lib/flame/application/config.rb +6 -0
- data/lib/flame/controller.rb +36 -76
- data/lib/flame/controller/path_to.rb +39 -0
- data/lib/flame/dispatcher.rb +25 -66
- data/lib/flame/dispatcher/cookies.rb +10 -2
- data/lib/flame/dispatcher/routes.rb +53 -0
- data/lib/flame/dispatcher/static.rb +15 -8
- data/lib/flame/errors/argument_not_assigned_error.rb +6 -0
- data/lib/flame/errors/route_arguments_order_error.rb +6 -0
- data/lib/flame/errors/route_extra_arguments_error.rb +10 -0
- data/lib/flame/errors/route_not_found_error.rb +10 -4
- data/lib/flame/errors/template_not_found_error.rb +6 -0
- data/lib/flame/path.rb +63 -33
- data/lib/flame/render.rb +21 -8
- data/lib/flame/router.rb +112 -66
- data/lib/flame/router/route.rb +9 -56
- data/lib/flame/router/routes.rb +86 -0
- data/lib/flame/validators.rb +7 -1
- data/lib/flame/version.rb +1 -1
- data/template/.editorconfig +15 -0
- data/template/.gitignore +19 -2
- data/template/.rubocop.yml +14 -0
- data/template/Gemfile +48 -8
- data/template/Rakefile +824 -0
- data/template/{app.rb.erb → application.rb.erb} +4 -1
- data/template/config.ru.erb +62 -10
- data/template/config/config.rb.erb +44 -2
- data/template/config/database.example.yml +1 -1
- data/template/config/deploy.example.yml +2 -0
- data/template/config/puma.rb +56 -0
- data/template/config/sequel.rb.erb +13 -6
- data/template/config/server.example.yml +32 -0
- data/template/config/session.example.yml +7 -0
- data/template/controllers/{_base_controller.rb.erb → _controller.rb.erb} +5 -4
- data/template/controllers/site/_controller.rb.erb +18 -0
- data/template/controllers/site/index_controller.rb.erb +12 -0
- data/template/filewatchers.yml +12 -0
- data/template/server +172 -21
- data/template/services/.keep +0 -0
- data/template/views/site/index.html.erb.erb +1 -0
- data/template/views/site/layout.html.erb.erb +10 -0
- metadata +112 -54
- data/template/Rakefile.erb +0 -64
- data/template/config/thin.example.yml +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e3d7d2c5f0cd76e641b7b5cc3999eeff5bf5c11
|
4
|
+
data.tar.gz: aa3c3efc4fba9d10060a554592be063f3384a7d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aeb8af2e6436404b2478a31ae95598f04a0677d13c3ea27b5ec0eb6bef859d3378cfecbbb8a19a1e79e2d37062b3bc58a05c0189bba75be09d93d40d21bb3940
|
7
|
+
data.tar.gz: ab7eb4d61a48c01cbf122d2a180ac8fdb8945c28d4a1024970c0ff68edd68fcdd92f5aec08bb5612143225dcda135578b798f3465c8f70f74270dad437603ceb
|
data/bin/flame
CHANGED
@@ -2,70 +2,15 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'thor'
|
5
|
-
require 'fileutils'
|
6
|
-
require 'gorilla-patch/inflections'
|
7
|
-
require 'erb'
|
8
5
|
|
9
|
-
|
10
|
-
class FlameCLI < Thor
|
11
|
-
desc 'new APP', 'Generate new application directory with sub-directories'
|
12
|
-
def new(app_name)
|
13
|
-
FlameApp.new app_name
|
14
|
-
end
|
15
|
-
|
16
|
-
## Class for Flame Application
|
17
|
-
class FlameApp
|
18
|
-
def initialize(app_name)
|
19
|
-
@app_name = app_name
|
20
|
-
New.build @app_name
|
21
|
-
puts 'Done!'
|
22
|
-
puts "\nMoving to '#{@app_name}' directory by:\n\ncd #{@app_name}\n\n"
|
23
|
-
end
|
24
|
-
|
25
|
-
## Module for new application
|
26
|
-
module New
|
27
|
-
module_function
|
28
|
-
|
29
|
-
using GorillaPatch::Inflections
|
30
|
-
|
31
|
-
def build(app_name)
|
32
|
-
@app_name = app_name
|
33
|
-
@module_name = @app_name.camelize
|
34
|
-
make_dir do
|
35
|
-
copy_template
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def make_dir(&block)
|
40
|
-
puts "Creating '#{@app_name}' directory..."
|
41
|
-
FileUtils.mkdir @app_name
|
42
|
-
FileUtils.cd @app_name, &block
|
43
|
-
end
|
44
|
-
|
45
|
-
def copy_template
|
46
|
-
puts 'Copy template directories and files...'
|
47
|
-
FileUtils.cp_r File.join(__dir__, '..', 'template', '.'), '.'
|
48
|
-
clean_dirs
|
49
|
-
render_templates
|
50
|
-
end
|
51
|
-
|
52
|
-
def clean_dirs
|
53
|
-
puts 'Clean directories...'
|
54
|
-
FileUtils.rm Dir[File.join('**', '*', '.keep')]
|
55
|
-
end
|
6
|
+
require_relative 'new'
|
56
7
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
content = ERB.new(File.read(file)).result(binding)
|
63
|
-
File.write(File.join(File.dirname(file), basename), content)
|
64
|
-
FileUtils.rm file
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
8
|
+
module FlameCLI
|
9
|
+
## CLI Application
|
10
|
+
class Flame < Thor
|
11
|
+
desc 'new ENTITY ...ARGS', 'create new entity'
|
12
|
+
subcommand 'new', New
|
68
13
|
end
|
69
14
|
end
|
70
15
|
|
71
|
-
FlameCLI.start(ARGV)
|
16
|
+
FlameCLI::Flame.start(ARGV)
|
data/lib/flame.rb
CHANGED
data/lib/flame/application.rb
CHANGED
@@ -19,12 +19,28 @@ module Flame
|
|
19
19
|
@cached_tilts ||= {}
|
20
20
|
end
|
21
21
|
|
22
|
+
## Require project directories, exclude executable files
|
23
|
+
## @param dirs [Array<String>] Array of directories names
|
24
|
+
## @example Regular require of project
|
25
|
+
## Flame::Application.require_dirs(
|
26
|
+
## %w[config lib models helpers mailers services controllers]
|
27
|
+
## )
|
28
|
+
def require_dirs(dirs)
|
29
|
+
caller_dir = File.dirname caller_file
|
30
|
+
dirs.each do |dir|
|
31
|
+
Dir[File.join(caller_dir, dir, '**', '*.rb')]
|
32
|
+
.reject { |file| File.executable?(file) }
|
33
|
+
.sort_by { |s| [File.basename(s)[0], s] }
|
34
|
+
.each { |file| require File.expand_path(file) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
22
38
|
## Generating application config when inherited
|
23
39
|
def inherited(app)
|
24
40
|
app.config = Config.new(
|
25
41
|
app,
|
26
42
|
default_config_dirs(
|
27
|
-
root_dir: File.dirname(
|
43
|
+
root_dir: File.dirname(caller_file)
|
28
44
|
).merge(
|
29
45
|
environment: ENV['RACK_ENV'] || 'development'
|
30
46
|
)
|
@@ -37,24 +53,75 @@ module Flame
|
|
37
53
|
@app.call env
|
38
54
|
end
|
39
55
|
|
56
|
+
## Build a path to the given controller and action
|
57
|
+
##
|
58
|
+
## @param ctrl [Flame::Controller] class of controller
|
59
|
+
## @param action [Symbol] method of controller
|
60
|
+
## @param args [Hash] parameters for method of controller
|
61
|
+
## @return [String] path for requested method, controller and parameters
|
62
|
+
## @example Path for `show(id)` method of `ArticlesController`
|
63
|
+
## path_to ArticlesController, :show, id: 2 # => "/articles/show/2"
|
64
|
+
## @example Path for `new` method of `ArticlesController` with params
|
65
|
+
## path_to ArticlesController, :new, params: { author_id: 1 }
|
66
|
+
## # => "/articles/new?author_id=1"
|
67
|
+
def path_to(ctrl, action = :index, args = {})
|
68
|
+
path = router.path_of(ctrl, action)
|
69
|
+
raise Errors::RouteNotFoundError.new(ctrl, action) unless path
|
70
|
+
query = Rack::Utils.build_nested_query args.delete(:params)
|
71
|
+
query = nil if query&.empty?
|
72
|
+
path = path.assign_arguments(args)
|
73
|
+
path = '/' if path.empty?
|
74
|
+
Addressable::URI.new(path: path, query: query).to_s
|
75
|
+
end
|
76
|
+
|
40
77
|
private
|
41
78
|
|
79
|
+
## Get filename from caller of method
|
80
|
+
## @return [String] filename of caller
|
81
|
+
def caller_file
|
82
|
+
caller(2..2).first.split(':')[0]
|
83
|
+
end
|
84
|
+
|
85
|
+
using GorillaPatch::DeepMerge
|
86
|
+
|
42
87
|
## Mount controller in application class
|
43
|
-
## @param
|
88
|
+
## @param controller [Symbol] the snake-cased name of mounted controller
|
89
|
+
## (without `Controller` or `::IndexController` for namespaces)
|
44
90
|
## @param path [String, nil] root path for the mounted controller
|
45
91
|
## @yield refine defaults pathes for a methods of the mounted controller
|
46
92
|
## @example Mount controller with defaults
|
47
|
-
## mount ArticlesController
|
93
|
+
## mount :articles # ArticlesController
|
48
94
|
## @example Mount controller with specific path
|
49
|
-
## mount
|
95
|
+
## mount :home, '/welcome' # HomeController
|
50
96
|
## @example Mount controller with specific path of methods
|
51
|
-
## mount
|
97
|
+
## mount :home do # HomeController
|
52
98
|
## get '/bye', :goodbye
|
53
99
|
## post '/greetings', :new
|
54
100
|
## defaults
|
55
101
|
## end
|
56
|
-
|
57
|
-
|
102
|
+
## @example Mount controller with nested controllers
|
103
|
+
## mount :cabinet do # Cabinet::IndexController
|
104
|
+
## mount :articles # Cabinet::ArticlesController
|
105
|
+
## end
|
106
|
+
def mount(controller_name, path = nil, &block)
|
107
|
+
## Add routes from controller to glob array
|
108
|
+
|
109
|
+
routes_refine = Router::RoutesRefine.new(
|
110
|
+
router, namespace, controller_name, path, &block
|
111
|
+
)
|
112
|
+
|
113
|
+
router.routes.deep_merge! routes_refine.routes
|
114
|
+
router.reverse_routes.merge! routes_refine.reverse_routes
|
115
|
+
end
|
116
|
+
|
117
|
+
using GorillaPatch::Namespace
|
118
|
+
|
119
|
+
def namespace
|
120
|
+
namespace = self
|
121
|
+
while namespace.name.nil? && namespace.superclass != Flame::Application
|
122
|
+
namespace = superclass
|
123
|
+
end
|
124
|
+
namespace.deconstantize
|
58
125
|
end
|
59
126
|
|
60
127
|
## Initialize default for config directories
|
@@ -67,15 +134,6 @@ module Flame
|
|
67
134
|
end
|
68
135
|
end
|
69
136
|
|
70
|
-
## Framework configuration
|
71
|
-
def config
|
72
|
-
self.class.config
|
73
|
-
end
|
74
|
-
|
75
|
-
def router
|
76
|
-
self.class.router
|
77
|
-
end
|
78
|
-
|
79
137
|
def initialize(app = nil)
|
80
138
|
@app = app
|
81
139
|
end
|
@@ -83,7 +141,7 @@ module Flame
|
|
83
141
|
## Request recieving method
|
84
142
|
def call(env)
|
85
143
|
@app.call(env) if @app.respond_to? :call
|
86
|
-
Flame::Dispatcher.new(self, env).run!
|
144
|
+
Flame::Dispatcher.new(self.class, env).run!
|
87
145
|
end
|
88
146
|
end
|
89
147
|
end
|
@@ -4,11 +4,17 @@ module Flame
|
|
4
4
|
class Application
|
5
5
|
## Class for Flame::Application.config
|
6
6
|
class Config < Hash
|
7
|
+
## Create an instance of application config
|
8
|
+
## @param app [Flame::Application] application
|
9
|
+
## @param hash [Hash] config content
|
7
10
|
def initialize(app, hash = {})
|
8
11
|
@app = app
|
9
12
|
replace(hash)
|
10
13
|
end
|
11
14
|
|
15
|
+
## Get config value by key
|
16
|
+
## @param key [Symbol] config key
|
17
|
+
## @return [Object] config value
|
12
18
|
def [](key)
|
13
19
|
result = super(key)
|
14
20
|
if result.class <= Proc && result.parameters.empty?
|
data/lib/flame/controller.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'forwardable'
|
4
|
+
require 'gorilla-patch/namespace'
|
5
|
+
|
6
|
+
require_relative 'controller/path_to'
|
4
7
|
require_relative 'render'
|
5
8
|
|
6
9
|
module Flame
|
@@ -9,13 +12,34 @@ module Flame
|
|
9
12
|
class Controller
|
10
13
|
extend Forwardable
|
11
14
|
|
12
|
-
FORBIDDEN_ACTIONS = [].freeze
|
13
|
-
|
14
15
|
## Shortcut for not-inherited public methods: actions
|
16
|
+
## @return [Array<Symbol>] array of actions (public instance methods)
|
15
17
|
def self.actions
|
16
18
|
public_instance_methods(false)
|
17
19
|
end
|
18
20
|
|
21
|
+
## Re-define public instance methods (actions) from parent
|
22
|
+
## @param actions [Array<Symbol>] Actions for inheritance
|
23
|
+
## @param exclude [Array<Symbol>] Actions for excluding from inheritance
|
24
|
+
## @example Inherit all parent actions
|
25
|
+
## class MyController < BaseController
|
26
|
+
## inherit_actions
|
27
|
+
## end
|
28
|
+
## @example Inherit certain parent actions
|
29
|
+
## class MyController < BaseController
|
30
|
+
## inherit_actions :index, :show
|
31
|
+
## end
|
32
|
+
## @example Inherit all parent actions exclude certain
|
33
|
+
## class MyController < BaseController
|
34
|
+
## inherit_actions exclude: %i[edit update]
|
35
|
+
## end
|
36
|
+
def self.inherit_actions(actions = superclass.actions, exclude: [])
|
37
|
+
(actions - exclude).each do |public_method|
|
38
|
+
um = superclass.public_instance_method(public_method)
|
39
|
+
define_method public_method, um
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
19
43
|
def_delegators(
|
20
44
|
:@dispatcher,
|
21
45
|
:config, :request, :params, :halt, :session, :response, :status, :body,
|
@@ -23,29 +47,12 @@ module Flame
|
|
23
47
|
)
|
24
48
|
|
25
49
|
## Initialize the controller for request execution
|
26
|
-
## @param dispatcher [Flame::Dispatcher] dispatcher
|
50
|
+
## @param dispatcher [Flame::Dispatcher] host dispatcher
|
27
51
|
def initialize(dispatcher)
|
28
52
|
@dispatcher = dispatcher
|
29
53
|
end
|
30
54
|
|
31
|
-
|
32
|
-
def path_to(*args)
|
33
|
-
add_controller_class(args)
|
34
|
-
@dispatcher.path_to(*args)
|
35
|
-
end
|
36
|
-
|
37
|
-
## Build a URI to the given controller and action, or path
|
38
|
-
def url_to(*args, **options)
|
39
|
-
first_arg = args.first
|
40
|
-
path =
|
41
|
-
if first_arg.is_a?(String) || first_arg.is_a?(Flame::Path)
|
42
|
-
static_file = find_static(first_arg)
|
43
|
-
static_file.path(with_version: options[:version])
|
44
|
-
else
|
45
|
-
path_to(*args, **options)
|
46
|
-
end
|
47
|
-
"#{request.scheme}://#{request.host_with_port}#{path}"
|
48
|
-
end
|
55
|
+
include Flame::Controller::PathTo
|
49
56
|
|
50
57
|
## Redirect for response
|
51
58
|
## @overload redirect(path, status)
|
@@ -107,7 +114,7 @@ module Flame
|
|
107
114
|
## @param path [Symbol, nil] path to the template file
|
108
115
|
## @param options [Hash] options for the `Flame::Render` rendering
|
109
116
|
## @return [String] rendered template
|
110
|
-
def view(path = nil, options = {})
|
117
|
+
def view(path = nil, options = {}, &block)
|
111
118
|
cache = options.delete(:cache)
|
112
119
|
cache = config[:environment] == 'production' if cache.nil?
|
113
120
|
template = Flame::Render.new(
|
@@ -115,7 +122,7 @@ module Flame
|
|
115
122
|
(path || caller_locations(1, 1)[0].label.to_sym),
|
116
123
|
options
|
117
124
|
)
|
118
|
-
template.render(cache: cache)
|
125
|
+
template.render(cache: cache, &block)
|
119
126
|
end
|
120
127
|
alias render view
|
121
128
|
|
@@ -128,6 +135,8 @@ module Flame
|
|
128
135
|
end
|
129
136
|
|
130
137
|
## Default method for Internal Server Error, can be inherited
|
138
|
+
## @param _exception [Exception] exception from code executing
|
139
|
+
## @return [String] content of exception page
|
131
140
|
def server_error(_exception)
|
132
141
|
body default_body
|
133
142
|
end
|
@@ -150,17 +159,17 @@ module Flame
|
|
150
159
|
end
|
151
160
|
|
152
161
|
def extract_params_for(action)
|
153
|
-
|
162
|
+
## Take parameters from action method
|
154
163
|
parameters = method(action).parameters
|
155
|
-
|
164
|
+
## Fill variables with values from params
|
156
165
|
req_values, opt_values = %i[req opt].map! do |type|
|
157
166
|
params.values_at(
|
158
167
|
*parameters.select { |key, _value| key == type }.map!(&:last)
|
159
168
|
)
|
160
169
|
end
|
161
|
-
|
170
|
+
## Remove nils from the end of optional values
|
162
171
|
opt_values.pop while opt_values.last.nil? && !opt_values.empty?
|
163
|
-
|
172
|
+
## Concat values
|
164
173
|
req_values + opt_values
|
165
174
|
end
|
166
175
|
|
@@ -181,55 +190,6 @@ module Flame
|
|
181
190
|
parts = [modules.last] if parts.empty?
|
182
191
|
Flame::Path.merge nil, parts.join('_')
|
183
192
|
end
|
184
|
-
|
185
|
-
## Re-define public instance method from parent
|
186
|
-
## @example Inherit controller with parent actions by method
|
187
|
-
## class MyController < BaseController.with_actions
|
188
|
-
## end
|
189
|
-
## @example Define actions from module in controller
|
190
|
-
## class MyController < BaseController
|
191
|
-
## include with_actions Module1
|
192
|
-
## include with_actions Module2
|
193
|
-
## ....
|
194
|
-
## end
|
195
|
-
def with_actions(mod = nil)
|
196
|
-
return mod.extend(ModuleActions) if mod
|
197
|
-
@with_actions ||= Class.new(self) { extend ParentActions }
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
## Extension for modules whose public methods will be defined as actions
|
202
|
-
## via including
|
203
|
-
module ModuleActions
|
204
|
-
def included(ctrl)
|
205
|
-
public_instance_methods.each do |meth|
|
206
|
-
ctrl.send :define_method, meth, public_instance_method(meth)
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
## Module for public instance methods re-defining from superclass
|
212
|
-
## @example Inherit controller with parent actions without forbidden
|
213
|
-
## actions by `extend`
|
214
|
-
## class MyController < BaseController
|
215
|
-
## FORBIDDEN_ACTIONS = %[foo bar baz].freeze
|
216
|
-
## extend Flame::Controller::ParentActions
|
217
|
-
## end
|
218
|
-
module ParentActions
|
219
|
-
def inherited(ctrl)
|
220
|
-
ctrl.define_parent_actions
|
221
|
-
end
|
222
|
-
|
223
|
-
def self.extended(ctrl)
|
224
|
-
ctrl.define_parent_actions
|
225
|
-
end
|
226
|
-
|
227
|
-
def define_parent_actions
|
228
|
-
(superclass.actions - self::FORBIDDEN_ACTIONS).each do |public_method|
|
229
|
-
um = superclass.public_instance_method(public_method)
|
230
|
-
define_method public_method, um
|
231
|
-
end
|
232
|
-
end
|
233
193
|
end
|
234
194
|
end
|
235
195
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Flame
|
4
|
+
class Controller
|
5
|
+
## Module with methods for path or URL building
|
6
|
+
module PathTo
|
7
|
+
## Look documentation at {Flame::Dispatcher#path_to}
|
8
|
+
def path_to(*args)
|
9
|
+
add_controller_class(args)
|
10
|
+
@dispatcher.path_to(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
## Build a URI to the given controller and action, or path
|
14
|
+
def url_to(*args, **options)
|
15
|
+
first_arg = args.first
|
16
|
+
path =
|
17
|
+
if first_arg.is_a?(String) || first_arg.is_a?(Flame::Path)
|
18
|
+
find_static(first_arg).path(with_version: options[:version])
|
19
|
+
else
|
20
|
+
path_to(*args, **options)
|
21
|
+
end
|
22
|
+
Addressable::URI.new(
|
23
|
+
scheme: request.scheme, host: request.host_with_port, path: path
|
24
|
+
).to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
using GorillaPatch::Namespace
|
28
|
+
|
29
|
+
## Path to previous page, or to index action, or to Index controller
|
30
|
+
## @return [String] path to previous page or to index
|
31
|
+
def path_to_back
|
32
|
+
back_path = request.referer
|
33
|
+
return back_path if back_path && back_path != request.url
|
34
|
+
return path_to :index if self.class.actions.include?(:index)
|
35
|
+
'/'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|