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 +4 -4
- data/Makefile +3 -0
- data/README.md +52 -2
- data/lib/application_form.rb +30 -3
- data/lib/application_form/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b81f5d6a05cf8fcfabc3714481407e04d5ee752c6dced927000764de369b7172
|
4
|
+
data.tar.gz: e72b208fadad3073246fd8feb0819af6efefa87738930d7cab21e65913da423f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cff5090a0feb65b5d2f243262f8679b47478a3407e8a957690f7d182ff45ecbe71292be1fd7d27af0558cb8a79182dd938c161697f1002095f5d3dbd99263ae
|
7
|
+
data.tar.gz: 290f830403a64539fc3f0bf7c9119ae3c0c9aca4627d4aa2bb363179064f2330d61de204a9feaf7071fca1b3e7f980fc32dfb01ed3423cfb4b70de271c56e2d5
|
data/Makefile
CHANGED
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
|
-
###
|
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
|
-
|
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.
|
data/lib/application_form.rb
CHANGED
@@ -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:
|
28
|
-
|
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
|