lotusrb 0.3.2 → 0.4.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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/FEATURES.md +17 -0
  4. data/README.md +16 -355
  5. data/lib/lotus.rb +0 -1
  6. data/lib/lotus/action/csrf_protection.rb +167 -0
  7. data/lib/lotus/application.rb +3 -1
  8. data/lib/lotus/cli.rb +14 -13
  9. data/lib/lotus/commands/console.rb +1 -1
  10. data/lib/lotus/commands/db.rb +102 -0
  11. data/lib/lotus/commands/db/abstract.rb +15 -0
  12. data/lib/lotus/commands/db/apply.rb +14 -0
  13. data/lib/lotus/commands/db/console.rb +1 -5
  14. data/lib/lotus/commands/db/create.rb +14 -0
  15. data/lib/lotus/commands/db/drop.rb +14 -0
  16. data/lib/lotus/commands/db/migrate.rb +19 -0
  17. data/lib/lotus/commands/db/prepare.rb +14 -0
  18. data/lib/lotus/commands/db/version.rb +14 -0
  19. data/lib/lotus/commands/generate.rb +20 -20
  20. data/lib/lotus/commands/new.rb +1 -0
  21. data/lib/lotus/commands/routes.rb +1 -2
  22. data/lib/lotus/configuration.rb +29 -0
  23. data/lib/lotus/container.rb +19 -3
  24. data/lib/lotus/environment.rb +62 -9
  25. data/lib/lotus/frameworks.rb +1 -0
  26. data/lib/lotus/generators/action.rb +46 -10
  27. data/lib/lotus/generators/action/action_spec.minitest.tt +1 -1
  28. data/lib/lotus/generators/action/action_spec.rspec.tt +1 -1
  29. data/lib/lotus/generators/action/view_spec.minitest.tt +2 -1
  30. data/lib/lotus/generators/action/view_spec.rspec.tt +2 -1
  31. data/lib/lotus/generators/app.rb +39 -0
  32. data/lib/lotus/generators/app/.gitkeep +1 -0
  33. data/lib/lotus/generators/application/app.rb +184 -0
  34. data/lib/lotus/generators/application/app/.env.development.tt +3 -0
  35. data/lib/lotus/generators/application/app/.env.test.tt +3 -0
  36. data/lib/lotus/generators/application/{container/config → app}/.env.tt +0 -0
  37. data/lib/lotus/generators/application/app/.gitkeep +1 -0
  38. data/lib/lotus/generators/application/app/Gemfile.tt +35 -0
  39. data/lib/lotus/generators/application/app/Rakefile.minitest.tt +10 -0
  40. data/lib/lotus/generators/application/app/Rakefile.rspec.tt +5 -0
  41. data/lib/lotus/generators/application/app/apps/.gitkeep.tt +1 -0
  42. data/lib/lotus/generators/application/app/capybara.rb.rspec.tt +8 -0
  43. data/lib/lotus/generators/application/app/config.ru.tt +3 -0
  44. data/lib/lotus/generators/application/app/config/application.rb.tt +227 -0
  45. data/lib/lotus/generators/application/app/config/environment.rb.tt +5 -0
  46. data/lib/lotus/generators/application/app/config/routes.rb.tt +2 -0
  47. data/lib/lotus/generators/application/app/db/.gitkeep +1 -0
  48. data/lib/lotus/generators/application/app/features_helper.rb.minitest.tt +11 -0
  49. data/lib/lotus/generators/application/app/features_helper.rb.rspec.tt +12 -0
  50. data/lib/lotus/generators/application/app/gitignore.tt +2 -0
  51. data/lib/lotus/generators/application/app/lib/app_name.rb.tt +47 -0
  52. data/lib/lotus/generators/application/app/lib/chirp/entities/.gitkeep +1 -0
  53. data/lib/lotus/generators/application/app/lib/chirp/repositories/.gitkeep +1 -0
  54. data/lib/lotus/generators/application/app/lib/config/mapping.rb.tt +7 -0
  55. data/lib/lotus/generators/application/app/lotusrc.tt +3 -0
  56. data/lib/lotus/generators/application/app/rspec.rspec.tt +2 -0
  57. data/lib/lotus/generators/application/app/schema.sql.tt +0 -0
  58. data/lib/lotus/generators/application/app/spec_helper.rb.minitest.tt +7 -0
  59. data/lib/lotus/generators/application/app/spec_helper.rb.rspec.tt +100 -0
  60. data/lib/lotus/generators/application/app/templates/application.html.erb.tt +9 -0
  61. data/lib/lotus/generators/application/app/views/application_layout.rb.tt +7 -0
  62. data/lib/lotus/generators/application/container.rb +37 -13
  63. data/lib/lotus/generators/application/container/{config/.env.development.tt → .env.development.tt} +0 -0
  64. data/lib/lotus/generators/application/container/{config/.env.test.tt → .env.test.tt} +0 -0
  65. data/lib/lotus/generators/application/container/.env.tt +1 -0
  66. data/lib/lotus/generators/application/container/lib/app_name.rb.tt +9 -0
  67. data/lib/lotus/generators/application/container/schema.sql.tt +0 -0
  68. data/lib/lotus/generators/migration.rb +58 -0
  69. data/lib/lotus/generators/migration/migration.rb.tt +4 -0
  70. data/lib/lotus/generators/model.rb +10 -7
  71. data/lib/lotus/generators/slice.rb +4 -12
  72. data/lib/lotus/generators/slice/application.rb.tt +3 -19
  73. data/lib/lotus/generators/slice/config/routes.rb.tt +1 -7
  74. data/lib/lotus/loader.rb +15 -1
  75. data/lib/lotus/lotusrc.rb +8 -3
  76. data/lib/lotus/templates/{welcome.html → welcome.html.erb} +4 -3
  77. data/lib/lotus/version.rb +1 -1
  78. data/lib/lotus/welcome.rb +20 -1
  79. data/lotusrb.gemspec +5 -5
  80. metadata +67 -18
  81. data/lib/lotus/generators/slice/action.rb.tt +0 -8
  82. data/lib/lotus/generators/slice/config/mapping.rb.tt +0 -13
  83. data/lib/lotus/generators/slice/templates/template.html.erb.tt +0 -2
  84. data/lib/lotus/generators/slice/view.rb.tt +0 -5
  85. data/lib/lotus/logger.rb +0 -141
