tramway 0.4 → 0.4.2

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: 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