hyperactiveform 0.1.0 → 0.3.0
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 +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +35 -1
- data/docs/HyperActiveForm/Base.html +884 -0
- data/docs/HyperActiveForm/CancelFormSubmit.html +124 -0
- data/docs/HyperActiveForm/FormDidNotSubmitError.html +124 -0
- data/docs/HyperActiveForm/Generators/InstallGenerator.html +199 -0
- data/docs/HyperActiveForm/Generators.html +115 -0
- data/docs/HyperActiveForm.html +135 -0
- data/docs/_index.html +182 -0
- data/docs/class_list.html +54 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +503 -0
- data/docs/file.README.html +271 -0
- data/docs/file_list.html +59 -0
- data/docs/frames.html +22 -0
- data/docs/index.html +271 -0
- data/docs/js/app.js +344 -0
- data/docs/js/full_list.js +242 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +126 -0
- data/docs/top-level-namespace.html +110 -0
- data/examples/basic.md +85 -0
- data/lib/generators/form/form_generator.rb +9 -0
- data/lib/generators/form/templates/form.rb +2 -0
- data/lib/{hyper_active_form/generators.rb → generators/hyper_active_form/install/install_generator.rb} +0 -2
- data/lib/generators/rspec/form_generator.rb +11 -0
- data/lib/generators/rspec/templates/form_spec.rb +5 -0
- data/lib/generators/test_unit/form_generator.rb +11 -0
- data/lib/generators/test_unit/templates/form_test.rb +7 -0
- data/lib/hyper_active_form/base.rb +43 -5
- data/lib/hyper_active_form/version.rb +1 -1
- data/lib/hyper_active_form.rb +0 -1
- metadata +44 -3
@@ -0,0 +1,110 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— Documentation by YARD 0.9.37
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
16
|
+
|
17
|
+
<script type="text/javascript">
|
18
|
+
pathId = "";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="class_list.html?1"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
|
41
|
+
|
42
|
+
<span class="title">Top Level Namespace</span>
|
43
|
+
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div id="search">
|
47
|
+
|
48
|
+
<a class="full_list_link" id="class_list_link"
|
49
|
+
href="class_list.html">
|
50
|
+
|
51
|
+
<svg width="24" height="24">
|
52
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
54
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
55
|
+
</svg>
|
56
|
+
</a>
|
57
|
+
|
58
|
+
</div>
|
59
|
+
<div class="clear"></div>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div id="content"><h1>Top Level Namespace
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
</h1>
|
67
|
+
<div class="box_info">
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
</div>
|
80
|
+
|
81
|
+
<h2>Defined Under Namespace</h2>
|
82
|
+
<p class="children">
|
83
|
+
|
84
|
+
|
85
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="HyperActiveForm.html" title="HyperActiveForm (module)">HyperActiveForm</a></span>
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
</p>
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
</div>
|
101
|
+
|
102
|
+
<div id="footer">
|
103
|
+
Generated on Sat Dec 14 13:22:03 2024 by
|
104
|
+
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
|
+
0.9.37 (ruby-3.3.1).
|
106
|
+
</div>
|
107
|
+
|
108
|
+
</div>
|
109
|
+
</body>
|
110
|
+
</html>
|
data/examples/basic.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Basic form example
|
2
|
+
|
3
|
+
## Form
|
4
|
+
```ruby
|
5
|
+
class ContactForm < ApplicationForm
|
6
|
+
proxy_for Contact, :@contact
|
7
|
+
|
8
|
+
attribute :first_name
|
9
|
+
attribute :last_name
|
10
|
+
attribute :birth_date, :date
|
11
|
+
|
12
|
+
validates :first_name, presence: true
|
13
|
+
validates :last_name, presence: true
|
14
|
+
validates :birth_date, presence: true
|
15
|
+
|
16
|
+
|
17
|
+
def setup(contact)
|
18
|
+
@contact = contact
|
19
|
+
self.first_name = @contact.first_name
|
20
|
+
self.last_name = @contact.last_name
|
21
|
+
self.birth_date = @contact.birth_date
|
22
|
+
## You could also do :
|
23
|
+
# self.attributes = @contact.attributes.slice(:first_name, :last_name, birth_date)
|
24
|
+
end
|
25
|
+
|
26
|
+
def perform
|
27
|
+
@contact.update!(
|
28
|
+
first_name:,
|
29
|
+
last_name:,
|
30
|
+
birth_date:
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
## Controller
|
37
|
+
```ruby
|
38
|
+
class ContactsController
|
39
|
+
def new
|
40
|
+
@form = ContactForm.new(Contact.new)
|
41
|
+
end
|
42
|
+
|
43
|
+
def create
|
44
|
+
@form = ContactForm.new(Contact.new)
|
45
|
+
|
46
|
+
if @form.submit(params[:contact])
|
47
|
+
redirect_to root_path, notice: "Contact created"
|
48
|
+
else
|
49
|
+
render :new, status: :unprocessable_entity
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def edit
|
54
|
+
@contact = Contact.find(params[:id])
|
55
|
+
@form = ContactForm.new(@contact)
|
56
|
+
end
|
57
|
+
|
58
|
+
def update
|
59
|
+
@contact = Contact.find(params[:id])
|
60
|
+
@form = ContactForm.new(@contact)
|
61
|
+
|
62
|
+
if @form.submit(params[:contact])
|
63
|
+
redirect_to root_path, notice: "Contact updated"
|
64
|
+
else
|
65
|
+
render :edit, status: :unprocessable_entity
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
## Views
|
72
|
+
### new.html.erb and edit.html.erb
|
73
|
+
```erb
|
74
|
+
<%= render "form", form: @form %>
|
75
|
+
```
|
76
|
+
|
77
|
+
### _form.html.erb
|
78
|
+
```erb
|
79
|
+
<%= form_with(model: form) do |f| %>
|
80
|
+
<%= f.text_field :first_name, placeholder: "First name" %>
|
81
|
+
<%= f.text_field :last_name, placeholder: "Last name" %>
|
82
|
+
<%= f.date_field :birth_date %>
|
83
|
+
<%= f.submit "Save" %>
|
84
|
+
<% end %>
|
85
|
+
```
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Rspec
|
2
|
+
module Generators
|
3
|
+
class FormGenerator < ::Rails::Generators::NamedBase
|
4
|
+
source_root File.expand_path("templates", __dir__)
|
5
|
+
|
6
|
+
def create_form_spec
|
7
|
+
template "form_spec.rb", File.join("spec/forms", class_path, "#{file_name}_form_spec.rb")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module TestUnit
|
2
|
+
module Generators
|
3
|
+
class FormGenerator < ::Rails::Generators::NamedBase
|
4
|
+
source_root File.expand_path("templates", __dir__)
|
5
|
+
|
6
|
+
def create_form_test
|
7
|
+
template "form_test.rb", File.join("test/forms", class_path, "#{file_name}_form_test.rb")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -4,11 +4,26 @@ require "active_model"
|
|
4
4
|
require "action_controller"
|
5
5
|
|
6
6
|
module HyperActiveForm
|
7
|
+
##
|
8
|
+
# Base class for HyperActiveForm objects
|
9
|
+
#
|
10
|
+
# HyperActiveForm objects are simple ActiveModel objects that encapsulate
|
11
|
+
# form logic and validations. They are designed to be subclassed and
|
12
|
+
# customized to fit the needs of your application.
|
13
|
+
#
|
7
14
|
class Base
|
8
15
|
include ActiveModel::Model
|
9
16
|
include ActiveModel::Attributes
|
10
17
|
include ActiveModel::Validations
|
18
|
+
extend ActiveModel::Callbacks
|
11
19
|
|
20
|
+
define_model_callbacks :assign_form_attributes, :submit
|
21
|
+
|
22
|
+
# Defines to which object the form should delegate the active model methods
|
23
|
+
# This is useful so `form_for`/`form_with` can automatically deduce the url and method to use
|
24
|
+
#
|
25
|
+
# @param klass [Class] the class of the object to proxy
|
26
|
+
# @param object [Object] where to delegate the object to, for example: `:@user`
|
12
27
|
def self.proxy_for(klass, object)
|
13
28
|
delegate :new_record?, :persisted?, :id, to: object
|
14
29
|
singleton_class.delegate :model_name, to: klass
|
@@ -25,24 +40,47 @@ module HyperActiveForm
|
|
25
40
|
raise NotImplementedError
|
26
41
|
end
|
27
42
|
|
43
|
+
# Assigns the attributes of the form from the params
|
44
|
+
# This method is called by the `submit` method, but can also be called
|
45
|
+
# directly if you need to assign the attributes without submitting the form
|
46
|
+
# for example if you want to refresh the form with new data
|
47
|
+
#
|
48
|
+
# @param params [Hash] the params to assign the attributes from
|
28
49
|
def assign_form_attributes(params)
|
29
|
-
|
30
|
-
|
31
|
-
|
50
|
+
run_callbacks :assign_form_attributes do
|
51
|
+
params = ActionController::Parameters.new(params) unless params.is_a?(ActionController::Parameters)
|
52
|
+
attribute_names.each do |attribute|
|
53
|
+
default_value = self.class._default_attributes[attribute]&.value_before_type_cast
|
54
|
+
public_send(:"#{attribute}=", params&.dig(attribute) || default_value)
|
55
|
+
end
|
32
56
|
end
|
33
57
|
end
|
34
58
|
|
59
|
+
# Submits the form, assigning the attributes from the params,
|
60
|
+
# running validations and calling the `perform` method if the form is valid
|
61
|
+
#
|
62
|
+
# @param params [Hash] the params to assign the attributes from
|
63
|
+
# @return [Boolean] true if the form is valid and the `perform` method returned something truthy
|
35
64
|
def submit(params)
|
36
|
-
|
37
|
-
|
65
|
+
run_callbacks :submit do
|
66
|
+
assign_form_attributes(params)
|
67
|
+
!!(valid? && perform)
|
68
|
+
end
|
38
69
|
rescue HyperActiveForm::CancelFormSubmit
|
39
70
|
false
|
40
71
|
end
|
41
72
|
|
73
|
+
# Same as `submit` but raises a `FormDidNotSubmitError` if the form is not valid
|
74
|
+
#
|
75
|
+
# @param params [Hash] the params to assign the attributes from
|
76
|
+
# @return [Boolean] true if the form is valid and the `perform` method returned something truthy
|
42
77
|
def submit!(params)
|
43
78
|
submit(params) || raise(HyperActiveForm::FormDidNotSubmitError)
|
44
79
|
end
|
45
80
|
|
81
|
+
# Adds the errors from a model to the form
|
82
|
+
#
|
83
|
+
# @param model [ActiveModel::Model] the model to add the errors from
|
46
84
|
def add_errors_from(model)
|
47
85
|
model.errors.each do |error|
|
48
86
|
Array.wrap(error.message).each { |e| errors.add(error.attribute, e) }
|
data/lib/hyper_active_form.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyperactiveform
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adrien Siami
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.13'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description: Encapsulate form logic and validations in a simple object
|
42
56
|
email:
|
43
57
|
- adrien@siami.fr
|
@@ -50,12 +64,39 @@ files:
|
|
50
64
|
- LICENSE.txt
|
51
65
|
- README.md
|
52
66
|
- Rakefile
|
67
|
+
- docs/HyperActiveForm.html
|
68
|
+
- docs/HyperActiveForm/Base.html
|
69
|
+
- docs/HyperActiveForm/CancelFormSubmit.html
|
70
|
+
- docs/HyperActiveForm/FormDidNotSubmitError.html
|
71
|
+
- docs/HyperActiveForm/Generators.html
|
72
|
+
- docs/HyperActiveForm/Generators/InstallGenerator.html
|
73
|
+
- docs/_index.html
|
74
|
+
- docs/class_list.html
|
75
|
+
- docs/css/common.css
|
76
|
+
- docs/css/full_list.css
|
77
|
+
- docs/css/style.css
|
78
|
+
- docs/file.README.html
|
79
|
+
- docs/file_list.html
|
80
|
+
- docs/frames.html
|
81
|
+
- docs/index.html
|
82
|
+
- docs/js/app.js
|
83
|
+
- docs/js/full_list.js
|
84
|
+
- docs/js/jquery.js
|
85
|
+
- docs/method_list.html
|
86
|
+
- docs/top-level-namespace.html
|
87
|
+
- examples/basic.md
|
53
88
|
- gemfiles/Gemfile.rails-7.1.x
|
54
89
|
- gemfiles/Gemfile.rails-7.2.x
|
55
90
|
- gemfiles/Gemfile.rails-8.x
|
91
|
+
- lib/generators/form/form_generator.rb
|
92
|
+
- lib/generators/form/templates/form.rb
|
93
|
+
- lib/generators/hyper_active_form/install/install_generator.rb
|
94
|
+
- lib/generators/rspec/form_generator.rb
|
95
|
+
- lib/generators/rspec/templates/form_spec.rb
|
96
|
+
- lib/generators/test_unit/form_generator.rb
|
97
|
+
- lib/generators/test_unit/templates/form_test.rb
|
56
98
|
- lib/hyper_active_form.rb
|
57
99
|
- lib/hyper_active_form/base.rb
|
58
|
-
- lib/hyper_active_form/generators.rb
|
59
100
|
- lib/hyper_active_form/version.rb
|
60
101
|
- lib/hyperactiveform.rb
|
61
102
|
- sig/hyperactiveform.rbs
|