tramway 0.2.2 → 0.3

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
  SHA256:
3
- metadata.gz: 12b9bb73f91f5c694ee64efaa36d66a5ee68c6b41066a5e775b42e4ba81678d4
4
- data.tar.gz: 79c240ff539d4762fb8a2c4b3fe29ff05805c2699e12225d53038fafb53c5a1d
3
+ metadata.gz: 5e8751e6e662061508bb687b258c13f3dcb40460344959595a66c998608e38af
4
+ data.tar.gz: 66076bba6be9af35c2e787bf43e8e6cb00877bd5f5b53cf4b70ce37a09f78c2b
5
5
  SHA512:
6
- metadata.gz: 5ccd8cdeb8bb8b9df08d4885ff473e68ef7a29f5980460050e52db4d7b7b758da170cabece248f78589dbc102d47f1ae4c3ee1410d50d8103cbb4ffc549d0a2e
7
- data.tar.gz: 58c752011aa51d3c0afd9e074380411657a390b0a09568226de9d4c38b033d1b9b23f172b27af2a3ae137bc342185fad3736085412025d66cac4dab68e4ff994
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
- ### Tailwind components
36
+ #### Define entities with options
30
37
 
31
- Tramway uses [Tailwind](https://tailwindcss.com/) by default. All UI helpers are implemented with [ViewComponent](https://github.com/viewcomponent/view_component).
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
@@ -15,7 +15,9 @@ module Tramway
15
15
 
16
16
  def entities=(collection)
17
17
  @entities = collection.map do |entity|
18
- Tramway::Configs::Entity.new(name: entity)
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 based framework
6
- #
7
- class Entity
8
- attr_reader :name
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 initialize(name:)
11
- @name = name.to_s
12
+ def routes
13
+ OpenStruct.new index: Rails.application.routes.url_helpers.public_send(route_helper_method)
12
14
  end
13
15
 
14
- def routes
15
- underscored_name = name.parameterize.pluralize.underscore
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
- OpenStruct.new index: Rails.application.routes.url_helpers.public_send("#{underscored_name}_path")
28
+ def model_class
29
+ name.camelize.constantize
30
+ rescue StandardError
31
+ nil
18
32
  end
19
33
 
20
- def human_name
21
- OpenStruct.new single: name.capitalize, plural: name.pluralize.capitalize
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
@@ -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
@@ -51,8 +51,6 @@ module Tramway
51
51
  filling_side :left
52
52
 
53
53
  entities.each do |entity|
54
- entity.to_s.pluralize
55
-
56
54
  item entity.human_name.plural, entity.routes.index
57
55
  end
58
56
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tramway
4
- VERSION = '0.2.2'
4
+ VERSION = '0.3'
5
5
  end
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
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-struct'
4
+
5
+ # We need because of this https://dry-rb.org/gems/dry-struct/1.6/recipes/
6
+ module Types
7
+ include Dry.Types()
8
+ end
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.2.2
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-07-26 00:00:00.000000000 Z
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