@@ -0,0 +1,14 @@
1
+ require 'lotus/commands/db/abstract'
2
+
3
+ module Lotus
4
+ module Commands
5
+ class DB
6
+ class Prepare < Abstract
7
+ def start
8
+ require 'lotus/model/migrator'
9
+ Lotus::Model::Migrator.prepare
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ require 'lotus/commands/db/abstract'
2
+
3
+ module Lotus
4
+ module Commands
5
+ class DB
6
+ class Version < Abstract
7
+ def start
8
+ require 'lotus/model/migrator'
9
+ puts Lotus::Model::Migrator.version
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -10,8 +10,7 @@ module Lotus
10
10
  # @since 0.3.0
11
11
  # @api private
12
12
  GENERATORS_NAMESPACE = "Lotus::Generators::%s".freeze
13
- APP = 'app'.freeze
14
- SLICE_TYPE = 'slice'.freeze
13
+ APP_ARCHITECTURE = 'app'.freeze
15
14
 
16
15
  # @since 0.3.0
17
16
  # @api private
@@ -20,21 +19,23 @@ module Lotus
20
19
 
21
20
  # @since 0.3.0
22
21
  # @api private
23
- attr_reader :cli, :source, :target, :app, :app_name, :name, :options
22
+ attr_reader :cli, :source, :target, :app, :app_name, :name, :options, :env
24
23
 
25
24
  # @since 0.3.0
26
25
  # @api private
27
26
  def initialize(type, app_name, name, env, cli)
28
27
  @cli = cli
28
+ @env = env
29
29
  @name = name
30
+ @options = env.to_options.merge(cli.options)
31
+
32
+ sanitize_input(app_name, name)
33
+ @type = type
30
34
 
31
- @type = sanitize_type(type)
32
- @app_name = app_name
33
35
  @source = Pathname.new(::File.dirname(__FILE__) + "/../generators/#{ @type }/").realpath
34
36
  @target = Pathname.pwd.realpath
35
37
 
36
38
  @app = Utils::String.new(@app_name).classify
37
- @options = sanitize_app_name_options(app_name).merge(env.to_options.merge(cli.options))
38
39
  end
39
40
 
40
41
  # @since 0.3.0
@@ -49,7 +50,11 @@ module Lotus
49
50
  # @since 0.3.0
50
51
  # @api private
51
52
  def app_root
