lesli 5.0.24 → 5.1.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/lesli/application.css +1 -192
  3. data/app/helpers/lesli/customization_helper.rb +1 -1
  4. data/app/helpers/lesli/html_helper.rb +1 -1
  5. data/lib/generators/lesli/base_generator.rb +172 -0
  6. data/lib/generators/lesli/controller/controller_generator.rb +40 -0
  7. data/lib/generators/lesli/controller/templates/controller.rb.tt +86 -0
  8. data/lib/generators/lesli/model/model_generator.rb +44 -0
  9. data/lib/generators/lesli/model/templates/model.rb.tt +16 -0
  10. data/lib/generators/lesli/scaffold/scaffold_generator.rb +47 -0
  11. data/lib/generators/lesli/service/service_generator.rb +40 -0
  12. data/lib/generators/lesli/service/templates/service.rb.tt +44 -0
  13. data/lib/generators/lesli/views/templates/_form.html.erb.tt +22 -0
  14. data/lib/generators/lesli/views/templates/index.html.erb.tt +17 -0
  15. data/lib/generators/lesli/views/templates/new.html.erb.tt +4 -0
  16. data/lib/generators/lesli/views/templates/show.html.erb.tt +22 -0
  17. data/lib/generators/lesli/views/views_generator.rb +106 -0
  18. data/lib/lesli/engine.rb +1 -23
  19. data/lib/lesli/version.rb +2 -2
  20. metadata +48 -54
  21. data/app/assets/config/lesli_manifest.js +0 -42
  22. data/app/assets/images/lesli/brand/app-auth.svg +0 -9
  23. data/app/assets/images/lesli/brand/app-icon.svg +0 -48
  24. data/app/assets/images/lesli/brand/app-logo.png +0 -0
  25. data/app/assets/images/lesli/brand/app-logo.svg +0 -4
  26. data/app/assets/images/lesli/brand/favicon.png +0 -0
  27. data/app/assets/images/lesli/brand/favicon.svg +0 -61
  28. data/app/assets/images/lesli/brand/login-background.jpg +0 -0
  29. data/app/assets/images/lesli/brand/register-background.jpg +0 -0
  30. data/app/assets/javascripts/lesli/application.js +0 -1
  31. data/config/importmap.rb +0 -1
  32. data/lib/generators/application_lesli_generator_base.rb +0 -164
  33. data/lib/generators/lesli/spec/USAGE +0 -8
  34. data/lib/generators/lesli/spec/spec_generator.rb +0 -22
  35. data/lib/generators/lesli/spec/templates/spec-factory.template +0 -17
  36. data/lib/generators/lesli/spec/templates/spec-model.template +0 -70
  37. data/lib/generators/lesli/view/USAGE +0 -8
  38. data/lib/generators/lesli/view/templates/spec-factory.template +0 -17
  39. data/lib/generators/lesli/view/templates/spec-model.template +0 -70
  40. data/lib/generators/lesli/view/view_generator.rb +0 -22
  41. data/lib/lesli/r_spec.rb +0 -43
  42. data/lib/scss/_apps.scss +0 -94
  43. data/lib/scss/application.scss +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a56fbd90769c845789e9fc2097da330344938d31db26be4da238adae6e18ded8
4
- data.tar.gz: 840585ccd69d395bde16bbd9b41e4b33e4cd41343e09f35b12fe7f5452e6b513
3
+ metadata.gz: 8e75a2365623cbc3a027ab7f7d3369b889e4338329abc2d2c0a6c1a02d13e85c
4
+ data.tar.gz: 16b78e83a7728bc919a99cba8ab98cbd3fecd3b399181c5c702eeba86e9a2331
5
5
  SHA512:
