tramway 0.2.2 → 0.3
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/README.md +172 -2
- data/lib/tramway/base_form.rb +76 -0
- data/lib/tramway/config.rb +3 -1
- data/lib/tramway/configs/entities/route.rb +18 -0
- data/lib/tramway/configs/entity.rb +31 -11
- data/lib/tramway/engine.rb +6 -0
- data/lib/tramway/forms/class_helper.rb +22 -0
- data/lib/tramway/helpers/form_helper.rb +15 -0
- data/lib/tramway/navbar.rb +0 -2
- data/lib/tramway/version.rb +1 -1
- data/lib/tramway.rb +2 -0
- data/lib/types.rb +8 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e8751e6e662061508bb687b258c13f3dcb40460344959595a66c998608e38af
|
4
|
+
data.tar.gz: 66076bba6be9af35c2e787bf43e8e6cb00877bd5f5b53cf4b70ce37a09f78c2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aec595653662af5dfe38f8d402dd799d8da2ad77ba8c3e032aba22c56020467f9b4ee1f701a07e7477ecbd34ff7725c32fac18a6a359513e064dbbdc567d703c
|
7
|
+
data.tar.gz: 5e1799a4d4290ac7bf5e9bd8c1fe524119eb4449ffe0ddeccb3ecf934343160672572c22e834f76a7bebe522d4ca226aa08ce8336ba1f56f88dc53fe692eba72
|
data/README.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
# Tramway
|
2
2
|
Unite Ruby on Rails brilliance. Streamline development with Tramway.
|
3
3
|
|
4
|
+
* [Installation](https://github.com/Purple-Magic/tramway#installation)
|
5
|
+
* [Usage](https://github.com/Purple-Magic/tramway#usage)
|
6
|
+
* [Tramway Entities](https://github.com/Purple-Magic/tramway#tramway-entities)
|
7
|
+
* [Tramway Decorators](https://github.com/Purple-Magic/tramway#tramway-decorators)
|
8
|
+
* [Tramway Form](https://github.com/Purple-Magic/tramway#tramway-form)
|
9
|
+
* [Tramway Navbar](https://github.com/Purple-Magic/tramway#tramway-navbar)
|
10
|
+
|
4
11
|
## Installation
|
5
12
|
Add this line to your application's Gemfile:
|
6
13
|
|
@@ -26,9 +33,22 @@ end
|
|
26
33
|
|
27
34
|
By default, links to the Tramway Entities index page are rendered in [Tramway Navbar](https://github.com/Purple-Magic/tramway#tramway-navbar).
|
28
35
|
|
29
|
-
|
36
|
+
#### Define entities with options
|
30
37
|
|
31
|
-
Tramway
|
38
|
+
Tramway Entity supports several options that are used in different features.
|
39
|
+
|
40
|
+
**route**
|
41
|
+
|
42
|
+
*config/initializers/tramway.rb*
|
43
|
+
```ruby
|
44
|
+
Tramway.configure do |config|
|
45
|
+
config.entities = [
|
46
|
+
{ name: :user, route: { namespace: :admin } }, # `admin_users_path` link in the Tramway Navbar
|
47
|
+
{ name: :podcast, route: { route_method: :shows } }, # `shows_path` link in the Tramway Navbar
|
48
|
+
{ name: :episodes, route: { namespace: :podcasts, route_method: :episodes } }, # `podcasts_episodes_path` link in the Tramway Navbar
|
49
|
+
]
|
50
|
+
end
|
51
|
+
```
|
32
52
|
|
33
53
|
### Tramway Decorators
|
34
54
|
|
@@ -80,6 +100,152 @@ def show
|
|
80
100
|
end
|
81
101
|
```
|
82
102
|
|
103
|
+
### Tramway Form
|
104
|
+
|
105
|
+
Tramway provides **convenient** form objects for Rails applications. List properties you want to change and the rules in Form classes. No controllers overloading.
|
106
|
+
|
107
|
+
*app/forms/user_form.rb
|
108
|
+
```ruby
|
109
|
+
class UserForm < Tramway::BaseForm
|
110
|
+
properties :email, :password, :first_name, :last_name, :phone
|
111
|
+
|
112
|
+
def password=(value)
|
113
|
+
object.password = value if value.present?
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
**Controllers without Tramway Form**
|
119
|
+
|
120
|
+
*app/controllers/users_controller.rb*
|
121
|
+
```ruby
|
122
|
+
class UsersController < ApplicationController
|
123
|
+
def create
|
124
|
+
@user = User.new
|
125
|
+
if @user.save user_params
|
126
|
+
render :show
|
127
|
+
else
|
128
|
+
render :new
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def update
|
133
|
+
@user = User.find params[:id]
|
134
|
+
if @user.save user_params
|
135
|
+
render :show
|
136
|
+
else
|
137
|
+
render :edit
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def user_params
|
144
|
+
params[:user].permit(:email, :password, :first_name, :last_name, :phone)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
**Controllers with Tramway Form**
|
150
|
+
|
151
|
+
*app/controllers/users_controller.rb*
|
152
|
+
```ruby
|
153
|
+
class UsersController < ApplicationController
|
154
|
+
def create
|
155
|
+
@user = tramway_form User.new
|
156
|
+
if @user.submit params[:user]
|
157
|
+
render :show
|
158
|
+
else
|
159
|
+
render :new
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def update
|
164
|
+
@user = tramway_form User.find params[:id]
|
165
|
+
if @user.submit params[:user]
|
166
|
+
render :show
|
167
|
+
else
|
168
|
+
render :edit
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
#### Implement Form objects for any case
|
175
|
+
|
176
|
+
*app/forms/user_updating_email_form.rb*
|
177
|
+
```ruby
|
178
|
+
class UserUpdatingEmailForm < Tramway::BaseForm
|
179
|
+
properties :email
|
180
|
+
end
|
181
|
+
```
|
182
|
+
|
183
|
+
*app/controllers/updating_emails_controller.rb*
|
184
|
+
```ruby
|
185
|
+
def update
|
186
|
+
@user = UserUpdatingEmailForm.new User.find params[:id]
|
187
|
+
if @user.submit params[:user]
|
188
|
+
# success
|
189
|
+
else
|
190
|
+
# failure
|
191
|
+
end
|
192
|
+
end
|
193
|
+
```
|
194
|
+
|
195
|
+
#### Create form namespaces
|
196
|
+
|
197
|
+
*app/forms/admin/user_form.rb*
|
198
|
+
```ruby
|
199
|
+
class Admin::UserForm < Tramway::BaseForm
|
200
|
+
properties :email, :password, :first_name, :last_name, :etc
|
201
|
+
end
|
202
|
+
```
|
203
|
+
|
204
|
+
*app/controllers/admin/users_controller.rb*
|
205
|
+
```ruby
|
206
|
+
class Admin::UsersController < Admin::ApplicationController
|
207
|
+
def create
|
208
|
+
@user = tramway_form User.new, namespace: :admin
|
209
|
+
if @user.submit params[:user]
|
210
|
+
render :show
|
211
|
+
else
|
212
|
+
render :new
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def update
|
217
|
+
@user = tramway_form User.find(params[:id]), namespace: :admin
|
218
|
+
if @user.submit params[:user]
|
219
|
+
render :show
|
220
|
+
else
|
221
|
+
render :edit
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
```
|
226
|
+
|
227
|
+
### Make flexible and extendable forms
|
228
|
+
|
229
|
+
Tramway Form properties are not mapped to a model. You're able to make extended forms.
|
230
|
+
|
231
|
+
*app/forms/user_form.rb*
|
232
|
+
```ruby
|
233
|
+
class UserForm < Tramway::BaseForm
|
234
|
+
properties :email, :password, :full_name
|
235
|
+
|
236
|
+
# RULE: in case password is empty, don't save
|
237
|
+
def password=(value)
|
238
|
+
object.password = value if value.present?
|
239
|
+
end
|
240
|
+
|
241
|
+
# EXTENDED FIELD: full name
|
242
|
+
def full_name=(value)
|
243
|
+
object.first_name = value.split(' ').first
|
244
|
+
object.last_name = value.split(' ').last
|
245
|
+
end
|
246
|
+
end
|
247
|
+
```
|
248
|
+
|
83
249
|
### Tramway Navbar
|
84
250
|
|
85
251
|
Tramway provides DSL for rendering Tailwind Navgiation bar.
|
@@ -146,6 +312,10 @@ tramway_navbar title: 'Purple Magic' do |nav|
|
|
146
312
|
end
|
147
313
|
```
|
148
314
|
|
315
|
+
### Tailwind components
|
316
|
+
|
317
|
+
Tramway uses [Tailwind](https://tailwindcss.com/) by default. All UI helpers are implemented with [ViewComponent](https://github.com/viewcomponent/view_component).
|
318
|
+
|
149
319
|
## Contributing
|
150
320
|
|
151
321
|
Install [lefthook](https://github.com/evilmartians/lefthook)
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tramway
|
4
|
+
# Provides form object for Tramway
|
5
|
+
#
|
6
|
+
class BaseForm
|
7
|
+
attr_reader :object
|
8
|
+
|
9
|
+
%i[model_name to_key to_model errors attributes].each do |method_name|
|
10
|
+
delegate method_name, to: :object
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(object)
|
14
|
+
@object = object
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def property(attribute, _proc_obj = nil)
|
19
|
+
@properties ||= []
|
20
|
+
@properties << attribute
|
21
|
+
|
22
|
+
delegate attribute, to: :object
|
23
|
+
end
|
24
|
+
|
25
|
+
def properties(*attributes)
|
26
|
+
if attributes.any?
|
27
|
+
attributes.each do |attribute|
|
28
|
+
property(attribute)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
@properties || []
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def submit(params)
|
37
|
+
__submit params
|
38
|
+
|
39
|
+
object.save.tap do
|
40
|
+
__object
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def submit!(params)
|
45
|
+
__submit params
|
46
|
+
|
47
|
+
object.save!.tap do
|
48
|
+
__object
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def method_missing(method_name, *args)
|
53
|
+
if method_name.to_s.end_with?('=') && args.count == 1
|
54
|
+
object.public_send(method_name, args.first)
|
55
|
+
else
|
56
|
+
super
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def respond_to_missing?(method_name, include_private = false)
|
61
|
+
method_name.to_s.end_with?('=') || super
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def __submit(params)
|
67
|
+
self.class.properties.each do |attribute|
|
68
|
+
public_send("#{attribute}=", params[attribute])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def __object
|
73
|
+
object.persisted? ? object.reload : object
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/tramway/config.rb
CHANGED
@@ -15,7 +15,9 @@ module Tramway
|
|
15
15
|
|
16
16
|
def entities=(collection)
|
17
17
|
@entities = collection.map do |entity|
|
18
|
-
|
18
|
+
entity_options = entity.is_a?(Hash) ? entity : { name: entity }
|
19
|
+
|
20
|
+
Tramway::Configs::Entity.new(**entity_options)
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tramway
|
4
|
+
module Configs
|
5
|
+
module Entities
|
6
|
+
# Route struct describes rules for route management
|
7
|
+
#
|
8
|
+
class Route < Dry::Struct
|
9
|
+
attribute? :namespace, Types::Coercible::String
|
10
|
+
attribute? :route_method, Types::Coercible::String
|
11
|
+
|
12
|
+
def helper_method_by(underscored_name)
|
13
|
+
"#{[namespace, route_method || underscored_name].compact.join('_')}_path"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,24 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'tramway/configs/entities/route'
|
4
|
+
|
3
5
|
module Tramway
|
4
6
|
module Configs
|
5
|
-
# Tramway is entity
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
# Tramway is an entity-based framework
|
8
|
+
class Entity < Dry::Struct
|
9
|
+
attribute :name, Types::Coercible::String
|
10
|
+
attribute? :route, Tramway::Configs::Entities::Route
|
9
11
|
|
10
|
-
def
|
11
|
-
|
12
|
+
def routes
|
13
|
+
OpenStruct.new index: Rails.application.routes.url_helpers.public_send(route_helper_method)
|
12
14
|
end
|
13
15
|
|
14
|
-
def
|
15
|
-
|
16
|
+
def human_name
|
17
|
+
options = if model_class.present?
|
18
|
+
model_name = model_class.model_name.human
|
19
|
+
{ single: model_name, plural: model_name.pluralize }
|
20
|
+
else
|
21
|
+
{ single: name.capitalize, plural: name.pluralize.capitalize }
|
22
|
+
end
|
23
|
+
OpenStruct.new(**options)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
16
27
|
|
17
|
-
|
28
|
+
def model_class
|
29
|
+
name.camelize.constantize
|
30
|
+
rescue StandardError
|
31
|
+
nil
|
18
32
|
end
|
19
33
|
|
20
|
-
def
|
21
|
-
|
34
|
+
def route_helper_method
|
35
|
+
underscored_name = name.parameterize.pluralize.underscore
|
36
|
+
|
37
|
+
if route.present?
|
38
|
+
route.helper_method_by(underscored_name)
|
39
|
+
else
|
40
|
+
"#{underscored_name}_path"
|
41
|
+
end
|
22
42
|
end
|
23
43
|
end
|
24
44
|
end
|
data/lib/tramway/engine.rb
CHANGED
@@ -18,6 +18,12 @@ module Tramway
|
|
18
18
|
|
19
19
|
loaded_class.include Tramway::Helpers::DecorateHelper
|
20
20
|
end
|
21
|
+
|
22
|
+
ActiveSupport.on_load(:action_controller) do |loaded_class|
|
23
|
+
require 'tramway/helpers/form_helper'
|
24
|
+
|
25
|
+
loaded_class.include Tramway::Helpers::FormHelper
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
23
29
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tramway
|
4
|
+
module Forms
|
5
|
+
# Provides method to determine decorators classes
|
6
|
+
module ClassHelper
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def form_class(object, form, namespace)
|
10
|
+
object_class = object.class
|
11
|
+
|
12
|
+
if form.present?
|
13
|
+
form
|
14
|
+
elsif namespace.present?
|
15
|
+
"#{namespace.to_s.camelize}::#{object_class}Form".constantize
|
16
|
+
else
|
17
|
+
"#{object_class}Form".constantize
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tramway/forms/class_helper'
|
4
|
+
|
5
|
+
module Tramway
|
6
|
+
module Helpers
|
7
|
+
# Provides methods into Rails ActionController
|
8
|
+
#
|
9
|
+
module FormHelper
|
10
|
+
def tramway_form(object, form: nil, namespace: nil)
|
11
|
+
Tramway::Forms::ClassHelper.form_class(object, form, namespace).new object
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/tramway/navbar.rb
CHANGED
data/lib/tramway/version.rb
CHANGED
data/lib/tramway.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'types'
|
3
4
|
require 'tramway/version'
|
4
5
|
require 'tramway/engine'
|
5
6
|
require 'tramway/base_decorator'
|
7
|
+
require 'tramway/base_form'
|
6
8
|
require 'tramway/config'
|
7
9
|
require 'view_component/compiler'
|
8
10
|
require 'view_component/engine'
|
data/lib/types.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tramway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kalashnikovisme
|
@@ -9,8 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-09-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: dry-struct
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
14
28
|
- !ruby/object:Gem::Dependency
|
15
29
|
name: haml-rails
|
16
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,16 +102,21 @@ files:
|
|
88
102
|
- lib/tasks/tramway_tasks.rake
|
89
103
|
- lib/tramway.rb
|
90
104
|
- lib/tramway/base_decorator.rb
|
105
|
+
- lib/tramway/base_form.rb
|
91
106
|
- lib/tramway/config.rb
|
107
|
+
- lib/tramway/configs/entities/route.rb
|
92
108
|
- lib/tramway/configs/entity.rb
|
93
109
|
- lib/tramway/decorators/class_helper.rb
|
94
110
|
- lib/tramway/decorators/collection_decorator.rb
|
95
111
|
- lib/tramway/engine.rb
|
112
|
+
- lib/tramway/forms/class_helper.rb
|
96
113
|
- lib/tramway/helpers/decorate_helper.rb
|
114
|
+
- lib/tramway/helpers/form_helper.rb
|
97
115
|
- lib/tramway/helpers/navbar_helper.rb
|
98
116
|
- lib/tramway/navbar.rb
|
99
117
|
- lib/tramway/utils/render.rb
|
100
118
|
- lib/tramway/version.rb
|
119
|
+
- lib/types.rb
|
101
120
|
homepage: https://github.com/purple-magic/tramway
|
102
121
|
licenses:
|
103
122
|
- MIT
|