52
- @app_root ||= Pathname.new([@options[:path], @app_name].join(::File::SEPARATOR))
53
+ @app_root ||= begin
54
+ result = Pathname.new(@options[:apps_path])
55
+ result = result.join(@app_name) if @env.container?
56
+ result
57
+ end
53
58
  end
54
59
 
55
60
  # @since 0.3.0
@@ -74,19 +79,14 @@ module Lotus
74
79
  Utils::Class.load!(GENERATORS_NAMESPACE % class_name).new(self)
75
80
  end
76
81
 
77
- # @since 0.3.1
78
- # @api private
79
- def sanitize_app_name_options(app_name)
80
- {
81
- application: app_name,
82
- application_base_url: "/#{app_name}"
83
- }
84
- end
85
-
86
- # @since 0.3.1
87
- # @api private
88
- def sanitize_type(type)
89
- type == APP ? SLICE_TYPE : type
82
+ def sanitize_input(app_name, name)
83
+ if options[:architecture] == APP_ARCHITECTURE
84
+ @app_name = nil
85
+ @name = app_name
86
+ else
87
+ @app_name = app_name
88
+ @name = name
89
+ end
90
90
  end
91
91
  end
92
92
  end
@@ -1,4 +1,5 @@
1
1
  require 'pathname'
2
+ require 'securerandom'
2
3
  require 'lotus/application_name'
3
4
  require 'lotus/utils/string'
4
5
  require 'lotus/utils/class'
@@ -2,11 +2,10 @@ module Lotus
2
2
  module Commands
3
3
  class Routes
4
4
  def initialize(environment)
5
- @environment = environment
5
+ environment.require_application_environment
6
6
  end
7
7
 
8
8
  def start
9
- require @environment.env_config
10
9
  puts Lotus::Container.new.routes.inspector.to_s
11
10
  end
12
11
  end
@@ -108,6 +108,21 @@ module Lotus
108
108
  @security ||= Config::Security.new
109
109
  end
110
110
 
111
+ # Force ssl redirection if http scheme is set
112
+ #
113
+ # @return [Boolean]
114
+ #
115
+ # @since 0.4.0
116
+ #
117
+ # @see Lotus::Routing::ForceSsl
118
+ def force_ssl(value = nil)
119
+ if value
120
+ @force_ssl = value
121
+ else
122
+ @force_ssl || false
123
+ end
124
+ end
125
+
111
126
  # The root of the application
112
127
  #
113
128
  # By default it returns the current directory, for this reason, **all the
@@ -1627,6 +1642,20 @@ module Lotus
1627
1642
  @view ||= Config::FrameworkConfiguration.new
1628
1643
  end
1629
1644
 
1645
+ # This options is used as a bridge between container and router application.
1646
+ #
1647
+ # @return [String, NilClass] path prefix for routes
1648
+ #
1649
+ # @since 0.4.0
1650
+ # @api private
1651
+ def path_prefix(value = nil)
1652
+ if value.nil?
1653
+ @path_prefix
1654
+ else
1655
+ @path_prefix = value
1656
+ end
1657
+ end
1658
+
1630
1659
  private
1631
1660
  # @since 0.2.0
1632
1661
  # @api private
@@ -3,16 +3,32 @@ require 'lotus/router'
3
3
 
4
4
  module Lotus
5
5
  class Container
6
+ class Router < ::Lotus::Router
7
+ def mount(app, options)
8
+ app = app.new(path_prefix: options.fetch(:at)) if lotus_app?(app)
9
+ super(app, options)
10
+ end
11
+
12
+ private
13
+
14
+ def lotus_app?(app)
15
+ app.ancestors.include? Lotus::Application
16
+ end
17
+ end
18
+
6
19
  attr_reader :routes
7
20
 
8
- def self.configure(&blk)
9
- Mutex.new.synchronize { @@configuration = blk }
21
+ def self.configure(options = {}, &blk)
22
+ Mutex.new.synchronize do
23
+ @@options = options
24
+ @@configuration = blk
25
+ end
10
26
  end
11
27
 
12
28
  def initialize
13
29
  Mutex.new.synchronize do
14
30
  assert_configuration_presence!
15
- @routes = Lotus::Router.new(&@@configuration)
31
+ @routes = Router.new(&@@configuration)
16
32
  end
17
33
  end
18
34
 
@@ -94,6 +94,22 @@ module Lotus
94
94
  # @api private
95
95
  CODE_RELOADING = { 'development' => true }.freeze
96
96
 
