abyme 0.2.4 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +1 -1
- data/.gitignore +1 -0
- data/CHANGELOG.md +93 -0
- data/Gemfile.lock +30 -28
- data/README.md +56 -39
- data/javascript/abyme_controller.js +7 -1
- data/lib/abyme.rb +1 -0
- data/lib/abyme/action_view_extensions/builder.rb +15 -0
- data/lib/abyme/engine.rb +0 -1
- data/lib/abyme/model.rb +1 -1
- data/lib/abyme/version.rb +2 -2
- data/lib/abyme/view_helpers.rb +9 -9
- data/package.json +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 627dd83f44a40bcdf8ebd3355761ff9e1201c9d9c11e526e00acee11c685e479
|
4
|
+
data.tar.gz: 476215a4ae3e062e79104f0351da75a090c74c25cbde16cdd26016e17cea08cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd5fa9ecb5bae8fdab1272017769649c4ca5945789f47a5c792c6240a2aa45366a335c231128e04feb57448e9275433a303df023ced40c5f26eaafefd03baf78
|
7
|
+
data.tar.gz: 8d5728bd54f6e9292f36f9336e7b8157b1354e17e6348ce1fa07ad611c31c8d5f4d2550f494e4e4d00dfd136c5daf621a1cf6d1ba999c5f2625fc8e1110841b2
|
data/.github/workflows/build.yml
CHANGED
@@ -23,7 +23,7 @@ jobs:
|
|
23
23
|
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
24
24
|
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
25
25
|
# uses: ruby/setup-ruby@v1
|
26
|
-
uses: ruby/setup-ruby@
|
26
|
+
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
27
27
|
with:
|
28
28
|
ruby-version: 2.6
|
29
29
|
- name: Install sqlite headers
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [Unreleased](https://github.com/bear-in-mind/abyme/tree/HEAD)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/v0.2.4...HEAD)
|
6
|
+
|
7
|
+
**Merged pull requests:**
|
8
|
+
|
9
|
+
- Bump nokogiri from 1.10.10 to 1.11.1 [\#22](https://github.com/bear-in-mind/abyme/pull/22) ([dependabot[bot]](https://github.com/apps/dependabot))
|
10
|
+
- Solved JS compile bug [\#19](https://github.com/bear-in-mind/abyme/pull/19) ([bear-in-mind](https://github.com/bear-in-mind))
|
11
|
+
|
12
|
+
## [v0.2.4](https://github.com/bear-in-mind/abyme/tree/v0.2.4) (2020-10-18)
|
13
|
+
|
14
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/v0.2.3...v0.2.4)
|
15
|
+
|
16
|
+
**Merged pull requests:**
|
17
|
+
|
18
|
+
- Abymebuilder doc [\#18](https://github.com/bear-in-mind/abyme/pull/18) ([ghbozz](https://github.com/ghbozz))
|
19
|
+
- Last fix [\#17](https://github.com/bear-in-mind/abyme/pull/17) ([bear-in-mind](https://github.com/bear-in-mind))
|
20
|
+
- Drop demo [\#16](https://github.com/bear-in-mind/abyme/pull/16) ([bear-in-mind](https://github.com/bear-in-mind))
|
21
|
+
- Coveralls [\#15](https://github.com/bear-in-mind/abyme/pull/15) ([bear-in-mind](https://github.com/bear-in-mind))
|
22
|
+
- changing action name [\#14](https://github.com/bear-in-mind/abyme/pull/14) ([bear-in-mind](https://github.com/bear-in-mind))
|
23
|
+
- fixing button default text when auto mode [\#13](https://github.com/bear-in-mind/abyme/pull/13) ([ghbozz](https://github.com/ghbozz))
|
24
|
+
- travis and rake update [\#12](https://github.com/bear-in-mind/abyme/pull/12) ([bear-in-mind](https://github.com/bear-in-mind))
|
25
|
+
- Autonomous Spec [\#11](https://github.com/bear-in-mind/abyme/pull/11) ([bear-in-mind](https://github.com/bear-in-mind))
|
26
|
+
|
27
|
+
## [v0.2.3](https://github.com/bear-in-mind/abyme/tree/v0.2.3) (2020-10-15)
|
28
|
+
|
29
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/v0.2.2...v0.2.3)
|
30
|
+
|
31
|
+
## [v0.2.2](https://github.com/bear-in-mind/abyme/tree/v0.2.2) (2020-10-15)
|
32
|
+
|
33
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/v0.2.1...v0.2.2)
|
34
|
+
|
35
|
+
**Merged pull requests:**
|
36
|
+
|
37
|
+
- Dummy app setup \(incomplete\) [\#10](https://github.com/bear-in-mind/abyme/pull/10) ([bear-in-mind](https://github.com/bear-in-mind))
|
38
|
+
|
39
|
+
## [v0.2.1](https://github.com/bear-in-mind/abyme/tree/v0.2.1) (2020-10-15)
|
40
|
+
|
41
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/0.2.0...v0.2.1)
|
42
|
+
|
43
|
+
**Merged pull requests:**
|
44
|
+
|
45
|
+
- fix partial path [\#9](https://github.com/bear-in-mind/abyme/pull/9) ([ghbozz](https://github.com/ghbozz))
|
46
|
+
|
47
|
+
## [0.2.0](https://github.com/bear-in-mind/abyme/tree/0.2.0) (2020-10-14)
|
48
|
+
|
49
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/v0.2.0...0.2.0)
|
50
|
+
|
51
|
+
**Merged pull requests:**
|
52
|
+
|
53
|
+
- End of doc [\#8](https://github.com/bear-in-mind/abyme/pull/8) ([bear-in-mind](https://github.com/bear-in-mind))
|
54
|
+
|
55
|
+
## [v0.2.0](https://github.com/bear-in-mind/abyme/tree/v0.2.0) (2020-10-14)
|
56
|
+
|
57
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/0.1.3...v0.2.0)
|
58
|
+
|
59
|
+
**Merged pull requests:**
|
60
|
+
|
61
|
+
- limit & min count options [\#7](https://github.com/bear-in-mind/abyme/pull/7) ([ghbozz](https://github.com/ghbozz))
|
62
|
+
- Documentation end [\#6](https://github.com/bear-in-mind/abyme/pull/6) ([bear-in-mind](https://github.com/bear-in-mind))
|
63
|
+
- add limit feature [\#5](https://github.com/bear-in-mind/abyme/pull/5) ([ghbozz](https://github.com/ghbozz))
|
64
|
+
|
65
|
+
## [0.1.3](https://github.com/bear-in-mind/abyme/tree/0.1.3) (2020-10-13)
|
66
|
+
|
67
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/v0.1.2...0.1.3)
|
68
|
+
|
69
|
+
## [v0.1.2](https://github.com/bear-in-mind/abyme/tree/v0.1.2) (2020-10-13)
|
70
|
+
|
71
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/0.1.1...v0.1.2)
|
72
|
+
|
73
|
+
**Merged pull requests:**
|
74
|
+
|
75
|
+
- basic lifecycle events [\#4](https://github.com/bear-in-mind/abyme/pull/4) ([ghbozz](https://github.com/ghbozz))
|
76
|
+
|
77
|
+
## [0.1.1](https://github.com/bear-in-mind/abyme/tree/0.1.1) (2020-10-12)
|
78
|
+
|
79
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/v0.1.1...0.1.1)
|
80
|
+
|
81
|
+
## [v0.1.1](https://github.com/bear-in-mind/abyme/tree/v0.1.1) (2020-10-12)
|
82
|
+
|
83
|
+
[Full Changelog](https://github.com/bear-in-mind/abyme/compare/9b99709cd8f84e9401adb8ba6f59f0074e2f416b...v0.1.1)
|
84
|
+
|
85
|
+
**Merged pull requests:**
|
86
|
+
|
87
|
+
- Gem Content [\#3](https://github.com/bear-in-mind/abyme/pull/3) ([bear-in-mind](https://github.com/bear-in-mind))
|
88
|
+
- install generator for stimulus init setup [\#2](https://github.com/bear-in-mind/abyme/pull/2) ([ghbozz](https://github.com/ghbozz))
|
89
|
+
- Update rake requirement from ~\> 10.0 to ~\> 13.0 [\#1](https://github.com/bear-in-mind/abyme/pull/1) ([dependabot[bot]](https://github.com/apps/dependabot))
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
abyme (0.
|
4
|
+
abyme (0.4.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -73,7 +73,7 @@ GEM
|
|
73
73
|
regexp_parser (~> 1.5)
|
74
74
|
xpath (~> 3.2)
|
75
75
|
childprocess (3.0.0)
|
76
|
-
concurrent-ruby (1.1.
|
76
|
+
concurrent-ruby (1.1.8)
|
77
77
|
crass (1.0.6)
|
78
78
|
database_cleaner (1.8.5)
|
79
79
|
database_cleaner-active_record (1.8.0)
|
@@ -81,12 +81,12 @@ GEM
|
|
81
81
|
database_cleaner (~> 1.8.0)
|
82
82
|
diff-lcs (1.4.4)
|
83
83
|
docile (1.3.2)
|
84
|
-
erubi (1.
|
84
|
+
erubi (1.10.0)
|
85
85
|
globalid (0.4.2)
|
86
86
|
activesupport (>= 4.2.0)
|
87
|
-
i18n (1.8.
|
87
|
+
i18n (1.8.8)
|
88
88
|
concurrent-ruby (~> 1.0)
|
89
|
-
loofah (2.
|
89
|
+
loofah (2.9.0)
|
90
90
|
crass (~> 1.0.2)
|
91
91
|
nokogiri (>= 1.5.9)
|
92
92
|
mail (2.7.1)
|
@@ -96,14 +96,16 @@ GEM
|
|
96
96
|
method_source (1.0.0)
|
97
97
|
mimemagic (0.3.5)
|
98
98
|
mini_mime (1.0.2)
|
99
|
-
mini_portile2 (2.
|
100
|
-
minitest (5.14.
|
99
|
+
mini_portile2 (2.5.0)
|
100
|
+
minitest (5.14.3)
|
101
101
|
nio4r (2.5.4)
|
102
|
-
nokogiri (1.
|
103
|
-
mini_portile2 (~> 2.
|
102
|
+
nokogiri (1.11.1)
|
103
|
+
mini_portile2 (~> 2.5.0)
|
104
|
+
racc (~> 1.4)
|
104
105
|
public_suffix (4.0.6)
|
105
|
-
puma (
|
106
|
+
puma (5.0.4)
|
106
107
|
nio4r (~> 2.0)
|
108
|
+
racc (1.5.2)
|
107
109
|
rack (2.2.3)
|
108
110
|
rack-test (1.1.0)
|
109
111
|
rack (>= 1.0, < 3)
|
@@ -137,33 +139,33 @@ GEM
|
|
137
139
|
method_source
|
138
140
|
rake (>= 0.8.7)
|
139
141
|
thor (>= 0.20.3, < 2.0)
|
140
|
-
rake (13.0.
|
142
|
+
rake (13.0.3)
|
141
143
|
regexp_parser (1.8.2)
|
142
|
-
rspec-core (3.
|
143
|
-
rspec-support (~> 3.
|
144
|
-
rspec-expectations (3.
|
144
|
+
rspec-core (3.10.1)
|
145
|
+
rspec-support (~> 3.10.0)
|
146
|
+
rspec-expectations (3.10.1)
|
145
147
|
diff-lcs (>= 1.2.0, < 2.0)
|
146
|
-
rspec-support (~> 3.
|
147
|
-
rspec-mocks (3.
|
148
|
+
rspec-support (~> 3.10.0)
|
149
|
+
rspec-mocks (3.10.2)
|
148
150
|
diff-lcs (>= 1.2.0, < 2.0)
|
149
|
-
rspec-support (~> 3.
|
150
|
-
rspec-rails (4.0.
|
151
|
+
rspec-support (~> 3.10.0)
|
152
|
+
rspec-rails (4.0.2)
|
151
153
|
actionpack (>= 4.2)
|
152
154
|
activesupport (>= 4.2)
|
153
155
|
railties (>= 4.2)
|
154
|
-
rspec-core (~> 3.
|
155
|
-
rspec-expectations (~> 3.
|
156
|
-
rspec-mocks (~> 3.
|
157
|
-
rspec-support (~> 3.
|
158
|
-
rspec-support (3.
|
156
|
+
rspec-core (~> 3.10)
|
157
|
+
rspec-expectations (~> 3.10)
|
158
|
+
rspec-mocks (~> 3.10)
|
159
|
+
rspec-support (~> 3.10)
|
160
|
+
rspec-support (3.10.2)
|
159
161
|
rubyzip (2.3.0)
|
160
162
|
selenium-webdriver (3.142.7)
|
161
163
|
childprocess (>= 0.5, < 4.0)
|
162
164
|
rubyzip (>= 1.2.2)
|
163
|
-
simplecov (0.19.
|
165
|
+
simplecov (0.19.1)
|
164
166
|
docile (~> 1.1)
|
165
167
|
simplecov-html (~> 0.11)
|
166
|
-
simplecov-html (0.12.
|
168
|
+
simplecov-html (0.12.3)
|
167
169
|
simplecov-lcov (0.8.0)
|
168
170
|
sprockets (4.0.2)
|
169
171
|
concurrent-ruby (~> 1.0)
|
@@ -173,9 +175,9 @@ GEM
|
|
173
175
|
activesupport (>= 4.0)
|
174
176
|
sprockets (>= 3.0.0)
|
175
177
|
sqlite3 (1.4.2)
|
176
|
-
thor (1.0
|
178
|
+
thor (1.1.0)
|
177
179
|
thread_safe (0.3.6)
|
178
|
-
tzinfo (1.2.
|
180
|
+
tzinfo (1.2.9)
|
179
181
|
thread_safe (~> 0.1)
|
180
182
|
webdrivers (4.4.1)
|
181
183
|
nokogiri (~> 1.6)
|
@@ -186,7 +188,7 @@ GEM
|
|
186
188
|
websocket-extensions (0.1.5)
|
187
189
|
xpath (3.2.0)
|
188
190
|
nokogiri (~> 1.8)
|
189
|
-
zeitwerk (2.4.
|
191
|
+
zeitwerk (2.4.2)
|
190
192
|
|
191
193
|
PLATFORMS
|
192
194
|
ruby
|
data/README.md
CHANGED
@@ -1,12 +1,29 @@
|
|
1
1
|
# Abyme 🕳
|
2
2
|
|
3
|
-
abyme is a modern take on handling dynamic nested forms in Rails 6+ using StimulusJS.
|
4
|
-
|
5
3
|
[![Gem Version](https://badge.fury.io/rb/abyme.svg)](https://badge.fury.io/rb/abyme)
|
6
4
|
![build](https://github.com/bear-in-mind/abyme/workflows/build/badge.svg)
|
7
5
|
[![Maintainability](https://api.codeclimate.com/v1/badges/f591a9e00f7cf5188ad5/maintainability)](https://codeclimate.com/github/bear-in-mind/abyme/maintainability)
|
8
6
|
[![Coverage Status](https://coveralls.io/repos/github/bear-in-mind/abyme/badge.svg)](https://coveralls.io/github/bear-in-mind/abyme?branch=master)
|
9
7
|
|
8
|
+
abyme makes it easy to handle nested attributes in Rails, using [stimulus](https://stimulusjs.org/handbook/introduction) under the hood. Here's an example :
|
9
|
+
```ruby
|
10
|
+
# views/projects/_form.html.erb
|
11
|
+
<%= simple_form_for @project do |f| %>
|
12
|
+
<%= f.input :title %>
|
13
|
+
<%= f.input :description %>
|
14
|
+
<%= f.submit 'Save' %>
|
15
|
+
|
16
|
+
<%= f.abyme_for(:tasks) %>
|
17
|
+
<% end %>
|
18
|
+
```
|
19
|
+
Supposing you have a partial located in `views/abyme/_task_fields` containing your fields for `tasks`, the `abyme_for` command will generate and display 3 elements in this order :
|
20
|
+
- A div containing all task fields for `@project.tasks` (either persisted or already built instances of `tasks`)
|
21
|
+
- A div which will contain all additional tasks about to be created (added through the `Add task` button below)
|
22
|
+
- A button to generate fields for new instances of tasks
|
23
|
+
|
24
|
+
Have a look below to learn more about the different options and needed configuration.
|
25
|
+
|
26
|
+
|
10
27
|
## Disclaimer
|
11
28
|
This project is still a work in progress and subject to change. We would advise not to use it in production code just yet.
|
12
29
|
|
@@ -89,7 +106,7 @@ class Project < ApplicationRecord
|
|
89
106
|
include Abyme::Model
|
90
107
|
has_many :tasks, inverse_of: :project
|
91
108
|
# ...
|
92
|
-
|
109
|
+
abymize :tasks
|
93
110
|
end
|
94
111
|
|
95
112
|
# models/task.rb
|
@@ -97,7 +114,7 @@ class Task < ApplicationRecord
|
|
97
114
|
include Abyme::Model
|
98
115
|
has_many :comments, inverse_of: :task
|
99
116
|
# ...
|
100
|
-
|
117
|
+
abymize :comments
|
101
118
|
end
|
102
119
|
```
|
103
120
|
Note the use of the `inverse_of` option. It is needed for Rails to effectively associate children to their yet unsaved parent. Have a peek to the bottom of [this page](https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for) for more info.
|
@@ -142,15 +159,15 @@ abyme provides helper methods for all these. Here's how our form for `Project` l
|
|
142
159
|
<%= f.input :description %>
|
143
160
|
<%= f.submit 'Save' %>
|
144
161
|
|
145
|
-
<%=
|
162
|
+
<%= f.abyme_for(:tasks) do |abyme| %>
|
146
163
|
<%= abyme.records %>
|
147
164
|
<%= abyme.new_records %>
|
148
|
-
<%=
|
165
|
+
<%= add_associated_record %>
|
149
166
|
<% end %>
|
150
167
|
<% end %>
|
151
168
|
```
|
152
169
|
|
153
|
-
`abyme.records` will contain the persisted associations fields, while `abyme.new_records` will contain fields for the new associations. `
|
170
|
+
`abyme.records` will contain the persisted associations fields, while `abyme.new_records` will contain fields for the new associations. `add_associated_record` will by default generate a button with a text of type "Add `resource_name`". To work properly, this method **has** to be called **inside the block** passed to the `abyme_for` method.
|
154
171
|
|
155
172
|
Now where's the code for these fields ? abyme will assume a **partial** to be present in the directory `/views/abyme` with a *name respecting this naming convention* (just like with [cocoon](https://github.com/nathanvda/cocoon#basic-usage)): `_singular_association_name_fields.html.erb`.
|
156
173
|
|
@@ -161,12 +178,12 @@ This partial might look like this:
|
|
161
178
|
<%= f.input :description %>
|
162
179
|
<%= f.hidden_field :_destroy %>
|
163
180
|
|
164
|
-
<%=
|
181
|
+
<%= remove_associated_record(tag: :div) do %>
|
165
182
|
<i class="fas fa-trash"></i>
|
166
183
|
<% end %>
|
167
184
|
```
|
168
185
|
|
169
|
-
Note the presence of the `
|
186
|
+
Note the presence of the `remove_associated_record` button. Here, we pass it an option to make it a `<div>`, as well as a block to customize its content. Don't forget the `_destroy` attribute, needed to mark items for destruction.
|
170
187
|
|
171
188
|
### What about the controller ?
|
172
189
|
|
@@ -175,11 +192,11 @@ What about it ? Well, not much. That's the actual magical thing about `nested_at
|
|
175
192
|
|
176
193
|
### Auto mode
|
177
194
|
|
178
|
-
Let's now take care of our comments fields. We'll add these using our neat *automatic mode*: just stick this line at the end of the partial:
|
195
|
+
Let's now take care of our comments fields. We'll add these using our neat *automatic mode*: just stick this line at the end of the partial :
|
179
196
|
```ruby
|
180
197
|
# views/abyme/_task_fields.html.erb
|
181
198
|
# ... rest of the partial above
|
182
|
-
<%=
|
199
|
+
<%= f.abyme_for(:comments) %>
|
183
200
|
```
|
184
201
|
Where's the rest of the code ? Well, if the default configuration you saw above in the `_form.html.erb` suits you, and the order in which the different resources appear feels right (persisted first, new fields second, and the 'Add' button last), then you can just spare the block, and it will be taken care of for you. We'll just write our `_comment_fields.html.erb` partial in the `views/abyme` directory and we'll be all set.
|
185
202
|
|
@@ -202,118 +219,118 @@ Which is the way you would configure `nested_attributes` 90% of the time. Should
|
|
202
219
|
A few options can be passed to `abyme.records`:
|
203
220
|
* `collection:` : allows you to pass a collection of your choice to only display specific objects.
|
204
221
|
```ruby
|
205
|
-
<%=
|
222
|
+
<%= f.abyme_for(:tasks) do |abyme| %>
|
206
223
|
<%= abyme.records(collection: @project.tasks.where(done: false)) %>
|
207
224
|
<%= abyme.new_records %>
|
208
|
-
<%=
|
225
|
+
<%= add_associated_record %>
|
209
226
|
<% end %>
|
210
227
|
```
|
211
228
|
* `order:` : allows you to pass an ActiveRecord `order` method to sort your instances the way you want.
|
212
229
|
```ruby
|
213
|
-
<%=
|
230
|
+
<%= f.abyme_for(:tasks) do |abyme| %>
|
214
231
|
<%= abyme.records(order: { created_at: :asc }) %>
|
215
232
|
<%= abyme.new_records %>
|
216
|
-
<%=
|
233
|
+
<%= add_associated_record %>
|
217
234
|
<% end %>
|
218
235
|
```
|
219
|
-
* `partial:` : allows you to indicate a custom partial, if one has not already been passed to `
|
236
|
+
* `partial:` : allows you to indicate a custom partial, if one has not already been passed to `abyme_for`.
|
220
237
|
```ruby
|
221
|
-
<%=
|
238
|
+
<%= f.abyme_for(:tasks) do |abyme| %>
|
222
239
|
<%= abyme.records %>
|
223
240
|
<%= abyme.new_records(partial: 'projects/task_fields') %>
|
224
|
-
<%=
|
241
|
+
<%= add_associated_record %>
|
225
242
|
<% end %>
|
226
243
|
```
|
227
244
|
* `fields_html:` : gives you the possibility to add any HTML attribute you may want to each set of fields. By default, an `abyme--fields` and an `singular_association-fields` class are already present.
|
228
245
|
```ruby
|
229
|
-
<%=
|
246
|
+
<%= f.abyme_for(:tasks) do |abyme| %>
|
230
247
|
<%= abyme.records(fields_html: { class: "some-class" }) %>
|
231
248
|
# Every set of persisted fields will have these 3 classes : 'abyme--fields', 'task-fields', and 'some-class'
|
232
249
|
<%= abyme.new_records %>
|
233
|
-
<%=
|
250
|
+
<%= add_associated_record %>
|
234
251
|
<% end %>
|
235
252
|
```
|
236
253
|
* `wrapper_html:` : gives you the possibility to add any HTML attribute you may want to the wrapper containing all fields.
|
237
254
|
```ruby
|
238
|
-
<%=
|
255
|
+
<%= f.abyme_for(:tasks) do |abyme| %>
|
239
256
|
<%= abyme.records(wrapper_html: { class: "persisted-records" }) %>
|
240
257
|
# The wrapper containing all persisted task fields will have an id "abyme-tasks-wrapper" and a class "persisted-records"
|
241
258
|
<%= abyme.new_records %>
|
242
|
-
<%=
|
259
|
+
<%= add_associated_record %>
|
243
260
|
<% end %>
|
244
261
|
```
|
245
262
|
#### #new_records
|
246
263
|
Here are the options that can be passed to `abyme.new_records`:
|
247
264
|
* `position:` : allows you to specify whether new fields added dynamically should go at the top or at the bottom. `:end` is the default value.
|
248
265
|
```ruby
|
249
|
-
<%=
|
266
|
+
<%= f.abyme_for(:tasks) do |abyme| %>
|
250
267
|
<%= abyme.records %>
|
251
268
|
<%= abyme.new_records(position: :start) %>
|
252
|
-
<%=
|
269
|
+
<%= add_associated_record %>
|
253
270
|
<% end %>
|
254
271
|
```
|
255
272
|
* `partial:` : same as `#records`
|
256
273
|
* `fields_html:` : same as `#records`
|
257
274
|
* `wrapper_html:` : same as `#records`
|
258
275
|
|
259
|
-
#### #
|
276
|
+
#### #add_associated_record, #remove_associated_record
|
260
277
|
These 2 methods behave the same. Here are their options :
|
261
278
|
* `tag:` : allows you to specify a tag of your choosing, like `:a`, or `:div`. Default is `:button`.
|
262
279
|
* `content:` : the text to display inside the element. Default is `Add association_name`
|
263
280
|
* `html:` : gives you the possibility to add any HTML attribute you may want to the element.
|
264
281
|
```ruby
|
265
|
-
<%=
|
282
|
+
<%= f.abyme_for(:tasks) do |abyme| %>
|
266
283
|
# ...
|
267
|
-
<%=
|
284
|
+
<%= add_associated_record(tag: :a, content: "Add a super task", html: {id: "add-super-task"}) %>
|
268
285
|
<% end %>
|
269
286
|
```
|
270
287
|
|
271
288
|
As you may have seen above, you can also pass a block to the method to give it whatever HTML content you want :
|
272
289
|
```ruby
|
273
|
-
<%=
|
290
|
+
<%= f.abyme_for(:tasks) do |abyme| %>
|
274
291
|
# ...
|
275
|
-
<%=
|
292
|
+
<%= add_associated_record(tag: :div, html: {id: "add-super-task", class: "flex"}) do %>
|
276
293
|
<i class="fas fa-plus"></i>
|
277
294
|
<h2>Add a super task</h2>
|
278
295
|
<% end %>
|
279
296
|
<% end %>
|
280
297
|
```
|
281
298
|
|
282
|
-
#### #
|
299
|
+
#### #abyme_for(:association, form_object)
|
283
300
|
This is the container for all your nested fields. It takes two parameters (the symbolized association and the `form_builder`), and some optional ones. Please note an id is automatically added to this element, which value is : `abyme--association`.
|
284
301
|
* `partial:` : allows you to indicate a custom partial path for both `records` and `new_records`
|
285
302
|
```ruby
|
286
|
-
<%=
|
303
|
+
<%= f.abyme_for(:tasks, partial: 'projects/task_fields') do |abyme| %>
|
287
304
|
<%= abyme.records %>
|
288
305
|
<%= abyme.new_records %>
|
289
|
-
<%=
|
306
|
+
<%= add_associated_record %>
|
290
307
|
<% end %>
|
291
308
|
```
|
292
309
|
* `limit:` : allows you to limit the number of new fields that can be created through JS. If you need to limit the number of associations in database, you will need to add validations. You can also pass an option [in your model as well](https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for).
|
293
310
|
```ruby
|
294
|
-
<%=
|
311
|
+
<%= f.abyme_for(:tasks, limit: 5) do |abyme| %>
|
295
312
|
# Beyond 5 tasks, the add button won't add any more fields. See events section below to see how to handle the 'abyme:limit-reached' event
|
296
313
|
<%= abyme.records %>
|
297
314
|
<%= abyme.new_records %>
|
298
|
-
<%=
|
315
|
+
<%= add_associated_record %>
|
299
316
|
<% end %>
|
300
317
|
```
|
301
318
|
* `min_count` : by default, there won't be any blank fields added on page load. By passing a `min_count` option, you can set how many empty fields should appear in the form.
|
302
319
|
```ruby
|
303
|
-
<%=
|
320
|
+
<%= f.abyme_for(:tasks, min_count: 1) do |abyme| %>
|
304
321
|
# 1 blank task will automatically be added to the form.
|
305
322
|
<%= abyme.records %>
|
306
323
|
<%= abyme.new_records %>
|
307
|
-
<%=
|
324
|
+
<%= add_associated_record %>
|
308
325
|
<% end %>
|
309
326
|
```
|
310
327
|
|
311
|
-
*When in auto mode*, the
|
312
|
-
* `button_text:` : this will set the `
|
328
|
+
*When in auto mode*, the abyme_for method can take a few options:
|
329
|
+
* `button_text:` : this will set the `add_associated_record` button text to the string of your choice.
|
313
330
|
* All options that should be passed to either `records` or `new_records` can be passed here and will be passed down.
|
314
331
|
|
315
332
|
## Events
|
316
|
-
This part is still a work in progress and subject to change. We're providing some basic self-explanatory events to attach to. These are emitted by the main container (created by the `
|
333
|
+
This part is still a work in progress and subject to change. We're providing some basic self-explanatory events to attach to. These are emitted by the main container (created by the `abyme_for` method).
|
317
334
|
|
318
335
|
We're currently thinking about a way to attach to these via Stimulus. Coming soon !
|
319
336
|
|
@@ -1,7 +1,13 @@
|
|
1
1
|
import { Controller } from 'stimulus';
|
2
2
|
|
3
3
|
export default class extends Controller {
|
4
|
-
static targets = ['template', 'associations', 'fields', 'newFields'];
|
4
|
+
// static targets = ['template', 'associations', 'fields', 'newFields'];
|
5
|
+
// Some applications don't compile correctly with the usual static syntax.
|
6
|
+
// Thus implementing targets with standard getters below
|
7
|
+
|
8
|
+
static get targets() {
|
9
|
+
return ['template', 'associations', 'fields', 'newFields'];
|
10
|
+
}
|
5
11
|
|
6
12
|
connect() {
|
7
13
|
console.log("Abyme Connected")
|
data/lib/abyme.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Abyme
|
2
|
+
module ActionViewExtensions
|
3
|
+
module Builder
|
4
|
+
def abyme_for(association, options = {}, &block)
|
5
|
+
@template.abyme_for(association, self, options, &block)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module ActionView::Helpers
|
12
|
+
class FormBuilder
|
13
|
+
include Abyme::ActionViewExtensions::Builder
|
14
|
+
end
|
15
|
+
end
|
data/lib/abyme/engine.rb
CHANGED
data/lib/abyme/model.rb
CHANGED
@@ -3,7 +3,7 @@ module Abyme
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
class_methods do
|
6
|
-
def
|
6
|
+
def abymize(association, options = {})
|
7
7
|
default_options = {reject_if: :all_blank, allow_destroy: true}
|
8
8
|
accepts_nested_attributes_for association, default_options.merge(options)
|
9
9
|
end
|
data/lib/abyme/version.rb
CHANGED
data/lib/abyme/view_helpers.rb
CHANGED
@@ -10,7 +10,7 @@ module Abyme
|
|
10
10
|
# it takes the Symbolized name of the association (plural) and the form object
|
11
11
|
# then you can pass a hash of options (see exemple below)
|
12
12
|
# if no block given it will generate a default markup for
|
13
|
-
# #persisted_records_for, #new_records_for & #
|
13
|
+
# #persisted_records_for, #new_records_for & #add_associated_record methods
|
14
14
|
# if a block is given it will instanciate a new AbymeBuilder and pass to it
|
15
15
|
# the name of the association, the form object and the lookup_context
|
16
16
|
|
@@ -38,7 +38,7 @@ module Abyme
|
|
38
38
|
# ...
|
39
39
|
# </div>
|
40
40
|
|
41
|
-
def
|
41
|
+
def abyme_for(association, form, options = {}, &block)
|
42
42
|
content_tag(:div, data: { controller: 'abyme', limit: options[:limit], min_count: options[:min_count] }, id: "abyme--#{association}") do
|
43
43
|
if block_given?
|
44
44
|
yield(Abyme::AbymeBuilder.new(
|
@@ -49,7 +49,7 @@ module Abyme
|
|
49
49
|
model = association.to_s.singularize.classify.constantize
|
50
50
|
concat(persisted_records_for(association, form, options))
|
51
51
|
concat(new_records_for(association, form, options))
|
52
|
-
concat(
|
52
|
+
concat(add_associated_record(content: options[:button_text] || "Add #{model}"))
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -100,7 +100,7 @@ module Abyme
|
|
100
100
|
|
101
101
|
wrapper_default = {
|
102
102
|
data: {
|
103
|
-
|
103
|
+
abyme_target: 'associations',
|
104
104
|
association: association,
|
105
105
|
abyme_position: options[:position] || :end
|
106
106
|
}
|
@@ -109,7 +109,7 @@ module Abyme
|
|
109
109
|
fields_default = { data: { target: 'abyme.fields abyme.newFields' } }
|
110
110
|
|
111
111
|
content_tag(:div, build_attributes(wrapper_default, options[:wrapper_html])) do
|
112
|
-
content_tag(:template, class: "abyme--#{association.to_s.singularize}_template", data: {
|
112
|
+
content_tag(:template, class: "abyme--#{association.to_s.singularize}_template", data: { abyme_target: 'template' }) do
|
113
113
|
form.fields_for association, association.to_s.classify.constantize.new, child_index: 'NEW_RECORD' do |f|
|
114
114
|
content_tag(:div, build_attributes(fields_default, basic_fields_markup(options[:fields_html], association))) do
|
115
115
|
# Here, if a block is passed, we're passing the association fields to it, rather than the form itself
|
@@ -164,7 +164,7 @@ module Abyme
|
|
164
164
|
def persisted_records_for(association, form, options = {})
|
165
165
|
records = options[:collection] || form.object.send(association)
|
166
166
|
options[:wrapper_html] ||= {}
|
167
|
-
fields_default = { data: {
|
167
|
+
fields_default = { data: { abyme_target: 'fields' } }
|
168
168
|
|
169
169
|
if options[:order].present?
|
170
170
|
records = records.order(options[:order])
|
@@ -190,13 +190,13 @@ module Abyme
|
|
190
190
|
# to generate the buttons for add and remove associations
|
191
191
|
# with the right action and a default content text for each button
|
192
192
|
|
193
|
-
def
|
193
|
+
def add_associated_record(options = {}, &block)
|
194
194
|
action = 'click->abyme#add_association'
|
195
195
|
options[:content] ||= 'Add Association'
|
196
196
|
create_button(action, options, &block)
|
197
197
|
end
|
198
198
|
|
199
|
-
def
|
199
|
+
def remove_associated_record(options = {}, &block)
|
200
200
|
action = 'click->abyme#remove_association'
|
201
201
|
options[:content] ||= 'Remove Association'
|
202
202
|
create_button(action, options, &block)
|
@@ -206,7 +206,7 @@ module Abyme
|
|
206
206
|
|
207
207
|
# CREATE_BUTTON
|
208
208
|
|
209
|
-
# this helper is call by either
|
209
|
+
# this helper is call by either add_associated_record or remove_associated_record
|
210
210
|
# by default it will generate a button tag.
|
211
211
|
|
212
212
|
# == Options
|
data/package.json
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abyme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Romain Sanson
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-02-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -191,6 +191,7 @@ files:
|
|
191
191
|
- ".gitignore"
|
192
192
|
- ".rspec"
|
193
193
|
- ".simplecov"
|
194
|
+
- CHANGELOG.md
|
194
195
|
- Gemfile
|
195
196
|
- Gemfile.lock
|
196
197
|
- LICENSE.txt
|
@@ -205,6 +206,7 @@ files:
|
|
205
206
|
- lib/.DS_Store
|
206
207
|
- lib/abyme.rb
|
207
208
|
- lib/abyme/abyme_builder.rb
|
209
|
+
- lib/abyme/action_view_extensions/builder.rb
|
208
210
|
- lib/abyme/engine.rb
|
209
211
|
- lib/abyme/model.rb
|
210
212
|
- lib/abyme/version.rb
|