tramway 0.4 → 0.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68a5dd780d7427b0c2075f140c891af3a4c33210c88a00d86e33279dc27e6c28
4
- data.tar.gz: 63701d608f5545ea95e98fac522624cc34092199fe839b16ba579d9c461c0383
3
+ metadata.gz: 9c08642e343cc49c4a282e4b8ae7741c9ecce0aa1aeaf2c345cfe1bd4c1770e4
4
+ data.tar.gz: 5e077f0ddad19fad81e7b575a473958d0ecbadf48914a37ee6885775538a7880
5
5
  SHA512:
6
- metadata.gz: 8e6c295607acc32db6b7a0bea211ddb9ba2d8e2ca141804bce78b7b51fb74a08478c38ead05962f56ecd226a57b2e7398b97c86ac6dcc7aa46c3862bd8a49f30
7
- data.tar.gz: bd89050c6d5b3391f457eea7a277cdaaa53c3fbe1f20a0567c39b659ab8a3187d2f161bed38a6b9226782191b884fe94eb63d7e7f8aa292e8ff121dcf149c521
6
+ metadata.gz: 0106dd32bbd48209be6aae488811d589266b5c485bb05bd4da483bf757bc9469933820472445c0fdd807d9c7cde21edf5e36db5a83f9f61dbbc38fbe5d523855
7
+ data.tar.gz: 1f534e4b5bc44dd6f532897042cd53d6385c1e55578281fe10172235ca5695dfa5f5acb2b5dc14849946f47256e5eda69f375f6d0e54163e7d2f291aa9f4f83c
data/README.md CHANGED
@@ -134,9 +134,7 @@ Tramway provides **convenient** form objects for Rails applications. List proper
134
134
  class UserForm < Tramway::BaseForm
135
135
  properties :email, :password, :first_name, :last_name, :phone
136
136
 
137
- def password=(value)
138
- object.password = value if value.present?
139
- end
137
+ normalizes :email, ->(value) { value.strip.downcase }
140
138
  end
141
139
  ```
142
140
 
@@ -249,6 +247,45 @@ class Admin::UsersController < Admin::ApplicationController
249
247
  end
250
248
  ```
251
249
 
250
+ ### Normalizes
251
+
252
+ Tramway Form supports `normalizes` method. It's almost the same [as in Rails](https://edgeapi.rubyonrails.org/classes/ActiveRecord/Normalization.html)
253
+
254
+ ```ruby
255
+ class UserForm < Tramway::BaseForme
256
+ properties :email, :first_name, :last_name
257
+
258
+ normalizes :email, with: ->(value) { value.strip.downcase }
259
+ normalizes :first_name, :last_name, with: ->(value) { value.strip }
260
+ end
261
+ ```
262
+
263
+ `normalizes` method arguments:
264
+ * `*properties` - collection of properties that will be normalized
265
+ * `with:` - a proc with a normalization
266
+ * `apply_on_nil` - by default is `false`. When `true` Tramway Form applies normalization on `nil` values
267
+
268
+ ### Form inheritance
269
+
270
+ Tramway Form supports inheritance of `properties` and `normalizations`
271
+
272
+ **Example**
273
+
274
+ ```ruby
275
+ class UserForm < TramwayForm
276
+ properties :email, :password
277
+
278
+ normalizes :email, with: ->(value) { value.strip.downcase }
279
+ end
280
+
281
+ class AdminForm < UserForm
282
+ properties :permissions
283
+ end
284
+
285
+ AdminForm.properties # returns [:email, :password, :permissions]
286
+ AdminForm.normalizations # contains the normalization of :email
287
+ ```
288
+
252
289
  ### Make flexible and extendable forms
253
290
 
254
291
  Tramway Form properties are not mapped to a model. You're able to make extended forms.
@@ -256,12 +293,7 @@ Tramway Form properties are not mapped to a model. You're able to make extended
256
293
  *app/forms/user_form.rb*