97
+ # @since 0.4.0
98
+ # @api private
99
+ CONTAINER = 'container'.freeze
100
+
101
+ # @since 0.4.0
102
+ # @api private
103
+ CONTAINER_PATH = 'apps'.freeze
104
+
105
+ # @since 0.4.0
106
+ # @api private
107
+ APPLICATION = 'app'.freeze
108
+
109
+ # @since 0.4.0
110
+ # @api private
111
+ APPLICATION_PATH = 'app'.freeze
112
+
97
113
  # Initialize a Lotus environment
98
114
  #
99
115
  # It accepts an optional set of configurations from the CLI commands.
@@ -121,17 +137,17 @@ module Lotus
121
137
  #
122
138
  # @example Define ENV variables from .env
123
139
  #
124
- # # % tree config/
125
- # # config
140
+ # # % tree .
141
+ # # .
142
+ # # # ...
126
143
  # # ├── .env
127
- # # ├── .env.development
128
- # # └── environment.rb
144
+ # # └── .env.development
129
145
  #
130
- # # % cat config/.env
146
+ # # % cat .env
131
147
  # # FOO="bar"
132
148
  # # XYZ="yes"
133
149
  #
134
- # # % cat config/.env.development
150
+ # # % cat .env.development
135
151
  # # FOO="ok"
136
152
  #
137
153
  # require 'lotus/environment'
@@ -156,7 +172,7 @@ module Lotus
156
172
  # # the one defined in the parent (eg `FOO` is overwritten). All the
157
173
  # # other settings (eg `XYZ`) will be left untouched.
158
174
  def initialize(options = {})
159
- @options = Lotus::Lotusrc.new(root).read
175
+ @options = Lotus::Lotusrc.new(root, options).read
160
176
  @options.merge! Utils::Hash.new(options).symbolize!
161
177
  @mutex = Mutex.new
162
178
  @mutex.synchronize { set_env_vars! }
@@ -315,6 +331,16 @@ module Lotus
315
331
  root.join(@options.fetch(:environment) { config.join(DEFAULT_ENVIRONMENT_CONFIG) })
316
332
  end
317
333
 
334
+ # Require application environment
335
+ #
336
+ # Eg <tt>require "config/environment"</tt>.
337
+ #
338
+ # @since 0.4.0
339
+ # @api private
340
+ def require_application_environment
341
+ require env_config.to_s
342
+ end
343
+
318
344
  # Determine if activate code reloading for the current environment while
319
345
  # running the server.
320
346
  #
@@ -337,6 +363,32 @@ module Lotus
337
363
  @options.fetch(:code_reloading) { !!CODE_RELOADING[environment] }
338
364
  end
339
365
 
366
+ # @since 0.4.0
367
+ # @api private
368
+ def architecture
369
+ @options.fetch(:architecture) {
370
+ puts "Cannot recognize Lotus architecture, please check `.lotusrc'"
371
+ exit 1
372
+ }
373
+ end
374
+
375
+ # @since 0.4.0
376
+ # @api private
377
+ def container?
378
+ architecture == CONTAINER
379
+ end
380
+
381
+ # @since 0.4.0
382
+ # @api private
383
+ def apps_path
384
+ @options.fetch(:path) {
385
+ case architecture
386
+ when CONTAINER then CONTAINER_PATH
387
+ when APPLICATION then APPLICATION_PATH
388
+ end
389
+ }
390
+ end
391
+
340
392
  # Serialize the most relevant settings into a Hash
341
393
  #
342
394
  # @return [Lotus::Utils::Hash]
