active_preview 0.1.1 → 0.1.2
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/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
|