poly_belongs_to 0.1.8 → 0.1.9

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
  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