poly_belongs_to 0.1.8 → 0.1.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9fef63bc76533283e3fa03444fb55e430cbfed81
4
- data.tar.gz: d19cf96a1ad099257eb1396eb84587cd8e983965
3
+ metadata.gz: 2485663b8e0b1364a05b151975b527c56e95bada
4
+ data.tar.gz: 33338ae33151a22083b535ea79a706b237cf64aa
5
5
  SHA512:
6
- metadata.gz: 4f503a3cfc275e89ac94915d2b53fb5f4bba1d2c03fcdfda31da38112da9c211216b6f4505691cae6e5ee01d76df61d4d5b09de9a380026ef4a7fac5f70125a0
7
- data.tar.gz: ff310a8b501f3c21133f720eb55f2d66655ac9740370dd2b44e1eab0b27fbce1c946682e7c9a49e297fdb9d5192971ab159159235fed0f60af2b7e90fa512a1b
6
+ metadata.gz: 52ceb7ef74ed74c91012ae7ac3fa662da98653ee5258f538544911147ff873eaafad836b39bd095532ae28c79bbe07071ab62a7b636f4cc000a5748f69f0310c
7
+ data.tar.gz: 5c0e6bd0b258619346e12753beb23a15ea830f884d19eee585a137b692ac1309575dfc2c9e7f7e041794c3044fae8ab4facf597e29fc2ab2e6f712cc908f72d8
data/README.md CHANGED
@@ -144,25 +144,18 @@ otherwise**. You can duplicate a record, or use a self recursive command **pbt_
144
144
  to duplicate a record and all of it's has_one/has_many children records at once. Afterwards
145
145
  be sure to use the save method.
146
146
 
147
- > NOTE: This will need to be included manually. The reason for this is because you need to
148
- know what's involved when using this. It's purposefully done this way to lead to reading
149
- the documentation for PolyBelongsTo's duplication methods.
150
147
 
151
148
  ####Known Issues
152
149
  - Carrierwave records won't duplicate. To ensure that other records will still save and
153
150
  prevent any rollback issues use .save(validate: false) ... I'm considering possible options
154
151
  to remedy this and
155
152
  other scenarios.
156
- - For deep duplication you need to be very aware of the potential for infinite loops with
157
- your records if there are any circular references.
153
+ - **PROBLEM SOLVED** ~~For deep duplication you need to be very aware of the potential for infinite loops with
154
+ your records if there are any circular references.~~
158
155
 
159
156
  ###How To Use
160
157
 
161
- Include it into ActiveRecord::Base in an initializer /config/initializers/poly_belongs_to.rb
162
- ```ruby
163
- ActiveRecord::Base.send(:include, PolyBelongsTo::Dup)
164
- ```
165
- Then use the dup/build methods as follows
158
+ Use the dup/build methods as follows
166
159
 
167
160
  ```ruby
168
161
  # If you were to create a new contact for example
@@ -183,11 +176,6 @@ contact.pbt_deep_dup_build( User.last.profile )
183
176
  contact.save
184
177
  ```
185
178
 
186
- ##Planning
187
-
188
- I'm in the process of planning mapping out record hierarchy. Also with this
189
- it will add recognition for circular references.
190
-
191
179
  ##Contributing
192
180
 
193
181
  Feel free to fork and make pull requests. Please bring up an issue before a pull
@@ -2,103 +2,13 @@
2
2
  # The MIT License (MIT)
3
3
  # Copyright (C) 2015 by Daniel P. Clark
4
4
  $: << File.join(File.dirname(__FILE__), "/poly_belongs_to")
5
+ require 'active_support/concern'
5
6
  require 'poly_belongs_to/version'
7
+ require 'poly_belongs_to/core'
8
+ require 'poly_belongs_to/singleton_set'
6
9
  require 'poly_belongs_to/dup'
7
- require 'poly_belongs_to/poly_belongs_to'
10
+ require 'poly_belongs_to/pbt'
8
11
  require 'poly_belongs_to/faked_collection'
