application_form 0.4.0 → 0.5.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: 05c6c488f4f25253c2fb3889eda3776207218a8a1bfb7101b18e9fc38fc5e663
4
- data.tar.gz: e8c073b39558f58391202b6d7353cc4be57e7c4df01987f31b1b624012fd010f
3
+ metadata.gz: b81f5d6a05cf8fcfabc3714481407e04d5ee752c6dced927000764de369b7172
4
+ data.tar.gz: e72b208fadad3073246fd8feb0819af6efefa87738930d7cab21e65913da423f
5
5
  SHA512:
6
- metadata.gz: e174c55c53544fd420808519c705f546fe166a44965c279a09ac25ccbd52c47e09329c06031aa3f1e143987400678322f870fa5736717f68c7397f7579097b86
7
- data.tar.gz: d1f64700776c503711dc40a6ee4530963058cac534bfd49473a5567c01b2bda117b375f223eeedb434196ee3fb2275ca35db7ad6c165f7ee3da14138383f6552
6
+ metadata.gz: 0cff5090a0feb65b5d2f243262f8679b47478a3407e8a957690f7d182ff45ecbe71292be1fd7d27af0558cb8a79182dd938c161697f1002095f5d3dbd99263ae
7
+ data.tar.gz: 290f830403a64539fc3f0bf7c9119ae3c0c9aca4627d4aa2bb363179064f2330d61de204a9feaf7071fca1b3e7f980fc32dfb01ed3423cfb4b70de271c56e2d5
data/Makefile CHANGED
@@ -16,4 +16,7 @@ release:
16
16
  build:
17
17
  bundle exec rake build
18
18
 
19
+ push:
20
+ git push origin master
21
+
19
22
  .PHONY: test
data/README.md CHANGED
@@ -41,7 +41,7 @@ or with namespace model
41
41
 
42
42
  $ rails g application_form:form admin_post --model=blog/post
43
43
 
44
- ### Example
44
+ ### Basic usage
45
45
 
46
46
  ```ruby
47
47
  # app/forms/user_sign_up_form.rb
@@ -66,13 +66,63 @@ class UserSignUpForm < User
66
66
  end
67
67
  ```
68
68
 
69
- In some cases it is necessary to use ActiveRecord object directly without form. For such cases conveniently to use method `become()` (built-in ActiveRecord):
69
+ ```
70
+ form = UserSignUpForm.new(user_params)
71
+ form.valid?
72
+ ```
73
+
74
+ ### Usage with `becomes`
75
+
76
+ In some cases it is necessary to use ActiveRecord object directly without form. For such cases conveniently to use method `becomes()` (built-in ActiveRecord):
70
77
 
71
78
  ```ruby
72
79
  user = User.find(params[:id])
73
80
  form = user.becomes(UserSignUpForm)
74
81
  ```
75
82
 
83
+ ### Checks
84
+
85
+ Checks are build on top of Rails validations. They are semantically separated from validations, because we treat them as business logic checks, not as data validation.
86
+
87
+ ```ruby
88
+ class ReservationCreateForm < Reservation
89
+ include ApplicationForm
90
+
91
+ permit :user_id, :vehicle_id, :start_at, :end_at, :pickup_location_id, :return_location_id
92
+
93
+ check :max_number_of_reservations_reached, ->(form) { !form.user&.reservations_limit_reached? }
94
+ check :car_is_on_maintenance, ->(form) { form.vehicle&.reservable? }
95
+ end
96
+
97
+ # In controller:
98
+ form = ReservationCreateForm.new(prepared_params)
99
+
100
+ if form.checks_passed?
101
+ # ...
102
+ else
103
+ render_error!(form.first_failed_check) # form.first_failed_check returns "reservation.error.max_number_of_reservations_reached"
104
+ end
105
+ ```
106
+
107
+ You can also assign check to a specific field:
108
+
109
+ ```ruby
110
+ check :end_at_must_be_greater_then_start_at, ->(form) { form.end_at > form.start_at }, :end_at
111
+ ```
112
+
113
+ In this case it will work as a regular validation.
114
+
115
+ ### `assign_attrs`
116
+
117
+ It works as regular `assign_attributes` but it also returns the object, so that you can chain it:
118
+
119
+ ```ruby
120
+ form = current_user.becomes(UserApplyReferralProgramForm)
121
+ .assign_attrs(registration_referral_code: referral_code)
122
+ ```
123
+
124
+ It is a usual pattern when you use for in `#update` action.
125
+
76
126
  ## Development
77
127
 
78
128
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -24,9 +24,8 @@ module ApplicationForm
24
24
  module ClassMethods
25
25
  delegate :sti_name, to: :superclass
26
26
  delegate :human_attribute_name, to: :superclass
27
- # NOTE: too many side effects if it is enabled
28
- # examples: form names, translations
29
- # delegate :name, to: :superclass
27
+ # NOTE: Controvertial thing. More details: https://github.com/Hexlet/active_form_model/issues/10
28
+ delegate :name, to: :superclass
30
29
 
31
30
  def permit(*args)
32
31
  @_permitted_args = args
@@ -35,6 +34,16 @@ module ApplicationForm
35
34
  def _permitted_args
36
35
  @_permitted_args || (superclass.respond_to?(:_permitted_args) && superclass._permitted_args) || []
37
36
  end
37
+
38
+ def check(key, block, field = :base)
39
+ validate do |form|
40
+ if !block.call(form)
41
+ entity_name = self.class.superclass.to_s.tableize.split('/').last.singularize
42
+ full_key = "#{entity_name}.errors.#{key}"
43
+ form.add_error_key(field, full_key)
44
+ end
45
+ end
46
+ end
38
47
  end
39
48
 
40
49
  def update(attrs = {})
@@ -55,4 +64,22 @@ module ApplicationForm
55
64
  def permit_attrs(attrs)
56
65
  attrs.respond_to?(:permit) ? attrs.send(:permit, self.class._permitted_args) : attrs
57
66
  end
67
+
68
+ def first_error_message
69
+ errors&.full_messages&.first
70
+ end
71
+
72
+ def checks_passed?
73
+ valid?
74
+ end
75
+
76
+ def first_failed_check
77
+ errors.details[:base].first[:error].to_s
78
+ end
79
+
80
+ def assign_attrs(attrsibutes)
81
+ attrs = ActiveSupport::HashWithIndifferentAccess.new(attributes)
82
+ assign_attributes(attrs)
83
+ self
84
+ end
58
85
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ApplicationForm
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.3'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: application_form
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kirill Mokevnin