active_fields 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/README.md +92 -77
- data/app/models/concerns/active_fields/customizable_concern.rb +4 -1
- data/lib/active_fields/engine.rb +6 -0
- data/lib/active_fields/version.rb +1 -1
- data/lib/active_fields.rb +51 -31
- data/lib/generators/active_fields/install/install_generator.rb +1 -1
- data/lib/generators/active_fields/scaffold/USAGE +9 -0
- data/lib/generators/active_fields/scaffold/scaffold_generator.rb +25 -0
- data/lib/generators/active_fields/scaffold/templates/controllers/active_fields_controller.rb +143 -0
- data/lib/generators/active_fields/scaffold/templates/helpers/active_fields_helper.rb +33 -0
- data/lib/generators/active_fields/scaffold/templates/javascript/controllers/array_field_controller.js +25 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/edit.html.erb +5 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_boolean.html.erb +53 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_date.html.erb +58 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_date_array.html.erb +70 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_datetime.html.erb +63 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_datetime_array.html.erb +75 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_decimal.html.erb +63 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_decimal_array.html.erb +76 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_enum.html.erb +61 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_enum_array.html.erb +73 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_integer.html.erb +58 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_integer_array.html.erb +70 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_text.html.erb +53 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/forms/_text_array.html.erb +70 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/index.html.erb +41 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/new.html.erb +5 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/show.html.erb +29 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_boolean.html.erb +8 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_date.html.erb +4 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_date_array.html.erb +12 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_datetime.html.erb +4 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_datetime_array.html.erb +12 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_decimal.html.erb +4 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_decimal_array.html.erb +12 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_enum.html.erb +4 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_enum_array.html.erb +4 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_integer.html.erb +4 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_integer_array.html.erb +12 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_text.html.erb +4 -0
- data/lib/generators/active_fields/scaffold/templates/views/active_fields/values/inputs/_text_array.html.erb +12 -0
- data/lib/generators/active_fields/scaffold/templates/views/shared/_array_field.html.erb +19 -0
- metadata +39 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd75dc9f715c95766a238fd268c8174c7920e2b64ddce086f4bd7eed9ea2c36a
|
4
|
+
data.tar.gz: 74ba8eaf11a578067d0c45730a59aa60dc23363b9e5ffcce5bfca7795ee12da3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4cc1b2984a7912497bc1b26cec3fc793bb897cc813c76440b5a8513834acae27d5c4df5da9c5f87cf9b36ae79351cacb52ab60965195fa6b44ce6ec8fc4f3c4e
|
7
|
+
data.tar.gz: 2f03d79bb28e91af86a99d36ff60a992b14ecf9c13d6d8a13eb92490790c4cd71afb11465173ba8a2a756cc24c3cf50c488a13bc8fca90d619b1079ec88fe216
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
## [Unreleased]
|
2
|
+
|
3
|
+
## [1.1.0] - 2024-09-10
|
4
|
+
- Added scaffold generator
|
5
|
+
- Disabled models reloading to prevent STI issues
|
6
|
+
|
7
|
+
## [1.0.0] - 2024-09-07
|
2
8
|
- Precision configuration for decimal fields
|
3
9
|
- Added array field types mix-in `ActiveFields::FieldArrayConcern`
|
4
10
|
- Fixed enum types behavior for blank values
|
data/README.md
CHANGED
@@ -9,9 +9,9 @@ enabling the addition of custom fields to any model at runtime without requiring
|
|
9
9
|
|
10
10
|
## Key Concepts
|
11
11
|
|
12
|
-
- **
|
13
|
-
- **Active
|
14
|
-
- **
|
12
|
+
- **Customizable**: A record that has custom fields (_Entity_).
|
13
|
+
- **Active Field**: A record with the definition of a custom field (_Attribute_).
|
14
|
+
- **Active Value**: A record that stores the value of an _Active Field_ for a specific _Customizable_ (_Value_).
|
15
15
|
|
16
16
|
## Models Structure
|
17
17
|
|
@@ -24,11 +24,11 @@ classDiagram
|
|
24
24
|
+ string name
|
25
25
|
+ string type
|
26
26
|
+ string customizable_type
|
27
|
-
+ json
|
27
|
+
+ json default_value_meta
|
28
28
|
+ json options
|
29
29
|
}
|
30
30
|
class ActiveValue {
|
31
|
-
+ json
|
31
|
+
+ json value_meta
|
32
32
|
}
|
33
33
|
class Customizable {
|
34
34
|
// This is your model
|
@@ -56,78 +56,90 @@ such as booleans, strings, numbers, arrays, etc.
|
|
56
56
|
3. Add the `has_active_fields` method to any models where you want to enable custom fields:
|
57
57
|
|
58
58
|
```ruby
|
59
|
-
class
|
59
|
+
class Post < ApplicationRecord
|
60
60
|
has_active_fields
|
61
61
|
end
|
62
62
|
```
|
63
63
|
|
64
|
-
4.
|
64
|
+
4. Run scaffold generator.
|
65
65
|
|
66
|
-
This plugin provides a convenient API
|
66
|
+
This plugin provides a convenient API, allowing you to write code that meets your specific needs
|
67
67
|
without being forced to use predefined implementations that is hard to extend.
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
69
|
+
However, for a quick start, you can generate a scaffold by running the following command:
|
70
|
+
|
71
|
+
```shell
|
72
|
+
bin/rails generate active_fields:scaffold
|
73
|
+
```
|
74
|
+
|
75
|
+
This command generates a controller, routes and views for managing _Active Fields_,
|
76
|
+
along with form inputs for _Active Values_ and some useful helper methods.
|
77
|
+
|
78
|
+
**Note:** Don't forget to add available _Customizable_ types in generated _Active Fields_ forms.
|
79
|
+
|
80
|
+
**Note:** The array field helper uses _Stimulus_ for interactivity.
|
81
|
+
If your app doesn't already include _Stimulus_, you can [easily add it](https://github.com/hotwired/stimulus-rails).
|
82
|
+
Alternatively, if you prefer not to use _Stimulus_, you should implement your own JavaScript code.
|
83
|
+
|
84
|
+
5. Add _Active Fields_ inputs in _Customizables_ forms and permit their params in controllers.
|
85
|
+
|
86
|
+
There are two methods available on _Customizable_ models for retrieving _Active Values_:
|
87
|
+
- `active_values` returns collection of only existing _Active Values_.
|
88
|
+
- `initialize_active_values` builds any missing _Active Values_ and returns the full collection.
|
89
|
+
|
90
|
+
Choose the method that suits your requirements.
|
91
|
+
In most cases, however, `initialize_active_values` is the more suitable option.
|
92
|
+
|
93
|
+
```erb
|
94
|
+
# app/views/posts/_form.html.erb
|
95
|
+
# ...
|
96
|
+
|
97
|
+
<%= form.fields_for :active_fields, post.initialize_active_values.sort_by(&:active_field_id), include_id: false do |active_fields_form| %>
|
98
|
+
<%= active_fields_form.hidden_field :name %>
|
99
|
+
<%= render_active_value_input(form: active_fields_form, active_value: active_fields_form.object) %>
|
100
|
+
<% end %>
|
101
|
+
|
102
|
+
# ...
|
103
|
+
```
|
104
|
+
|
105
|
+
Finally, permit the _Active Fields_ attributes in your _Customizables_ controllers:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
# app/controllers/posts_controller.rb
|
109
|
+
# ...
|
110
|
+
|
111
|
+
def post_params
|
112
|
+
permitted_params = params.require(:post).permit(
|
113
|
+
# ...
|
114
|
+
active_fields_attributes: [:name, :value, :_destroy, value: []],
|
115
|
+
)
|
116
|
+
permitted_params[:active_fields_attributes]&.each do |_index, value_attrs|
|
117
|
+
value_attrs[:value] = compact_array_param(value_attrs[:value]) if value_attrs[:value].is_a?(Array)
|
118
|
+
end
|
119
|
+
|
120
|
+
permitted_params
|
121
|
+
end
|
122
|
+
|
123
|
+
# Removes an empty string from the beginning of the array parameter
|
124
|
+
def compact_array_param(value)
|
125
|
+
if value.first == ""
|
126
|
+
value[1..-1]
|
127
|
+
else
|
128
|
+
value
|
129
|
+
end
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
**Note:** Here we use the `active_fields_attributes=` method (as a permitted parameter),
|
134
|
+
that integrates well with Rails `fields_for` to generate appropriate form fields.
|
135
|
+
Alternatively, the alias `active_fields=` can be used in contexts without `fields_for`, such as API controllers.
|
136
|
+
|
137
|
+
That's it!
|
138
|
+
You can now add _Active Fields_ to _Customizables_ at `http://localhost:3000/active_fields`
|
139
|
+
and fill in _Active Values_ within _Customizable_ forms.
|
140
|
+
|
141
|
+
You can also explore the [Demo app](https://github.com/lassoid/active_fields/blob/main/spec/dummy)
|
142
|
+
where the plugin is fully integrated into a full-stack Rails application.
|
131
143
|
Feel free to explore the source code and run it locally:
|
132
144
|
|
133
145
|
```shell
|
@@ -251,7 +263,7 @@ classDiagram
|
|
251
263
|
- `name`(`string`)
|
252
264
|
- `type`(`string`)
|
253
265
|
- `customizable_type`(`string`)
|
254
|
-
- `
|
266
|
+
- `default_value_meta` (`json`)
|
255
267
|
|
256
268
|
### Field Types Summary
|
257
269
|
|
@@ -495,6 +507,8 @@ For an example, refer to the [locale file](https://github.com/lassoid/active_fie
|
|
495
507
|
leading to the associated _Customizables_ also becoming invalid,
|
496
508
|
which could potentially result in update failures.
|
497
509
|
|
510
|
+
3. Only _Zeitwerk_ autoloading mode is supported.
|
511
|
+
|
498
512
|
## API Overview
|
499
513
|
|
500
514
|
### Fields API
|
@@ -510,7 +524,7 @@ active_field.type # Class name of this Active Field (utilizing STI)
|
|
510
524
|
active_field.customizable_type # Name of the Customizable model this Active Field is registered to
|
511
525
|
active_field.name # Identifier of this Active Field, it should be unique in scope of customizable_type
|
512
526
|
active_field.default_value_meta # JSON column declaring the default value. Consider using `default_value` instead
|
513
|
-
active_field.options #
|
527
|
+
active_field.options # JSON column containing type-specific attributes for this Active Field
|
514
528
|
|
515
529
|
# Methods:
|
516
530
|
active_field.default_value # Default value for all Active Values associated with this Active Field
|
@@ -523,7 +537,7 @@ active_field.customizable_model # Customizable model class
|
|
523
537
|
active_field.type_name # Identifier of the type of this Active Field (instead of class name)
|
524
538
|
|
525
539
|
# Scopes:
|
526
|
-
ActiveFields::Field::Boolean.for("
|
540
|
+
ActiveFields::Field::Boolean.for("Post") # Collection of Active Fields registered for the specified Customizable type
|
527
541
|
```
|
528
542
|
|
529
543
|
### Values API
|
@@ -546,7 +560,7 @@ active_value.name # Name of the associated Active Field
|
|
546
560
|
### Customizable API
|
547
561
|
|
548
562
|
```ruby
|
549
|
-
customizable =
|
563
|
+
customizable = Post.take
|
550
564
|
|
551
565
|
# Associations:
|
552
566
|
customizable.active_values # `has_many` association with Active Values linked to this Customizable
|
@@ -577,9 +591,10 @@ customizable.active_fields = [
|
|
577
591
|
# Please use `active_fields_attributes=`/`active_fields=` instead.
|
578
592
|
customizable.active_values_attributes = attributes
|
579
593
|
|
580
|
-
# Build
|
594
|
+
# Build not existing Active Values, with the default value for each Active Field.
|
595
|
+
# Returns full collection of Active Values.
|
581
596
|
# This method is useful with `fields_for`, allowing you to pass the collection as an argument to render new Active Values:
|
582
|
-
# `form.fields_for :
|
597
|
+
# `form.fields_for :active_fields, customizable.initialize_active_values`.
|
583
598
|
customizable.initialize_active_values
|
584
599
|
```
|
585
600
|
|
@@ -602,7 +617,7 @@ ActiveFields.config.register_field(:ip, "IpField") # Register a custom Active Fi
|
|
602
617
|
### Customizable Config
|
603
618
|
|
604
619
|
```ruby
|
605
|
-
customizable_model =
|
620
|
+
customizable_model = Post
|
606
621
|
customizable_model.active_fields_config # Access the Customizable's configuration
|
607
622
|
customizable_model.active_fields_config.customizable_model # The Customizable model itself
|
608
623
|
customizable_model.active_fields_config.types # Allowed Active Field types (e.g., `[:boolean]`)
|
@@ -80,7 +80,8 @@ module ActiveFields
|
|
80
80
|
|
81
81
|
alias_method :active_fields=, :active_fields_attributes=
|
82
82
|
|
83
|
-
# Build an active_value, if it doesn't exist, with a default value for each available active_field
|
83
|
+
# Build an active_value, if it doesn't exist, with a default value for each available active_field.
|
84
|
+
# Returns active_values collection.
|
84
85
|
def initialize_active_values
|
85
86
|
existing_field_ids = active_values.map(&:active_field_id)
|
86
87
|
|
@@ -89,6 +90,8 @@ module ActiveFields
|
|
89
90
|
|
90
91
|
active_values.new(active_field: active_field, value: active_field.default_value)
|
91
92
|
end
|
93
|
+
|
94
|
+
active_values
|
92
95
|
end
|
93
96
|
end
|
94
97
|
end
|
data/lib/active_fields/engine.rb
CHANGED
@@ -4,6 +4,12 @@ module ActiveFields
|
|
4
4
|
class Engine < ::Rails::Engine
|
5
5
|
isolate_namespace ActiveFields
|
6
6
|
|
7
|
+
config.eager_load_namespaces << ActiveFields
|
8
|
+
|
9
|
+
# Disable models reloading to avoid STI issues.
|
10
|
+
# Reloading can prevent subclasses from recognizing the base class.
|
11
|
+
config.autoload_once_paths = %W[#{root}/app/models #{root}/app/models/concerns]
|
12
|
+
|
7
13
|
initializer "active_fields.active_record" do
|
8
14
|
ActiveSupport.on_load(:active_record) do
|
9
15
|
include HasActiveFields
|
data/lib/active_fields.rb
CHANGED
@@ -4,42 +4,62 @@ require_relative "active_fields/version"
|
|
4
4
|
require_relative "active_fields/engine"
|
5
5
|
|
6
6
|
module ActiveFields
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
extend ActiveSupport::Autoload
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def eager_load!
|
11
|
+
super
|
12
|
+
Casters.eager_load!
|
13
|
+
Validators.eager_load!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
eager_autoload do
|
18
|
+
autoload :Config
|
19
|
+
autoload :CustomizableConfig
|
20
|
+
autoload :HasActiveFields
|
21
|
+
end
|
10
22
|
|
11
23
|
module Casters
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
extend ActiveSupport::Autoload
|
25
|
+
|
26
|
+
eager_autoload do
|
27
|
+
autoload :BaseCaster
|
28
|
+
autoload :BooleanCaster
|
29
|
+
autoload :DateCaster
|
30
|
+
autoload :DateArrayCaster
|
31
|
+
autoload :DateTimeCaster
|
32
|
+
autoload :DateTimeArrayCaster
|
33
|
+
autoload :DecimalCaster
|
34
|
+
autoload :DecimalArrayCaster
|
35
|
+
autoload :EnumCaster
|
36
|
+
autoload :EnumArrayCaster
|
37
|
+
autoload :IntegerCaster
|
38
|
+
autoload :IntegerArrayCaster
|
39
|
+
autoload :TextCaster
|
40
|
+
autoload :TextArrayCaster
|
41
|
+
end
|
26
42
|
end
|
27
43
|
|
28
44
|
module Validators
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
45
|
+
extend ActiveSupport::Autoload
|
46
|
+
|
47
|
+
eager_autoload do
|
48
|
+
autoload :BaseValidator
|
49
|
+
autoload :BooleanValidator
|
50
|
+
autoload :DateValidator
|
51
|
+
autoload :DateArrayValidator
|
52
|
+
autoload :DateTimeValidator
|
53
|
+
autoload :DateTimeArrayValidator
|
54
|
+
autoload :DecimalValidator
|
55
|
+
autoload :DecimalArrayValidator
|
56
|
+
autoload :EnumValidator
|
57
|
+
autoload :EnumArrayValidator
|
58
|
+
autoload :IntegerValidator
|
59
|
+
autoload :IntegerArrayValidator
|
60
|
+
autoload :TextValidator
|
61
|
+
autoload :TextArrayValidator
|
62
|
+
end
|
43
63
|
end
|
44
64
|
|
45
65
|
class << self
|
@@ -5,7 +5,7 @@ require "rails/generators"
|
|
5
5
|
module ActiveFields
|
6
6
|
module Generators
|
7
7
|
class InstallGenerator < ::Rails::Generators::Base
|
8
|
-
desc "This generator creates an
|
8
|
+
desc "This generator creates an initializer and copies plugin migrations"
|
9
9
|
|
10
10
|
def create_initializer
|
11
11
|
initializer "active_fields.rb", <<~RUBY
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Description:
|
2
|
+
Creates a controller, routes and views for managing Active Fields,
|
3
|
+
along with form inputs for Active Values and some useful helper methods.
|
4
|
+
|
5
|
+
The code it generates is unlikely to be a perfect fit for your application.
|
6
|
+
You’ll most probably want to customize the generated code.
|
7
|
+
|
8
|
+
Examples:
|
9
|
+
`bin/rails generate active_fields:scaffold`
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
|
5
|
+
module ActiveFields
|
6
|
+
module Generators
|
7
|
+
class ScaffoldGenerator < ::Rails::Generators::Base
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
9
|
+
|
10
|
+
desc "This generator creates some useful templates"
|
11
|
+
|
12
|
+
def copy_files
|
13
|
+
Dir.glob("**/*", base: self.class.source_root).each do |path|
|
14
|
+
next unless File.file?(File.expand_path(path, self.class.source_root))
|
15
|
+
|
16
|
+
copy_file path, File.join("app", path)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_routes
|
21
|
+
route "resources :active_fields"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ActiveFieldsController < ApplicationController
|
4
|
+
helper ActiveFieldsHelper
|
5
|
+
|
6
|
+
before_action :set_active_field, only: %i[show edit update destroy]
|
7
|
+
|
8
|
+
def index
|
9
|
+
@active_fields = ActiveFields.config.field_base_class.order(:customizable_type, :id)
|
10
|
+
end
|
11
|
+
|
12
|
+
def show; end
|
13
|
+
|
14
|
+
def new
|
15
|
+
@active_field = model_class.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def create
|
19
|
+
@active_field = model_class.new(active_field_create_params(model_class))
|
20
|
+
|
21
|
+
if @active_field.save
|
22
|
+
redirect_to edit_active_field_path(@active_field), status: :see_other
|
23
|
+
else
|
24
|
+
render :new, status: :unprocessable_entity
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def edit; end
|
29
|
+
|
30
|
+
def update
|
31
|
+
if @active_field.update(active_field_update_params(@active_field.class))
|
32
|
+
redirect_to edit_active_field_path(@active_field), status: :see_other
|
33
|
+
else
|
34
|
+
render :edit, status: :unprocessable_entity
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy
|
39
|
+
@active_field.destroy!
|
40
|
+
|
41
|
+
redirect_to active_fields_path, status: :see_other
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def active_field_create_params(model_class)
|
47
|
+
params.require(:active_field).permit(*permitted_attributes_for_create(model_class)).tap do |attrs|
|
48
|
+
attrs.transform_values! do |value|
|
49
|
+
value.is_a?(Array) ? compact_array_param(value) : value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def active_field_update_params(model_class)
|
55
|
+
params.require(:active_field).permit(*permitted_attributes_for_update(model_class)).tap do |attrs|
|
56
|
+
attrs.transform_values! do |value|
|
57
|
+
value.is_a?(Array) ? compact_array_param(value) : value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def compact_array_param(value)
|
63
|
+
if value.first == ""
|
64
|
+
value[1..-1]
|
65
|
+
else
|
66
|
+
value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# It is strongly recommended to move it to, for example, policies.
|
71
|
+
def permitted_attributes_for_create(model_class)
|
72
|
+
if model_class == ActiveFields::Field::Boolean
|
73
|
+
%i[customizable_type name required nullable default_value]
|
74
|
+
elsif model_class == ActiveFields::Field::Date
|
75
|
+
%i[customizable_type name required min max default_value]
|
76
|
+
elsif model_class == ActiveFields::Field::DateArray
|
77
|
+
[:customizable_type, :name, :min_size, :max_size, :min, :max, default_value: []]
|
78
|
+
elsif model_class == ActiveFields::Field::DateTime
|
79
|
+
%i[customizable_type name required min max precision default_value]
|
80
|
+
elsif model_class == ActiveFields::Field::DateTimeArray
|
81
|
+
[:customizable_type, :name, :min_size, :max_size, :min, :max, :precision, default_value: []]
|
82
|
+
elsif model_class == ActiveFields::Field::Decimal
|
83
|
+
%i[customizable_type name required min max precision default_value]
|
84
|
+
elsif model_class == ActiveFields::Field::DecimalArray
|
85
|
+
[:customizable_type, :name, :min_size, :max_size, :min, :max, :precision, default_value: []]
|
86
|
+
elsif model_class == ActiveFields::Field::Enum
|
87
|
+
[:customizable_type, :name, :required, :default_value, allowed_values: []]
|
88
|
+
elsif model_class == ActiveFields::Field::EnumArray
|
89
|
+
[:customizable_type, :name, :min_size, :max_size, allowed_values: [], default_value: []]
|
90
|
+
elsif model_class == ActiveFields::Field::Integer
|
91
|
+
%i[customizable_type name required min max default_value]
|
92
|
+
elsif model_class == ActiveFields::Field::IntegerArray
|
93
|
+
[:customizable_type, :name, :min_size, :max_size, :min, :max, default_value: []]
|
94
|
+
elsif model_class == ActiveFields::Field::Text
|
95
|
+
%i[customizable_type name min_length max_length default_value]
|
96
|
+
elsif model_class == ActiveFields::Field::TextArray
|
97
|
+
[:customizable_type, :name, :min_size, :max_size, :min_length, :max_length, default_value: []]
|
98
|
+
else
|
99
|
+
raise ArgumentError, "undefined model_class `#{model_class.inspect}`"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# It is strongly recommended to move it to, for example, policies.
|
104
|
+
def permitted_attributes_for_update(model_class)
|
105
|
+
if model_class == ActiveFields::Field::Boolean
|
106
|
+
%i[name default_value]
|
107
|
+
elsif model_class == ActiveFields::Field::Date
|
108
|
+
%i[name default_value]
|
109
|
+
elsif model_class == ActiveFields::Field::DateArray
|
110
|
+
[:name, default_value: []]
|
111
|
+
elsif model_class == ActiveFields::Field::DateTime
|
112
|
+
%i[name default_value]
|
113
|
+
elsif model_class == ActiveFields::Field::DateTimeArray
|
114
|
+
[:name, default_value: []]
|
115
|
+
elsif model_class == ActiveFields::Field::Decimal
|
116
|
+
%i[name default_value]
|
117
|
+
elsif model_class == ActiveFields::Field::DecimalArray
|
118
|
+
[:name, default_value: []]
|
119
|
+
elsif model_class == ActiveFields::Field::Enum
|
120
|
+
%i[name default_value]
|
121
|
+
elsif model_class == ActiveFields::Field::EnumArray
|
122
|
+
[:name, default_value: []]
|
123
|
+
elsif model_class == ActiveFields::Field::Integer
|
124
|
+
%i[name default_value]
|
125
|
+
elsif model_class == ActiveFields::Field::IntegerArray
|
126
|
+
[:name, default_value: []]
|
127
|
+
elsif model_class == ActiveFields::Field::Text
|
128
|
+
%i[name default_value]
|
129
|
+
elsif model_class == ActiveFields::Field::TextArray
|
130
|
+
[:name, default_value: []]
|
131
|
+
else
|
132
|
+
raise ArgumentError, "undefined model_class `#{model_class.inspect}`"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def set_active_field
|
137
|
+
@active_field = ActiveFields.config.field_base_class.find(params[:id])
|
138
|
+
end
|
139
|
+
|
140
|
+
def model_class
|
141
|
+
(ActiveFields.config.fields[params[:type]&.to_sym] || ActiveFields.config.type_class_names.first).constantize
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveFieldsHelper
|
4
|
+
def render_array_field(form:, name:, value:, field_method:, field_opts: {})
|
5
|
+
render partial: "shared/array_field", locals: {
|
6
|
+
form: form,
|
7
|
+
name: name,
|
8
|
+
value: value,
|
9
|
+
field_method: field_method,
|
10
|
+
field_opts: field_opts,
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def render_active_field_form(active_field:)
|
15
|
+
partial = active_field_form(active_field)
|
16
|
+
|
17
|
+
render partial: partial, locals: { active_field: active_field }
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_active_value_input(form:, active_value:)
|
21
|
+
partial = active_value_input(active_value.active_field)
|
22
|
+
|
23
|
+
render partial: partial, locals: { form: form, active_value: active_value, active_field: active_value.active_field }
|
24
|
+
end
|
25
|
+
|
26
|
+
def active_field_form(active_field)
|
27
|
+
"active_fields/forms/#{active_field.type_name}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def active_value_input(active_field)
|
31
|
+
"active_fields/values/inputs/#{active_field.type_name}"
|
32
|
+
end
|
33
|
+
end
|