6
- metadata.gz: 20d6570450c48ca8c79132403144d12c7a718dd6b91c03e346899badeacad0d2627543f0f5b5dd98274edbb600b6073c2147ac27ef09a694acd0a3d257466a19
7
- data.tar.gz: 6ab41da8a99d0b615071dedce1a4f020be93d4ffe85de5ae48a6fd5538182cec1194ff38b2daa79a16d901441463f5e376e67c403baf4a1e09509e1a3539c09c
6
+ metadata.gz: 63ad9a17d31d1d42da5559882dcd5148af37930159becd88023937ae25a08d53f213795e371d6a970412863c85e838c4c3a0f620e0d51836a3d13a93a5ab4fd5
7
+ data.tar.gz: ec30a9449b36d01f07777f793bcff6993ace743fd3f9b015d07dd1403c01d11eb439d4822aaf8625a34dc87c4b8cb8a5014bc6b3764b65e6a3ed76dd028eb2b9
@@ -1,192 +1 @@
1
- @charset "UTF-8";
2
- /*
3
- Lesli
4
-
5
- Copyright (c) 2025, Lesli Technologies, S. A.
6
-
7
- This program is free software: you can redistribute it and/or modify
8
- it under the terms of the GNU General Public License as published by
9
- the Free Software Foundation, either version 3 of the License, or
10
- (at your option) any later version.
11
-
12
- This program is distributed in the hope that it will be useful,
13
- but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- GNU General Public License for more details.
16
-
17
- You should have received a copy of the GNU General Public License
18
- along with this program. If not, see http://www.gnu.org/licenses/.
19
-
20
- Lesli · Ruby on Rails SaaS Development Framework.
21
-
22
- Made with ♥ by LesliTech
23
- Building a better future, one line of code at a time.
24
-
25
- @contact hello@lesli.tech
26
- @website https://www.lesli.tech
27
- @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
-
29
- // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
- // ·
31
- */
32
- /*
33
- Lesli
34
-
35
- Copyright (c) 2025, Lesli Technologies, S. A.
36
-
37
- This program is free software: you can redistribute it and/or modify
38
- it under the terms of the GNU General Public License as published by
39
- the Free Software Foundation, either version 3 of the License, or
40
- (at your option) any later version.
41
-
42
- This program is distributed in the hope that it will be useful,
43
- but WITHOUT ANY WARRANTY; without even the implied warranty of
44
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45
- GNU General Public License for more details.
46
-
47
- You should have received a copy of the GNU General Public License
48
- along with this program. If not, see http://www.gnu.org/licenses/.
49
-
50
- Lesli · Ruby on Rails SaaS Development Framework.
51
-
52
- Made with ♥ by LesliTech
53
- Building a better future, one line of code at a time.
54
-
55
- @contact hello@lesli.tech
56
- @website https://www.lesli.tech
57
- @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
58
-
59
- // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
60
- // ·
61
- */
62
- /**
63
- Lesli
64
-
65
- Copyright (c) 2025, Lesli Technologies, S. A.
66
-
67
- This program is free software: you can redistribute it and/or modify
68
- it under the terms of the GNU General Public License as published by
69
- the Free Software Foundation, either version 3 of the License, or
70
- (at your option) any later version.
71
-
72
- This program is distributed in the hope that it will be useful,
73
- but WITHOUT ANY WARRANTY; without even the implied warranty of
74
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75
- GNU General Public License for more details.
76
-
77
- You should have received a copy of the GNU General Public License
78
- along with this program. If not, see http://www.gnu.org/licenses/.
79
-
80
- Lesli - SCSS Utilities for websites, apps and web applications
81
-
82
- Made with ♥ by LesliTech
83
- Building a better future, one line of code at a time.
84
-
85
- @contact hello@lesli.tech
86
- @website https://www.lesli.tech
87
- @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
88
-
89
- // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
90
- // ·
91
- */
92
- /*
93
- Lesli
94
-
95
- Copyright (c) 2025, Lesli Technologies, S. A.
96
-
97
- This program is free software: you can redistribute it and/or modify
98
- it under the terms of the GNU General Public License as published by
99
- the Free Software Foundation, either version 3 of the License, or
100
- (at your option) any later version.
101
-
102
- This program is distributed in the hope that it will be useful,
103
- but WITHOUT ANY WARRANTY; without even the implied warranty of
104
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105
- GNU General Public License for more details.
106
-
107
- You should have received a copy of the GNU General Public License
108
- along with this program. If not, see http://www.gnu.org/licenses/.
109
-
110
- Lesli - SCSS Utilities for websites, apps and web applications
111
-
112
- Made with ♥ by LesliTech
113
- Building a better future, one line of code at a time.
114
-
115
- @contact hello@lesli.tech
116
- @website https://www.lesli.tech
117
- @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
118
-
119
- // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
120
- // ·
121
- */
122
- /**
123
- Lesli
124
-
125
- Copyright (c) 2025, Lesli Technologies, S. A.
126
-
127
- This program is free software: you can redistribute it and/or modify
128
- it under the terms of the GNU General Public License as published by
129
- the Free Software Foundation, either version 3 of the License, or
130
- (at your option) any later version.
131
-
132
- This program is distributed in the hope that it will be useful,
133
- but WITHOUT ANY WARRANTY; without even the implied warranty of
134
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
135
- GNU General Public License for more details.
136
-
137
- You should have received a copy of the GNU General Public License
138
- along with this program. If not, see http://www.gnu.org/licenses/.
139
-
140
- Lesli - SCSS Utilities for websites, apps and web applications
141
-
142
- Made with ♥ by LesliTech
143
- Building a better future, one line of code at a time.
144
-
145
- @contact hello@lesli.tech
146
- @website https://www.lesli.tech
147
- @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
148
-
149
- // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
150
- // ·
151
- */
152
- body.lesli.apps.show .lesli-element-header {
153
- margin-bottom: 5rem !important;
154
- }
155
- body.lesli.apps.show .engines {
156
- gap: 24px;
157
- margin-inline-end: auto;
158
- margin-inline-start: auto;
159
- }
160
- body.lesli.apps.show .engines a {
161
- flex-basis: 318px;
162
- text-align: center;
163
- padding: 2rem 0.4rem 2.8rem;
164
- border: white 1px solid;
165
- border-radius: 6px;
166
- background-color: white;
167
- transition: all ease-in-out 0.2s;
168
- box-shadow: rgba(9, 30, 66, 0.25) 0px 4px 8px -2px, rgba(9, 30, 66, 0.08) 0px 0px 0px 1px;
169
- }
170
- body.lesli.apps.show .engines a:hover {
171
- border-color: var(--lesli-color-primary);
172
- transform: translateY(-2px);
173
- }
174
- body.lesli.apps.show .engines a.is-active {
175
- background-color: #F0F4FF;
176
- border-color: var(--lesli-color-primary);
177
- }
178
- body.lesli.apps.show .engines a svg {
179
- margin-right: 0.4rem;
180
- fill: var(--lesli-color-primary);
181
- }
182
- body.lesli.apps.show .engines a p {
183
- font-size: 14;
184
- font-family: "OpenSans";
185
- }
186
- body.lesli.apps.show .engines a span {
187
- font-weight: 600;
188
- font-size: 20px;
189
- }
190
- body.lesli.apps.show .engines a span, body.lesli.apps.show .engines a p {
191
- color: var(--lesli-color-primary);
192
- }
1
+ body.lesli.apps.show .lesli-element-header{margin-bottom:5rem !important}body.lesli.apps.show .engines{gap:24px;margin-inline-end:auto;margin-inline-start:auto}body.lesli.apps.show .engines a{flex-basis:318px;text-align:center;padding:2rem .4rem 2.8rem;border:#fff 1px solid;border-radius:6px;background-color:#fff;transition:all ease-in-out .2s;box-shadow:rgba(9,30,66,.25) 0px 4px 8px -2px,rgba(9,30,66,.08) 0px 0px 0px 1px}body.lesli.apps.show .engines a:hover{border-color:var(--lesli-color-primary);transform:translateY(-2px)}body.lesli.apps.show .engines a.is-active{background-color:#f0f4ff;border-color:var(--lesli-color-primary)}body.lesli.apps.show .engines a svg{margin-right:.4rem;fill:var(--lesli-color-primary)}body.lesli.apps.show .engines a p{font-size:14;font-family:"OpenSans"}body.lesli.apps.show .engines a span{font-weight:600;font-size:20px}body.lesli.apps.show .engines a span,body.lesli.apps.show .engines a p{color:var(--lesli-color-primary)}
@@ -45,7 +45,7 @@ module Lesli
45
45
  def customization_instance_logo(tag: false, logo: "app-logo", variant: "light", mode: "web",
46
46
  options: { alt: "Logo" })
47
47
  # loading logo from builder assets
48
- logo_path = "#{lesli_instance_code}/brand/#{logo}.svg"
48
+ logo_path = "lesli_assets/brand/#{logo}.svg"
49
49
 
50
50
  # load favicon as PNG for better compatibility between web browsers
51
51
  #logo_path = "#{lesli_instance_code}/brand/#{logo}.png" if logo == "favicon"
@@ -35,7 +35,7 @@ module Lesli
35
35
 
36
36
  # Prints link tags to add favicon to websites
37
37
  def lesli_favicon
38
- icon_path = image_url("lesli/brand/favicon.svg")
38
+ icon_path = image_url("lesli_assets/brand/favicon.svg")
39
39
  safe_join([
40
40
  tag.link(href: icon_path, rel: "alternate icon"),
41
41
  tag.link(href: icon_path, rel: "icon", type: "image/svg+xml"),
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module Lesli
6
+ module Generators
7
+ # Shared base generator for all Lesli generators.
8
+ #
9
+ # This class centralizes the logic used by all generators, such as:
10
+ #
11
+ # - engine name detection
12
+ # - engine namespace detection
13
+ # - domain name normalization
14
+ # - resource naming helpers
15
+ #
16
+ # This avoids duplicating the same helper methods in every generator.
17
+ class BaseGenerator < Rails::Generators::NamedBase
18
+
19
+ private
20
+
21
+ # Returns the current engine folder name in snake_case.
22
+ #
23
+ # Examples:
24
+ # "/code/lesli_support" -> "lesli_support"
25
+ # "/code/my_engine" -> "my_engine"
26
+ # "/code/store" -> "store"
27
+ def engine_name
28
+ File.basename(ENGINE_ROOT.to_s).underscore
29
+ end
30
+
31
+ # Returns the current engine Ruby namespace in CamelCase.
32
+ #
33
+ # Examples:
34
+ # "lesli_support" -> "LesliSupport"
35
+ # "my_engine" -> "MyEngine"
36
+ # "store" -> "Store"
37
+ def engine_namespace
38
+ engine_name.camelize
39
+ end
40
+
41
+ # Returns the domain name derived from the engine namespace.
42
+ #
43
+ # Rules:
44
+ # - If the engine starts with "Lesli", remove that prefix
45
+ # - Otherwise use the full engine namespace
46
+ # - Convert the result to snake_case
47
+ #
48
+ # Examples:
49
+ # "LesliSupport" -> "support"
50
+ # "LesliCalendar" -> "calendar"
51
+ # "MyEngine" -> "my_engine"
52
+ # "Store" -> "store"
53
+ def engine_domain_name
54
+ namespace = engine_namespace
55
+
56
+ if namespace.start_with?("Lesli") && namespace != "Lesli"
57
+ namespace.delete_prefix("Lesli").underscore
58
+ else
59
+ namespace.underscore
60
+ end
61
+ end
62
+
63
+ # Returns the singular normalized resource name.
64
+ #
65
+ # Examples:
66
+ # "tickets" -> "ticket"
67
+ # "products" -> "product"
68
+ # "store" -> "store"
69
+ #
70
+ # This is the main workaround for NamedBase, because by default
71
+ # a plural input like "products" may produce class_name = "Products".
72
+ def resource_name
73
+ name.to_s.singularize.underscore
74
+ end
75
+
76
+ # Returns the plural normalized resource name.
77
+ #
78
+ # Examples:
79
+ # "ticket" -> "tickets"
80
+ # "product" -> "products"
81
+ def resource_collection_name
82
+ resource_name.pluralize
83
+ end
84
+
85
+ # Returns the Ruby model class name.
86
+ #
87
+ # Examples:
88
+ # "ticket" -> "Ticket"
89
+ # "product" -> "Product"
90
+ def resource_class_name
91
+ resource_name.camelize
92
+ end
93
+
94
+ # Returns the plural controller class name.
95
+ #
96
+ # Examples:
97
+ # "tickets" -> "Tickets"
98
+ # "products" -> "Products"
99
+ def controller_class_name
100
+ resource_collection_name.camelize
101
+ end
102
+
103
+ # Returns the service class name.
104
+ #
105
+ # Examples:
106
+ # "Ticket" -> "TicketService"
107
+ # "Product" -> "ProductService"
108
+ def service_class_name
109
+ "#{resource_class_name}Service"
110
+ end
111
+
112
+ # Returns the resource instance variable name.
113
+ #
114
+ # Examples:
115
+ # "ticket" -> "@ticket"
116
+ # "product" -> "@product"
117
+ def resource_instance
118
+ "@#{resource_name}"
119
+ end
120
+
121
+ # Returns the resource collection instance variable name.
122
+ #
123
+ # Examples:
124
+ # "tickets" -> "@tickets"
125
+ # "products" -> "@products"
126
+ def resource_collection_instance
127
+ "@#{resource_collection_name}"
128
+ end
129
+
130
+ # Returns the before_action setter method name.
131
+ #
132
+ # Examples:
133
+ # "ticket" -> "set_ticket"
134
+ # "product" -> "set_product"
135
+ def set_resource_method_name
136
+ "set_#{resource_name}"
137
+ end
138
+
139
+ # Returns the params method name.
140
+ #
141
+ # Examples:
142
+ # "ticket" -> "ticket_params"
143
+ # "product" -> "product_params"
144
+ def params_method_name
145
+ "#{resource_name}_params"
146
+ end
147
+
148
+ # Returns the namespaced model class name.
149
+ #
150
+ # Examples:
151
+ # "LesliSupport::Ticket"
152
+ # "MyEngine::Product"
153
+ def namespaced_resource_class_name
154
+ "#{engine_namespace}::#{resource_class_name}"
155
+ end
156
+
157
+ # Returns only the attribute names passed to the generator.
158
+ #
159
+ # Example:
160
+ # ["subject:string", "owner_id:integer"] -> ["subject", "owner_id"]
161
+ def permitted_attributes
162
+ return [] unless respond_to?(:attributes)
163
+
164
+ attributes.map(&:name)
165
+ end
166
+
167
+ def namespaced_model_name
168
+ "#{engine_namespace}::#{resource_class_name}"
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require_relative "../base_generator"
5
+
6
+ module Lesli
7
+ module Generators
8
+ # Generates a Lesli-style controller inside the current engine.
9
+ class ControllerGenerator < BaseGenerator
10
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
11
+
12
+ source_root File.expand_path("templates", __dir__)
13
+
14
+ # Creates the controller file from the template.
15
+ def create_controller_file
16
+ template "controller.rb.tt", controller_file_path
17
+ end
18
+
19
+ private
20
+
21
+ # Returns the controller directory inside the engine namespace.
22
+ #
23
+ # Example:
24
+ # app/controllers/lesli_support
25
+ # app/controllers/my_engine
26
+ # app/controllers/store
27
+ def controller_directory
28
+ File.join(ENGINE_ROOT, "app/controllers", engine_name)
29
+ end
30
+
31
+ # Returns the final controller file path.
32
+ #
33
+ # Example:
34
+ # app/controllers/lesli_support/tickets_controller.rb
35
+ def controller_file_path
36
+ File.join(controller_directory, "#{resource_collection_name}_controller.rb")
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= engine_namespace %>
4
+ class <%= controller_class_name %>Controller < ApplicationController
5
+ before_action :<%= set_resource_method_name %>, only: [:show, :edit, :update, :destroy]
6
+
7
+ def index
8
+ <%= resource_collection_instance %> = respond_with_pagination(
9
+ <%= service_class_name %>.new(current_user, query).index
10
+ )
11
+ end
12
+
13
+ def show
14
+ <%= resource_instance %> = <%= resource_instance %>.show
15
+ end
16
+
17
+ def new
18
+ <%= resource_instance %> = <%= resource_class_name %>.new
19
+ end
20
+
21
+ def edit
22
+ end
23
+
24
+ def create
25
+ <%= resource_name %> = <%= service_class_name %>.new(current_user, query).create(<%= params_method_name %>)
26
+
27
+ <%= resource_instance %> = <%= resource_name %>.result
28
+
29
+ if <%= resource_name %>.successful?
30
+ success("<%= resource_name %> creado de forma exitosa")
31
+
32
+ respond_with_lesli(
33
+ turbo: stream_redirection(<%= resource_name %>_path(<%= resource_instance %>.id))
34
+ )
35
+ else
36
+ respond_with_lesli(
37
+ turbo: <%= resource_name %>.errors_as_sentence
38
+ )
39
+ end
40
+ end
41
+
42
+ def update
43
+ if <%= resource_instance %>.update(<%= params_method_name %>)
44
+ respond_with_lesli(
45
+ turbo: stream_notification_success("<%= resource_class_name %> updated successfully")
46
+ )
47
+ else
48
+ respond_with_lesli(
49
+ turbo: stream_notification_danger(<%= resource_instance %>.errors)
50
+ )
51
+ end
52
+ end
53
+
54
+ def destroy
55
+ return respond_with_not_found unless <%= resource_instance %>
56
+ return respond_with_unauthorized unless <%= resource_instance %>.is_editable_by?(current_user)
57
+
58
+ <%= resource_name %>_destroy_response = <%= service_class_name %>.destroy(current_user, <%= resource_instance %>)
59
+
60
+ if <%= resource_name %>_destroy_response.successful?
61
+ respond_with_successful
62
+ else
63
+ respond_with_error(<%= resource_name %>_destroy_response.payload.errors.full_messages.to_sentence)
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def <%= set_resource_method_name %>
70
+ <%= resource_instance %> = <%= service_class_name %>.new(current_user, query).find(id: params[:id])
71
+ return respond_with_not_found unless <%= resource_instance %>.found?
72
+ end
73
+
74
+ def <%= params_method_name %>
75
+ params.require(:<%= resource_name %>).permit(
76
+ <% if permitted_attributes.any? -%>
77
+ <% permitted_attributes.each_with_index do |attribute, index| -%>
78
+ :<%= attribute %><%= "," unless index == permitted_attributes.length - 1 %>
79
+ <% end -%>
80
+ <% else -%>
81
+ # Add permitted attributes here
82
+ <% end -%>
83
+ )
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require_relative "../base_generator"
5
+
6
+ module Lesli
7
+ module Generators
8
+ # Generates a Lesli-style model inside the current engine.
9
+ #
10
+ # Example:
11
+ # rails generate lesli:model tickets
12
+ #
13
+ # Result:
14
+ # app/models/lesli_support/ticket.rb
15
+ class ModelGenerator < BaseGenerator
16
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
17
+
18
+ source_root File.expand_path("templates", __dir__)
19
+
20
+ # Creates the model file from the template.
21
+ def create_model_file
22
+ template "model.rb.tt", model_file_path
23
+ end
24
+
25
+ private
26
+
27
+ # Returns the directory where the model file should be created.
28
+ #
29
+ # Example:
30
+ # app/models/lesli_support
31
+ def model_directory
32
+ File.join(ENGINE_ROOT, "app/models", engine_name)
33
+ end
34
+
35
+ # Returns the final path of the generated model file.
36
+ #
37
+ # Example:
38
+ # app/models/lesli_support/ticket.rb
39
+ def model_file_path
40
+ File.join(model_directory, "#{resource_name}.rb")
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= engine_namespace %>
4
+ class <%= resource_class_name %> < ApplicationRecord
5
+ belongs_to :account
6
+
7
+ # Optional user relations
8
+ # belongs_to :owner, class_name: "Lesli::User"
9
+ # belongs_to :user, class_name: "Lesli::User"
10
+
11
+ # Optional item concerns
12
+ # include Lesli::Item::Tasks
13
+ # include Lesli::Item::Activities
14
+ # include Lesli::Item::Discussions
15
+ end
16
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require_relative "../base_generator"
5
+
6
+ module Lesli
7
+ module Generators
8
+ # Main Lesli scaffold generator.
9
+ #
10
+ # This generator delegates work to the specialized generators.
11
+ class ScaffoldGenerator < BaseGenerator
12
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
13
+
14
+ def invoke_model_generator
15
+ invoke "lesli:model", [name, *attributes]
16
+ end
17
+
18
+ # Invokes the custom Lesli controller generator.
19
+ def invoke_controller_generator
20
+ invoke "lesli:controller", [name, *attributes]
21
+ end
22
+
23
+ # Invokes the custom Lesli service generator.
24
+ def invoke_service_generator
25
+ invoke "lesli:service", [name, *attributes]
26
+ end
27
+
28
+ def invoke_views_generator
29
+ invoke "lesli:views", [name, *attributes]
30
+ end
31
+
32
+ def invoke_migration_generator
33
+ invoke "active_record:migration", [migration_name, *attributes]
34
+ end
35
+
36
+ def invoke_route_generator
37
+ invoke "resource_route", [resource_collection_name]
38
+ end
39
+
40
+ private
41
+
42
+ def migration_name
43
+ "create_#{engine_name}_#{resource_collection_name}"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require_relative "../base_generator"
5
+
6
+ module Lesli
7
+ module Generators
8
+ # Generates a Lesli-style service object inside the current engine.
9
+ class ServiceGenerator < BaseGenerator
10
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
11
+
12
+ source_root File.expand_path("templates", __dir__)
13
+
14
+ # Creates the service file from the template.
15
+ def create_service_file
16
+ template "service.rb.tt", service_file_path
17
+ end
18
+
19
+ private
20
+
21
+ # Returns the service directory inside the engine namespace.
22
+ #
23
+ # Example:
24
+ # app/services/lesli_support
25
+ # app/services/my_engine
26
+ # app/services/store
27
+ def service_directory
28
+ File.join(ENGINE_ROOT, "app/services", engine_name)
29
+ end
30
+
31
+ # Returns the final service file path.
32
+ #
33
+ # Example:
34
+ # app/services/lesli_support/ticket_service.rb
35
+ def service_file_path
36
+ File.join(service_directory, "#{resource_name}_service.rb")
37
+ end
38
+ end
39
+ end
40
+ end