9
- require 'active_support/concern'
10
-
11
- module PolyBelongsTo
12
- module Core
13
- extend ActiveSupport::Concern
14
-
15
- included do
16
- def self.pbt
17
- reflect_on_all_associations(:belongs_to).first.try(:name)
18
- end
19
-
20
- def self.pbts
21
- reflect_on_all_associations(:belongs_to).map(&:name)
22
- end
23
-
24
- def self.poly?
25
- !!reflect_on_all_associations(:belongs_to).first.try {|i| i.options[:polymorphic] }
26
- end
27
-
28
- def self.pbt_params_name(allow_as_nested = true)
29
- if poly?
30
- allow_as_nested ? "#{table_name}_attributes".to_sym : name.downcase.to_sym
31
- else
32
- name.downcase.to_sym
33
- end
34
- end
35
-
36
- def self.pbt_id_sym
37
- val = pbt
38
- val ? "#{val}_id".to_sym : nil
39
- end
40
-
41
- def self.pbt_type_sym
42
- poly? ? "#{pbt}_type".to_sym : nil
43
- end
44
- end
45
-
46
- def pbt
47
- self.class.pbt
48
- end
49
-
50
- def pbts
51
- self.class.pbts
52
- end
53
-
54
- def poly?
55
- self.class.poly?
56
- end
57
-
58
- def pbt_id
59
- val = pbt
60
- val ? eval("self.#{val}_id") : nil
61
- end
62
-
63
- def pbt_type
64
- poly? ? eval("self.#{pbt}_type") : nil
65
- end
66
-
67
- def pbt_parent
68
- val = pbt
69
- if val
70
- if poly?
71
- eval "#{pbt_type}.find(#{pbt_id})"
72
- else
73
- eval "#{val.capitalize.to_s}.find(#{pbt_id})"
74
- end
75
- else
76
- nil
77
- end
78
- end
79
-
80
- def pbt_parents
81
- if poly?
82
- Array[pbt_parent].compact
83
- else
84
- self.class.pbts.map {|i|
85
- try{ eval("#{i.capitalize}").find eval("self.#{i}_id") }
86
- }.compact
87
- end
88
- end
89
-
90
- def pbt_id_sym
91
- self.class.pbt_id_sym
92
- end
93
-
94
- def pbt_type_sym
95
- self.class.pbt_type_sym
96
- end
97
-
98
- def pbt_params_name(allow_as_nested = true)
99
- self.class.pbt_params_name(allow_as_nested)
100
- end
101
- end
102
- end
12
+ ActiveRecord::Base.send(:include, PolyBelongsTo::Core )
13
+ ActiveRecord::Base.send(:include, PolyBelongsTo::Dup )
103
14
 
104
- ActiveRecord::Base.send(:include, PolyBelongsTo::Core)
@@ -0,0 +1,92 @@
1
+ module PolyBelongsTo
2
+ module Core
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ def self.pbt
7
+ reflect_on_all_associations(:belongs_to).first.try(:name)
8
+ end
9
+
10
+ def self.pbts
11
+ reflect_on_all_associations(:belongs_to).map(&:name)
12
+ end
13
+
14
+ def self.poly?
15
+ !!reflect_on_all_associations(:belongs_to).first.try {|i| i.options[:polymorphic] }
16
+ end
17
+
18
+ def self.pbt_params_name(allow_as_nested = true)
19
+ if poly?
20
+ allow_as_nested ? "#{table_name}_attributes".to_sym : name.downcase.to_sym
21
+ else
22
+ name.downcase.to_sym
23
+ end
24
+ end
25
+
26
+ def self.pbt_id_sym
27
+ val = pbt
28
+ val ? "#{val}_id".to_sym : nil
29
+ end
30
+
31
+ def self.pbt_type_sym
32
+ poly? ? "#{pbt}_type".to_sym : nil
33
+ end
34
+ end
35
+
36
+ def pbt
37
+ self.class.pbt
38
+ end
39
+
40
+ def pbts
41
+ self.class.pbts
42
+ end
43
+
44
+ def poly?
45
+ self.class.poly?
46
+ end
47
+
48
+ def pbt_id
49
+ val = pbt
50
+ val ? self.send("#{val}_id") : nil
51
+ end
52
+
53
+ def pbt_type
54
+ poly? ? self.send("#{pbt}_type") : nil
55
+ end
56
+
57
+ def pbt_parent
58
+ val = pbt
59
+ if val
60
+ if poly?
61
+ "#{pbt_type}".constantize.find(pbt_id)
62
+ else
63
+ "#{val.capitalize}".constantize.find(pbt_id)
64
+ end
65
+ else
66
+ nil
67
+ end
68
+ end
69
+
70
+ def pbt_parents
71
+ if poly?
72
+ Array[pbt_parent].compact
73
+ else
74
+ self.class.pbts.map {|i|
75
+ try{ "#{i.capitalize}".constantize.find(self.send("#{i}_id")) }
76
+ }.compact
77
+ end
78
+ end
79
+
80
+ def pbt_id_sym
81
+ self.class.pbt_id_sym
82
+ end
83
+
84
+ def pbt_type_sym
85
+ self.class.pbt_type_sym
86
+ end
87
+
88
+ def pbt_params_name(allow_as_nested = true)
89
+ self.class.pbt_params_name(allow_as_nested)
90
+ end
91
+ end
92
+ end
@@ -4,34 +4,37 @@ module PolyBelongsTo
4
4
 
