para 0.12.5 → 0.12.7
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/app/views/para/admin/nested_forms/show.html.haml +0 -1
- data/app/views/para/inputs/nested_many/_add.html.haml +1 -1
- data/app/views/para/inputs/nested_many/_add_with_subclasses.html.haml +2 -2
- data/lib/para/cloneable/include_tree_builder.rb +40 -4
- data/lib/para/form_builder/attributes_mappings_tracker.rb +8 -9
- data/lib/para/version.rb +1 -1
- metadata +3 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5339b2dc5c28403fd3e4ba08fbb1bfc7b2b2196269f9927d25eb1d428eb99d71
|
|
4
|
+
data.tar.gz: 6266de04143dbd8e18aa9826e8a007d2d96909d4d4f6d9704791e30893f0cffe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aa7cfd1587567f56a06853bfc0acf74736d4082d79a59f51af90de4fc4afc4fc840085e1e4580aa8372eee4e6e2299584f262ba7d064ee47fffc4abf71ed6fd9
|
|
7
|
+
data.tar.gz: 5ad58a35c8f690c2ce70063f12cc04ebf0f2e1b812ea22c8f2918193f16e3b7f98a4758b0a780affbb3e7e72a4f319906dae122c650bd3c183aba84ac2a4db14
|
|
@@ -13,6 +13,5 @@
|
|
|
13
13
|
- form.object_name = @object_name
|
|
14
14
|
- nested_form = capture do
|
|
15
15
|
= render(partial: find_partial_for(@model, :remote_nested_form), locals: { form: form, model: @model, object: @object, object_name: @object_name })
|
|
16
|
-
= form.attributes_mappings_field_for(form)
|
|
17
16
|
|
|
18
17
|
= nested_form
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
= link_to_add_association form, attribute_name, partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: "btn btn-shadow add-button nested-many-inset-add-button #{add_button_class}", data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, locals: { model: model, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, allow_destroy_if: allow_destroy_if, render_partial: render_partial, remote_partial_params: remote_partial_params } } do
|
|
1
|
+
= link_to_add_association form, attribute_name, partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: "btn btn-shadow add-button nested-many-inset-add-button #{add_button_class}", data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, track_attribute_mappings: render_partial, locals: { model: model, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, allow_destroy_if: allow_destroy_if, render_partial: render_partial, remote_partial_params: remote_partial_params } } do
|
|
2
2
|
= add_button_label
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
- if subclasses.one?
|
|
2
2
|
- submodel = subclasses.first
|
|
3
3
|
|
|
4
|
-
= link_to_add_association form, attribute_name, wrap_object: proc { with_inverse_association_for(submodel.new, attribute_name, form.object) }, partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: "btn btn-shadow add-button nested-many-inset-add-button #{add_button_class}", data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, locals: { model: submodel, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, render_partial: render_partial, remote_partial_params: remote_partial_params, allow_destroy_if: allow_destroy_if } } do
|
|
4
|
+
= link_to_add_association form, attribute_name, wrap_object: proc { with_inverse_association_for(submodel.new, attribute_name, form.object) }, partial: find_partial_for(model, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: "btn btn-shadow add-button nested-many-inset-add-button #{add_button_class}", data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, track_attribute_mappings: render_partial, locals: { model: submodel, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, render_partial: render_partial, remote_partial_params: remote_partial_params, allow_destroy_if: allow_destroy_if } } do
|
|
5
5
|
= add_button_label
|
|
6
6
|
- else
|
|
7
7
|
.add-button.nested-many-inset-add-button.dropdown
|
|
@@ -11,5 +11,5 @@
|
|
|
11
11
|
%ul.dropdown-menu
|
|
12
12
|
- subclasses.each do |submodel|
|
|
13
13
|
%li
|
|
14
|
-
= link_to_add_association form, attribute_name, wrap_object: proc { with_inverse_association_for(submodel.new, attribute_name, form.object) }, partial: find_partial_for(submodel, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: 'dropdown-link', data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, locals: { model: submodel, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, allow_destroy_if: allow_destroy_if, render_partial: render_partial, remote_partial_params: remote_partial_params } } do
|
|
14
|
+
= link_to_add_association form, attribute_name, wrap_object: proc { with_inverse_association_for(submodel.new, attribute_name, form.object) }, partial: find_partial_for(submodel, 'nested_many/container', partial_dir: 'inputs'), form_name: 'form', class: 'dropdown-link', data: { :'association-insertion-node' => "##{ dom_identifier }", :'association-insertion-method' => 'append' }, render_options: { nested_attribute_name: attribute_name, orderable: orderable, track_attribute_mappings: render_partial, locals: { model: submodel, nested_locals: nested_locals, inset: inset, uncollapsed: uncollapsed, allow_destroy_if: allow_destroy_if, render_partial: render_partial, remote_partial_params: remote_partial_params } } do
|
|
15
15
|
= submodel.model_name.human
|
|
@@ -97,10 +97,7 @@ module Para
|
|
|
97
97
|
# This is not the most optimized solution, but works well enough as if the
|
|
98
98
|
# author's posts match previously cloned posts, they won't be cloned as they'll
|
|
99
99
|
# exist in the cloned resources dictionary.
|
|
100
|
-
next if path
|
|
101
|
-
path[-4] == path[-2] &&
|
|
102
|
-
path[-2] == reflection_name &&
|
|
103
|
-
path[-3] == path[-1]
|
|
100
|
+
next if circular_reference?(path, reflection_name)
|
|
104
101
|
|
|
105
102
|
hash[reflection_name] = {}
|
|
106
103
|
|
|
@@ -140,6 +137,8 @@ module Para
|
|
|
140
137
|
options = nested_resource.class.try(:cloneable_options)
|
|
141
138
|
return reflection_options unless options
|
|
142
139
|
|
|
140
|
+
puts "Building cloneable options for #{nested_resource.class.name} at path #{path.join(' -> ')}"
|
|
141
|
+
|
|
143
142
|
target_options = build_cloneable_options_tree(nested_resource, path)
|
|
144
143
|
reflection_options.deep_merge!(target_options)
|
|
145
144
|
end
|
|
@@ -191,6 +190,43 @@ module Para
|
|
|
191
190
|
|
|
192
191
|
deep_relations.empty? ? shallow_relations : shallow_relations + [deep_relations]
|
|
193
192
|
end
|
|
193
|
+
|
|
194
|
+
# Checks if adding reflection_name to the path would create a circular reference
|
|
195
|
+
# of 2 levels deep with a cycle length between 2 and 10.
|
|
196
|
+
#
|
|
197
|
+
# Examples of detected patterns:
|
|
198
|
+
#
|
|
199
|
+
# Length 2: [:a, :b, :a, :b]
|
|
200
|
+
# Length 3: [:a, :b, :c, :a, :b, :c]
|
|
201
|
+
# Length 4: [:a, :b, :c, :d, :a, :b, :c, :d]
|
|
202
|
+
#
|
|
203
|
+
def circular_reference?(path, reflection_name)
|
|
204
|
+
# Check for cycle lengths from 2 to 10
|
|
205
|
+
(2..10).each do |cycle_length|
|
|
206
|
+
# We need at least 2 * cycle_length elements in the path to detect a cycle
|
|
207
|
+
required_length = cycle_length * 2
|
|
208
|
+
next if path.length < required_length
|
|
209
|
+
|
|
210
|
+
# Check if the pattern repeats exactly twice
|
|
211
|
+
# The new reflection_name would be at position -cycle_length
|
|
212
|
+
match = true
|
|
213
|
+
|
|
214
|
+
# First, check if the element at -cycle_length position matches reflection_name
|
|
215
|
+
next unless path[-cycle_length] == reflection_name
|
|
216
|
+
|
|
217
|
+
# Then check if all other elements in the first cycle match the second cycle
|
|
218
|
+
(1...cycle_length).each do |offset|
|
|
219
|
+
if path[-(cycle_length + offset)] != path[-offset]
|
|
220
|
+
match = false
|
|
221
|
+
break
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
return true if match
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
false
|
|
229
|
+
end
|
|
194
230
|
end
|
|
195
231
|
end
|
|
196
232
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Para
|
|
2
2
|
module FormBuilder
|
|
3
3
|
module AttributesMappingsTracker
|
|
4
|
-
def initialize(*)
|
|
4
|
+
def initialize(*) # :nodoc:
|
|
5
5
|
@attributes_mappings = {}
|
|
6
6
|
|
|
7
7
|
super
|
|
@@ -22,10 +22,9 @@ module Para
|
|
|
22
22
|
def fields_for(*args, &block)
|
|
23
23
|
fields_options = args.extract_options!
|
|
24
24
|
|
|
25
|
-
track_attribute_mappings =
|
|
25
|
+
track_attribute_mappings =
|
|
26
26
|
fields_options[:track_attribute_mappings] != false &&
|
|
27
27
|
options[:track_attribute_mappings]
|
|
28
|
-
)
|
|
29
28
|
|
|
30
29
|
fields_options.reverse_merge!(
|
|
31
30
|
track_attribute_mappings: track_attribute_mappings
|
|
@@ -42,7 +41,7 @@ module Para
|
|
|
42
41
|
return unless options[:track_attribute_mappings]
|
|
43
42
|
|
|
44
43
|
hidden_field :_attributes_mappings, value: @attributes_mappings.to_json,
|
|
45
|
-
|
|
44
|
+
data: { 'attributes-mappings': fields.options[:child_index] }
|
|
46
45
|
end
|
|
47
46
|
|
|
48
47
|
private
|
|
@@ -51,11 +50,11 @@ module Para
|
|
|
51
50
|
return unless options[:track_attribute_mappings]
|
|
52
51
|
|
|
53
52
|
type = if input_options[:as]
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
input_options[:as]
|
|
54
|
+
else
|
|
55
|
+
input = find_input(attribute_name, input_options, &block)
|
|
56
|
+
input.class.name.demodulize.underscore.gsub(/_input\z/, '')
|
|
57
|
+
end
|
|
59
58
|
|
|
60
59
|
@attributes_mappings[attribute_name] = type
|
|
61
60
|
end
|
data/lib/para/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: para
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.12.
|
|
4
|
+
version: 0.12.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Valentin Ballestrino
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: active_decorator
|
|
@@ -777,7 +776,6 @@ homepage: http://github.com/glyph-fr/para
|
|
|
777
776
|
licenses:
|
|
778
777
|
- MIT
|
|
779
778
|
metadata: {}
|
|
780
|
-
post_install_message:
|
|
781
779
|
rdoc_options: []
|
|
782
780
|
require_paths:
|
|
783
781
|
- lib
|
|
@@ -792,8 +790,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
792
790
|
- !ruby/object:Gem::Version
|
|
793
791
|
version: '0'
|
|
794
792
|
requirements: []
|
|
795
|
-
rubygems_version: 3.
|
|
796
|
-
signing_key:
|
|
793
|
+
rubygems_version: 3.6.9
|
|
797
794
|
specification_version: 4
|
|
798
795
|
summary: Rails admin engine
|
|
799
796
|
test_files: []
|