257
294
  ```ruby
258
295
  class UserForm < Tramway::BaseForm
259
- properties :email, :password, :full_name
260
-
261
- # RULE: in case password is empty, don't save
262
- def password=(value)
263
- object.password = value if value.present?
264
- end
296
+ properties :email, :full_name
265
297
 
266
298
  # EXTENDED FIELD: full name
267
299
  def full_name=(value)
@@ -1,9 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tramway/forms/properties'
4
+ require 'tramway/forms/normalizations'
5
+
3
6
  module Tramway
4
7
  # Provides form object for Tramway
5
8
  #
6
9
  class BaseForm
10
+ include Tramway::Forms::Properties
11
+ include Tramway::Forms::Normalizations
12
+
7
13
  attr_reader :object
8
14
 
9
15
  %i[model_name to_key to_model errors attributes].each do |method_name|
@@ -17,21 +23,11 @@ module Tramway
17
23
  end
18
24
 
19
25
  class << self
20
- def property(attribute, _proc_obj = nil)
21
- @properties ||= []
22
- @properties << attribute
23
-
24
- delegate attribute, to: :object
25
- end
26
+ def inherited(subclass)
27
+ __initialize_properties subclass
28
+ __initialize_normalizations subclass
26
29
 
27
- def properties(*attributes)
28
- if attributes.any?
29
- attributes.each do |attribute|
30
- property(attribute)
31
- end
32
- else
33
- @properties || []
34
- end
30
+ super
35
31
  end
36
32
  end
37
33
 
@@ -66,9 +62,7 @@ module Tramway
66
62
  private
67
63
 
68
64
  def __submit(params)
69
- self.class.properties.each do |attribute|
70
- public_send("#{attribute}=", params[attribute]) if params.keys.include? attribute.to_s
71
- end
65
+ __apply_properties __apply_normalizations params
72
66
  end
73
67
 
74
68
  def __object
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Forms
5
+ # This is the same `normalizes` feature like in Rails
6
+ # https://api.rubyonrails.org/v7.1/classes/ActiveRecord/Normalization/ClassMethods.html#method-i-normalizes
7
+ module Normalizations
8
+ # A collection of methods that would be using in users forms
9
+ module ClassMethods
10
+ # :reek:BooleanParameter { enabled: false }
11
+ def normalizes(*attributes, with:, apply_to_nil: false)
12
+ attributes.each do |attribute|
13
+ @normalizations.merge!(attribute => { proc: with, apply_to_nil: })
14
+ end
15
+ end
16
+
17
+ def normalizations
18
+ __ancestor_normalizations.merge(@normalizations)
19
+ end
20
+
21
+ # :reek:ManualDispatch { enabled: false }
22
+ def __ancestor_normalizations(klass = superclass)
23
+ superklass = klass.superclass
24
+
25
+ return {} unless superklass.respond_to?(:normalizations)
26
+
27
+ klass.normalizations.merge!(__ancestor_normalizations(superklass))
28
+ end
29
+
30
+ # :reek:UtilityFunction { enabled: false }
31
+ def __initialize_normalizations(subclass)
32
+ subclass.instance_variable_set(:@normalizations, {})
33
+ end
34
+ end
35
+
36
+ def self.included(base)
37
+ base.extend ClassMethods
38
+ end
39
+
40
+ def __apply_normalizations(params)
41
+ self.class.normalizations.reduce(params) do |hash, (attribute, normalization)|
42
+ if hash.key?(attribute) || normalization[:apply_to_nil]
43
+ hash.merge(attribute => instance_exec(hash[attribute], &normalization[:proc]))
44
+ else
45
+ hash
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ module Forms
5
+ # This is `properties`. The main feature of Tramway Form
6
+ module Properties
7
+ # A collection of methods that would be using in users forms
8
+ module ClassMethods
9
+ def property(attribute)
10
+ @properties << attribute
11
+
12
+ delegate attribute, to: :object
13
+ end
14
+
15
+ def properties(*attributes)
16
+ attributes.any? ? __set_properties(attributes) : __properties
17
+ end
18
+
19
+ def __set_properties(attributes)
20
+ attributes.each do |attribute|
21
+ property(attribute)
22
+ end
23
+ end
24
+
25
+ def __properties
26
+ (__ancestor_properties + @properties).uniq
27
+ end
28
+
29
+ # :reek:ManualDispatch { enabled: false }
30
+ def __ancestor_properties(klass = superclass)
31
+ superklass = klass.superclass
32
+
33
+ return [] unless superklass.respond_to?(:properties)
34
+
35
+ klass.properties + __ancestor_properties(superklass)
36
+ end
37
+
38
+ # :reek:UtilityFunction { enabled: false }
39
+ def __initialize_properties(subclass)
40
+ subclass.instance_variable_set(:@properties, [])
41
+ end
42
+ end
43
+
44
+ def self.included(base)
45
+ base.extend ClassMethods
46
+ end
47
+
48
+ def __apply_properties(params)
49
+ self.class.properties.each do |attribute|
50
+ public_send("#{attribute}=", params[attribute]) if params.key?(attribute)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tramway
4
- VERSION = '0.4'
4
+ VERSION = '0.4.2'
5
5
  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.4'
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - kalashnikovisme
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-01-20 00:00:00.000000000 Z
12
+ date: 2024-02-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dry-struct
@@ -126,6 +126,8 @@ files:
126
126
  - lib/tramway/decorators/collection_decorator.rb
127
127
  - lib/tramway/engine.rb
128
128
  - lib/tramway/forms/class_helper.rb
129
+ - lib/tramway/forms/normalizations.rb
130
+ - lib/tramway/forms/properties.rb
129
131
  - lib/tramway/helpers/decorate_helper.rb
130
132
  - lib/tramway/helpers/form_helper.rb
131
133
  - lib/tramway/helpers/navbar_helper.rb