5
5
  included do
6
6
  def self.pbt_dup_build(item_to_build_on, item_to_duplicate)
7
+ singleton_record = yield if block_given?
7
8
  if PolyBelongsTo::Pbt::IsReflected[item_to_build_on, item_to_duplicate]
8
9
  PolyBelongsTo::Pbt::AsCollectionProxy[item_to_build_on, item_to_duplicate].
9
- build PolyBelongsTo::Pbt::AttrSanitizer[item_to_duplicate]
10
+ build PolyBelongsTo::Pbt::AttrSanitizer[item_to_duplicate] if (
11
+ block_given? ? singleton_record.add?(item_to_duplicate) : true)
10
12
  end
11
13
  end
12
14
 
13
15
  def self.pbt_deep_dup_build(item_to_build_on, item_to_duplicate)
14
- pbt_dup_build(item_to_build_on, item_to_duplicate)
16
+ singleton_record = (block_given? ? yield : PolyBelongsTo::SingletonSet.new)
17
+ pbt_dup_build(item_to_build_on, item_to_duplicate) {singleton_record}
15
18
  PolyBelongsTo::Pbt::Reflects[item_to_duplicate].each do |ref|
16
- child = eval("item_to_duplicate.#{ref}")
19
+ child = item_to_duplicate.send(ref)
17
20
  PolyBelongsTo::Pbt::AsCollectionProxy[item_to_build_on, item_to_duplicate].
18
21
  each do |builder|
19
22
  child.respond_to?(:build) ? child.each {|spawn|
20
- builder.pbt_deep_dup_build(spawn)
21
- } : builder.pbt_deep_dup_build(child)
22
- end
23
+ builder.pbt_deep_dup_build(spawn) {singleton_record}
24
+ } : builder.pbt_deep_dup_build(child) {singleton_record}
25
+ end unless singleton_record.include?(item_to_build_on)
23
26
  end
24
27
  item_to_build_on
25
28
  end
26
29
 
27
30
  end
28
31
 
29
- def pbt_dup_build(item_to_duplicate)
30
- self.class.pbt_dup_build(self, item_to_duplicate)
32
+ def pbt_dup_build(item_to_duplicate, &block)
33
+ self.class.pbt_dup_build(self, item_to_duplicate, &block)
31
34
  end
32
35
 
33
- def pbt_deep_dup_build(item_to_duplicate)
34
- self.class.pbt_deep_dup_build(self, item_to_duplicate)
36
+ def pbt_deep_dup_build(item_to_duplicate, &block)
37
+ self.class.pbt_deep_dup_build(self, item_to_duplicate, &block)
35
38
  end
36
39
 
37
40
  end
@@ -4,10 +4,14 @@ module PolyBelongsTo
4
4
  raise "Not a has_one rleationship for FakedCollection" unless PolyBelongsTo::Pbt::IsSingular[obj,child]
5
5
  @obj = obj
6
6
  @child = child
7
- @instance = eval("@obj.#{PolyBelongsTo::Pbt::CollectionProxy[@obj,@child]}")
7
+ @instance = @obj.send(PolyBelongsTo::Pbt::CollectionProxy[@obj,@child])
8
8
  self
9
9
  end
10
10
 
11
+ def id
12
+ @instance.try(:id)
13
+ end
14
+
11
15
  def all
12
16
  Array[@instance].compact
13
17
  end
@@ -45,7 +49,7 @@ module PolyBelongsTo
45
49
  end
46
50
 
47
51
  def build(*args)
48
- @instance = eval("@obj.#{PolyBelongsTo::Pbt::BuildCmd[@obj, @child]}(#{args.join(',')})")
52
+ @instance = @obj.send(PolyBelongsTo::Pbt::BuildCmd[@obj, @child], *args)
49
53
  self
50
54
  end
51
55
 
@@ -9,25 +9,25 @@ module PolyBelongsTo
9
9
 
10
10
  BuildCmd = lambda {|obj, child|
11
11
  return nil unless obj && child
12
- dup_name = "#{CollectionProxy[obj,child]}"
12
+ dup_name = CollectionProxy[obj, child]
13
13
  IsSingular[obj, child] ? "build_#{dup_name}" : IsPlural[obj, child] ? "#{dup_name}.build" : nil
14
14
  }