@@ -347,6 +399,7 @@ module Lotus
347
399
  @options.merge(
348
400
  environment: environment,
349
401
  env_config: env_config,
402
+ apps_path: apps_path,
350
403
  rackup: rackup,
351
404
  host: host,
352
405
  port: port
@@ -373,8 +426,8 @@ module Lotus
373
426
  # @since 0.2.0
374
427
  # @api private
375
428
  def set_application_env_vars!
376
- Dotenv.load config.join(DEFAULT_DOTENV)
377
- Dotenv.overload config.join(DEFAULT_DOTENV_ENV % environment)
429
+ Dotenv.load root.join(DEFAULT_DOTENV)
430
+ Dotenv.overload root.join(DEFAULT_DOTENV_ENV % environment)
378
431
  end
379
432
 
380
433
  # @since 0.1.0
@@ -2,6 +2,7 @@ require 'lotus/router'
2
2
  require 'lotus/view'
3
3
  require 'lotus/controller'
4
4
  require 'lotus/action/glue'
5
+ require 'lotus/action/csrf_protection'
5
6
 
6
7
  Lotus::Controller.configure do
7
8
  prepare do
@@ -42,12 +42,14 @@ module Lotus
42
42
  assert_action!
43
43
 
44
44
  opts = {
45
- app: app,
46
- controller: @controller_name,
47
- action: @action_name,
48
- action_path: _action_path_without_suffix,
49
- view_path: _view_path_without_suffix,
50
- template_path: _template_path,
45
+ app: app,
46
+ controller: @controller_name,
47
+ action: @action_name,
48
+ action_path: _action_path_without_suffix,
49
+ relative_action_path: _relative_action_path,
50
+ relative_view_path: _relative_view_path,
51
+ view_path: _view_path_without_suffix,
52
+ template_path: _template_path,
51
53
  }
52
54
 
53
55
  test_type = case options[:test]
@@ -98,6 +100,15 @@ module Lotus
98
100
  end
99
101
  end
100
102
 
103
+ def app
104
+ if env.container?
105
+ super
106
+ else
107
+ env.require_application_environment
108
+ Utils::String.new(Lotus::Application.applications.first).namespace
109
+ end
110
+ end
111
+
101
112
  # @since 0.3.0
102
113
  # @api private
103
114
  def generate_route
@@ -108,14 +119,21 @@ module Lotus
108
119
 
109
120
  # Insert at the top of the file
110
121
  cli.insert_into_file _routes_path, before: /\A(.*)/ do
111
- "get '/#{ @controller }', to: '#{ @name }'\n"
122
+ "get '#{ _route_url }', to: '#{ @name }'\n"
112
123
  end
113
124
  end
114
125
 
126
+ # @since 0.4.0
127
+ # @api private
128
+ def _route_url
129
+ options.fetch(:url, "/#{ @controller }")
130
+ end
131
+
115
132
  # @since 0.3.0
116
133
  # @api private
117
134
  def _routes_path
118
- app_root.join("config", "routes#{ SUFFIX }")
135
+ routes_root = env.container? ? app_root : env.root
136
+ routes_root.join("config", "routes#{ SUFFIX }")
119
137
  end
120
138
 
121
139
  # @since 0.3.0
@@ -151,13 +169,31 @@ module Lotus
151
169
  # @since 0.3.0
152
170
  # @api private
153
171
  def _action_spec_path
154
- spec_root.join(app_name, 'controllers', @controller, "#{ @action }_spec#{ SUFFIX }")
172
+ spec_root.join(app_name.to_s, 'controllers', @controller, "#{ @action }_spec#{ SUFFIX }")
155
173
  end
156
174
 
157
175
  # @since 0.3.0
158
176
  # @api private
159
177
  def _view_spec_path
160
- spec_root.join(app_name, 'views', @controller, "#{ @action }_spec#{ SUFFIX }")
178
+ spec_root.join(app_name.to_s, 'views', @controller, "#{ @action }_spec#{ SUFFIX }")
179
+ end
180
+
181
+ # @since 0.4.0
182
+ # @api private
183
+ def _relative_action_path
184
+ result = '../../../'
185
+ result << '../' if env.container?
186
+ result << _action_path_without_suffix.to_s
187
+ result
188
+ end
189
+
190
+ # @since 0.4.0
191
+ # @api private
192
+ def _relative_view_path
193
+ result = '../../../'
194
+ result << '../' if env.container?
195
+ result << _view_path_without_suffix.to_s
196
+ result
161
197
  end
162
198
  end
163
199
  end
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
- require_relative '../../../../<%= config[:action_path] %>'
2
+ require_relative '<%= config[:relative_action_path] %>'
3
3
 
4
4
  describe <%= config[:app] %>::Controllers::<%= config[:controller] %>::<%= config[:action] %> do
5
5
  let(:action) { <%= config[:app] %>::Controllers::<%= config[:controller] %>::<%= config[:action] %>.new }
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
- require_relative '../../../../<%= config[:action_path] %>'
2
+ require_relative '<%= config[:relative_action_path] %>'
3
3
 
4
4
  describe <%= config[:app] %>::Controllers::<%= config[:controller] %>::<%= config[:action] %> do
5
5
  let(:action) { <%= config[:app] %>::Controllers::<%= config[:controller] %>::<%= config[:action] %>.new }