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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3064d283634c7dac6ebd82658a795efc68b5e097732cb8cdcef8c3bc0bf9bdaf
4
- data.tar.gz: f30d54a086aa9ecc8804ec882980152492e4093ae90072832b9fde027104ed84
3
+ metadata.gz: 889b89b88ed0233e99903e3476854a4ac7b0b0c0d46da07df3f6a5221bcb57d7
4
+ data.tar.gz: 4396bc99b473040e8e01997874d59219b06e81a5a37fce73f48e9abdc26747b1
5
5
  SHA512:
6
- metadata.gz: e987815ad60a34626e10a82eeee2843bc8952110f992955dd04d6e70bceb60b38c85c025b8057824b4cdb21a1696b3b1ec6c1d8be0ace5dd6e0e9fe7b8841137
7
- data.tar.gz: 560b7ecf7d57496750aa0a1bce9c2845cd2cc6e9f90786e0943674e03de22b22329ad45717d1f4c462f642a7b0fcbcd1822e243304bd1081d35d0e9f42827643
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 association_class(klass:, key:)
11
- klass.reflect_on_association(association_from_key(key)).klass
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 original
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(:attr_accessor, a)
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
- merged_object(params).tap do |p|
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
@@ -1,3 +1,3 @@
1
1
  module ActivePreview
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -1,7 +1,8 @@
1
1
  require "active_preview/association_helper"
2
+ require "active_preview/batch_builder"
3
+ require "active_preview/builder"
2
4
  require "active_preview/preview"
3
5
  require "active_preview/previewing"
4
6
 
5
7
  module ActivePreview
6
- # Your code goes here...
7
8
  end
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.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-05 00:00:00.000000000 Z
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