15
15
 
16
16
  Reflects = lambda {|obj|
17
17
  return [] unless obj
18
18
  [:has_one, :has_many].map { |has|
19
- eval(obj.class.name).reflect_on_all_associations(has).map(&:name).map(&:to_sym)
19
+ obj.class.name.constantize.reflect_on_all_associations(has).map(&:name).map(&:to_sym)
20
20
  }.flatten
21
21
  }
22
22
 
23
23
  ReflectsAsClasses = lambda {|obj|
24
24
  Reflects[obj].map {|ref|
25
- eval (eval("obj.#{ref}").try(:klass) || eval("obj.#{ref}").class).name
25
+ (obj.send(ref).try(:klass) || obj.send(ref).class).name.constantize
26
26
  }
27
27
  }
28
28
 
29
- IsReflected = lambda {|obj,child|
30
- !!SingularOrPlural[obj, child]
29
+ IsReflected = lambda {|obj, child|
30
+ !!CollectionProxy[obj, child]
31
31
  }
32
32
 
33
33
  SingularOrPlural = lambda {|obj, child|
@@ -35,7 +35,7 @@ module PolyBelongsTo
35
35
  reflects = Reflects[obj]
36
36
  if reflects.include?(ActiveModel::Naming.singular(child).to_sym)
37
37
  :singular
38
- elsif reflects.include?(ActiveModel::Naming.plural(child).to_sym)
38
+ elsif CollectionProxy[obj, child]
39
39
  :plural
40
40
  else
41
41
  nil
@@ -52,20 +52,14 @@ module PolyBelongsTo
52
52
 
53
53
  CollectionProxy = lambda {|obj, child|
54
54
  return nil unless obj && child
55
- reflects = Reflects[obj]
56
- proxy = ActiveModel::Naming.singular(child).to_sym
57
- return proxy if reflects.include? proxy
58
- proxy = ActiveModel::Naming.plural(child).to_sym
59
- reflects.include?(proxy) ? proxy : nil
55
+ names = [ActiveModel::Naming.singular(child).to_s, ActiveModel::Naming.plural(child).to_s].uniq
56
+ Reflects[obj].detect {|ref| "#{ref}"[/(?:#{ names.join('|') }).{,3}/]}
60
57
  }
61
58
 
62
59
  AsCollectionProxy = lambda {|obj, child|
63
60
  return [] unless obj && child
64
- reflects = Reflects[obj]
65
- proxy = ActiveModel::Naming.singular(child).to_sym
66
- return PolyBelongsTo::FakedCollection.new(obj, child) if reflects.include? proxy
67
- proxy = ActiveModel::Naming.plural(child).to_sym
68
- reflects.include?(proxy) ? eval("obj.#{PolyBelongsTo::Pbt::CollectionProxy[obj, child]}") : []
61
+ return PolyBelongsTo::FakedCollection.new(obj, child) if IsSingular[obj, child]
62
+ !!CollectionProxy[obj, child] ? obj.send(PolyBelongsTo::Pbt::CollectionProxy[obj, child]) : []
69
63
  }
70
64
  end
71
65
 
@@ -0,0 +1,45 @@
1
+ require 'set'
2
+ module PolyBelongsTo
3
+ class SingletonSet
4
+ def initialize
5
+ @set = Set.new
6
+ @flagged = Set.new
7
+ self
8
+ end
9
+
10
+ def formatted_name(record)
11
+ "#{record.class.name}-#{record.id}"
12
+ end
13
+
14
+ def add?(record)
15
+ result = @set.add?( formatted_name( record ) )
16
+ return result if result
17
+ flag(record)
18
+ result
19
+ end
20
+
21
+ def add(record)
22
+ add?(record)
23
+ end
24
+
25
+ def <<(record)
26
+ add?(record)
27
+ end
28
+
29
+ def include?(record)
30
+ @set.include?(formatted_name(record))
31
+ end
32
+
33
+ def flag(record)
34
+ @flagged << formatted_name(record)
35
+ end
36
+
37
+ def flagged?(record)
38
+ @flagged.include?(formatted_name(record))
39
+ end
40
+
41
+ def method_missing(mthd)
42
+ @set.send(mthd)
43
+ end
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
1
  module PolyBelongsTo
2
- VERSION = "0.1.8"
2
+ VERSION = "0.1.9"
3
3
  end