active_preview 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/active_preview/association_helper.rb +14 -2
- data/lib/active_preview/batch_builder.rb +35 -0
- data/lib/active_preview/builder.rb +84 -0
- data/lib/active_preview/preview.rb +9 -3
- data/lib/active_preview/previewing.rb +1 -58
- data/lib/active_preview/version.rb +1 -1
- data/lib/active_preview.rb +2 -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: 889b89b88ed0233e99903e3476854a4ac7b0b0c0d46da07df3f6a5221bcb57d7
|
4
|
+
data.tar.gz: 4396bc99b473040e8e01997874d59219b06e81a5a37fce73f48e9abdc26747b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7018167fdb991cdd0b1a35e9e8977cdea558fe752f30ea95ea02ecfb6c7cce4311b332670158cc9d14dda12078d7988e3b5ea6ccf78014be314c6a0fa4906dde
|
7
|
+
data.tar.gz: 9b14a4d453741b1519724a7c3d9fa0492c3c6cef05f973a4f12f940cbcedfd6898a5cde168be8a2a59fa14c3af5c094f1160919a7cabe3d45f07e0c1d1e4cf21
|
@@ -7,8 +7,20 @@ module AssociationHelper
|
|
7
7
|
klass.reflect_on_all_associations.map { |a| a.name.to_s }
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
|
10
|
+
def class_of_association(base_class:, key: nil, association: nil)
|
11
|
+
association = association_from_key(key) if key
|
12
|
+
klass.reflect_on_association(association).klass
|
13
|
+
end
|
14
|
+
|
15
|
+
# Used to properly set parent in has_many previews
|
16
|
+
def association_inverse(parent_class:, child_class:)
|
17
|
+
parent = parent_class.to_s.downcase
|
18
|
+
set = associations(child_class)
|
19
|
+
return parent if set.include? parent
|
20
|
+
set.each do |a|
|
21
|
+
next unless singular? a
|
22
|
+
return a if association_class(klass: child_class, association: a)
|
23
|
+
end
|
12
24
|
end
|
13
25
|
|
14
26
|
def singular?(name)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ActivePreview
|
2
|
+
class BatchBuilder
|
3
|
+
def self.build(**args)
|
4
|
+
new(**args).build
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(klass:, saved_models:, params: nil, parent: nil)
|
8
|
+
@klass = klass
|
9
|
+
@saved_models = saved_models
|
10
|
+
@params_set = params
|
11
|
+
@parent = parent
|
12
|
+
end
|
13
|
+
|
14
|
+
def build
|
15
|
+
objects_with_new_attrs.map do |obj, attrs|
|
16
|
+
obj ||= klass.new
|
17
|
+
attrs ||= {}
|
18
|
+
Builder.build(model: obj, params: attrs, parent: parent)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :klass, :saved_models, :params_set, :parent
|
25
|
+
|
26
|
+
def objects_with_new_attrs
|
27
|
+
return saved_models unless params_set
|
28
|
+
if saved_models.size > params_set.size
|
29
|
+
saved_models.zip(params_set)
|
30
|
+
else
|
31
|
+
params_set.zip(saved_models).map(&:reverse!)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module ActivePreview
|
2
|
+
class Builder
|
3
|
+
include AssociationHelper
|
4
|
+
|
5
|
+
def self.build(**args)
|
6
|
+
new(**args).build
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(model:, params: {}, parent: nil)
|
10
|
+
@model = model
|
11
|
+
@params = params
|
12
|
+
@klass = model.class
|
13
|
+
@parent = parent
|
14
|
+
end
|
15
|
+
|
16
|
+
def build
|
17
|
+
build_preview_object
|
18
|
+
update_associations
|
19
|
+
associate_parent
|
20
|
+
load_associations
|
21
|
+
return preview
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :model, :params, :klass, :preview, :updated_associations,
|
27
|
+
:parent
|
28
|
+
|
29
|
+
def build_preview_object
|
30
|
+
@preview ||= preview_class.new(klass.new(model.attributes.merge(params)))
|
31
|
+
end
|
32
|
+
|
33
|
+
def preview_class
|
34
|
+
"#{klass}Preview".constantize
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_associations
|
38
|
+
@updated_associations ||= child_params_keys.map do |params_key|
|
39
|
+
association_from_key(params_key).tap do |a|
|
40
|
+
preview.send("#{a}=", build_children(params_key, a))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def child_params_keys
|
46
|
+
@child_params_keys ||= params.map do |k, _|
|
47
|
+
a = association_from_key(k)
|
48
|
+
# TODO: singular associations
|
49
|
+
k if associations(klass).include?(a) && !singular?(a)
|
50
|
+
end.compact
|
51
|
+
end
|
52
|
+
|
53
|
+
def build_children(params_key, association)
|
54
|
+
child_params = params[params_key].to_h.values
|
55
|
+
.sort! { |a, b| a["id"] <=> b["id"] }
|
56
|
+
saved = model.send(association).order(:id)
|
57
|
+
child_klass = class_of_association(base_class: klass,
|
58
|
+
association: association)
|
59
|
+
BatchPreviewBuilder.build(klass: child_klass, saved_models: saved,
|
60
|
+
params: child_params, parent: preview)
|
61
|
+
end
|
62
|
+
|
63
|
+
def associate_parent
|
64
|
+
return unless parent
|
65
|
+
association = association_inverse(parent_class: parent.model_object.class,
|
66
|
+
child_class: klass)
|
67
|
+
preview.send("#{association}=", parent)
|
68
|
+
@updated_associations << association
|
69
|
+
end
|
70
|
+
|
71
|
+
def load_associations
|
72
|
+
associations(klass).each do |a|
|
73
|
+
next if updated_associations.include?(a)
|
74
|
+
saved = [*model.send(a)]
|
75
|
+
next if saved.empty?
|
76
|
+
to_assign = BatchPreviewBuilder.build(klass: saved.first.class,
|
77
|
+
saved_models: saved,
|
78
|
+
parent: preview)
|
79
|
+
to_assign = to_assign.first if singular? a
|
80
|
+
preview.send("#{a}=", to_assign)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -10,7 +10,7 @@ module ActivePreview
|
|
10
10
|
super(record)
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
13
|
+
def model_object
|
14
14
|
__getobj__
|
15
15
|
end
|
16
16
|
|
@@ -22,12 +22,18 @@ module ActivePreview
|
|
22
22
|
|
23
23
|
def redefine_associations(record)
|
24
24
|
associations(record.class).each do |a|
|
25
|
-
next if respond_to? a # avoid redefining methods
|
25
|
+
next if respond_to? "#{a}=" # avoid redefining methods
|
26
26
|
methods = singular?(a) ? SINGULAR : COLLECTION
|
27
27
|
methods.each do |method|
|
28
28
|
self.class.send(:define_method, method.gsub("~", a)) {}
|
29
29
|
end
|
30
|
-
self.class.send(:
|
30
|
+
self.class.send(:define_method, "#{a}=") do |associated|
|
31
|
+
instance_variable_set("@#{a}", associated)
|
32
|
+
unless instance_variable_get("@#{a}_defined")
|
33
|
+
define_singleton_method(a) { instance_variable_get "@#{a}" }
|
34
|
+
instance_variable_set("@#{a}_defined", true)
|
35
|
+
end
|
36
|
+
end
|
31
37
|
end
|
32
38
|
end
|
33
39
|
end
|
@@ -1,66 +1,9 @@
|
|
1
1
|
module ActivePreview
|
2
2
|
module Previewing
|
3
3
|
extend ActiveSupport::Concern
|
4
|
-
include AssociationHelper
|
5
4
|
|
6
|
-
included do
|
7
|
-
def self.collection_preview(saved, params)
|
8
|
-
child_args(saved, params).map do |obj, attrs|
|
9
|
-
if obj
|
10
|
-
obj.preview(attrs)
|
11
|
-
else
|
12
|
-
self.new(attrs).preview
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def self.child_args(saved, child_attrs)
|
20
|
-
if saved.size > child_attrs.size
|
21
|
-
saved.zip(child_attrs)
|
22
|
-
else
|
23
|
-
child_attrs.zip(saved).map(&:reverse!)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Returns an unsaved object with updated attributes, along with any
|
29
|
-
# child objects and their updated attributes.
|
30
|
-
# Note that the associations are not assigned, so parent.children will be
|
31
|
-
# empty
|
32
5
|
def preview(params)
|
33
|
-
|
34
|
-
child_keys(params).each do |params_key|
|
35
|
-
association = association_from_key(params_key)
|
36
|
-
next unless associations(self.class).include?(association)
|
37
|
-
p.send("#{association}=", generate_children(params, params_key))
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def merged_object(new_attrs)
|
45
|
-
preview_class.new(self.class.new(self.attributes.merge(new_attrs)))
|
46
|
-
end
|
47
|
-
|
48
|
-
def preview_class
|
49
|
-
"#{self.class}Preview".constantize
|
50
|
-
end
|
51
|
-
|
52
|
-
def child_keys(hash)
|
53
|
-
hash.map do |k, v|
|
54
|
-
k if v.is_a?(ActionController::Parameters) || v.is_a?(Hash)
|
55
|
-
end.compact
|
56
|
-
end
|
57
|
-
|
58
|
-
def generate_children(params, *params_keys)
|
59
|
-
child_params = params.dig(*params_keys).to_h.values
|
60
|
-
.sort! { |a, b| a["id"] <=> b["id"] }
|
61
|
-
klass = association_class(klass: self.class, key: params_keys.last)
|
62
|
-
saved = klass.where(id: child_params.map { |p| p["id"] }).order(:id)
|
63
|
-
klass.collection_preview(saved, child_params)
|
6
|
+
PreviewBuilder.build(model: self, params: params)
|
64
7
|
end
|
65
8
|
end
|
66
9
|
end
|
data/lib/active_preview.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_preview
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Syd Young
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -133,6 +133,8 @@ files:
|
|
133
133
|
- Rakefile
|
134
134
|
- lib/active_preview.rb
|
135
135
|
- lib/active_preview/association_helper.rb
|
136
|
+
- lib/active_preview/batch_builder.rb
|
137
|
+
- lib/active_preview/builder.rb
|
136
138
|
- lib/active_preview/override_persistence.rb
|
137
139
|
- lib/active_preview/preview.rb
|
138
140
|
- lib/active_preview/previewing.rb
|