clone_util 0.0.1

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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjM3YTg5OWQwYzcyMTA4YjRkYTg0YzNhYmIxN2FmNmJkMWQ5YTExYg==
5
+ data.tar.gz: !binary |-
6
+ MmUzNWViODhmZTM4YjZjYzYxOGQyZjRhYzMyZmI5YmVlYTgzMzQ3Yg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MjA4ZWJiMmM3Njg4MjU5NDk1OTgwOWJjYjdhOWVjYjgxOTE0YzFhZTkwNDI5
10
+ YzVjNTQxODhhYjZhZWMyOTk0ZDAzNDM5OGQ3YzIzNmU5YjliOTMxZjczNTlh
11
+ MTBlY2U3ZGVlZTRlNDY5YjVkZGQ3ZTYxMjQzOWY1YTUxZjRmMDQ=
12
+ data.tar.gz: !binary |-
13
+ NzMxZDRjZDQ3NWVjZDMwODFlOTM3M2M5YzkxMjk4MTJmZGI3ZTE0NDgwNmY4
14
+ NjAyMjQyNzA3ZWZmMDczODAyZGVkMDM2YmI1ZjFlNTc4NzNiNTExNDIyY2I5
15
+ NjkwZDhkNjFmNjViYTRmNjQ3ODJkOGVhOWJkYWM0MDEzMGM2ZGE=
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in clone_util.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # CloneUtil
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'clone_util'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install clone_util
18
+
19
+ ## Usage
20
+
21
+ #Call deep_clone with the parent object which should copy all its children
22
+ Ex: School.first.deep_clone
23
+
24
+ #Add deep_clone_options in the models which needs to be copied with the parent
25
+ Ex: deep_clone_options(:associations => [:departments, :laboratories])
26
+
27
+ Example:
28
+
29
+ Models:
30
+
31
+ class School < ActiveRecord::Base
32
+ has_many :laboratories
33
+ has_many :departments
34
+
35
+ deep_clone_options(:associations => [:departments, :laboratories])
36
+
37
+ def copy
38
+ self.deep_clone
39
+ end
40
+ end
41
+
42
+ class Laboratory < ActiveRecord::Base
43
+ belongs_to :school
44
+ belongs_to :department
45
+
46
+ deep_clone_options(:parent_id_att => [:school_id],
47
+ :equivalent_associations => [:department] )
48
+ end
49
+
50
+ class Department < ActiveRecord::Base
51
+ belongs_to :school
52
+ has_many :students
53
+
54
+ deep_clone_options(:parent_id_att => [:school_id],
55
+ :associations => [:students])
56
+ end
57
+
58
+ class Student < ActiveRecord::Base
59
+ belongs_to :department
60
+ end
61
+
62
+ Migrations:
63
+
64
+ class CreateSchools < ActiveRecord::Migration
65
+ def change
66
+ create_table :schools do |t|
67
+ t.string :name
68
+
69
+ t.timestamps null: false
70
+ end
71
+ end
72
+ end
73
+
74
+ class CreateLaboratories < ActiveRecord::Migration
75
+ def change
76
+ create_table :laboratories do |t|
77
+ t.string :name
78
+ t.integer :department_id
79
+ t.integer :school_id
80
+
81
+ t.timestamps null: false
82
+ end
83
+ end
84
+ end
85
+
86
+ class CreateDepartments < ActiveRecord::Migration
87
+ def change
88
+ create_table :departments do |t|
89
+ t.string :name
90
+ t.integer :school_id
91
+
92
+ t.timestamps null: false
93
+ end
94
+ end
95
+ end
96
+
97
+ class CreateStudents < ActiveRecord::Migration
98
+ def change
99
+ create_table :students do |t|
100
+ t.string :name
101
+ t.integer :age
102
+ t.integer :department_id
103
+
104
+ t.timestamps null: false
105
+ end
106
+ end
107
+ end
108
+
109
+ # Seed File:
110
+ School.create([{ name: 'school1'}])
111
+ Department.create([{ name: 'department1', :school_id => 1 }])
112
+ Laboratory.create([{ name: 'Lab1', :school_id => 1, :department_id => 1 }, { name: 'Lab2', :school_id => 1, :department_id => 1 }])
113
+ Student.create([{ name: 'student1', :department_id => 1 }, { name: 'student2', :department_id => 1 }])
114
+
115
+ Include the models and run the above migrations
116
+ Finally below command gives you the clone result
117
+
118
+ School.first.deep_clone
119
+
120
+
121
+ ## Contributing
122
+
123
+ 1. Fork it ( https://github.com/[my-github-username]/clone_util/fork )
124
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
125
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
126
+ 4. Push to the branch (`git push origin my-new-feature`)
127
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'clone_util/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "clone_util"
8
+ spec.version = CloneUtil::VERSION
9
+ spec.authors = "Srijith C"
10
+ spec.email = "srijithc038@gmail.com"
11
+ spec.summary = "Copy the ActiveRecord objects recursively"
12
+ spec.description = "This gem helps us to copy the ActiveRecord objects recursively"
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ end
data/lib/clone_util.rb ADDED
@@ -0,0 +1,122 @@
1
+ module ActiveRecord
2
+ class Base
3
+ def self.deep_clone_options(options={})
4
+ class_eval do
5
+
6
+ @clone_options = options
7
+
8
+ def self.allow_dup
9
+ @clone_options[:allow_dup]
10
+ end
11
+
12
+ def self.clone_info
13
+ @clone_options
14
+ end
15
+
16
+ def self.clone_associations
17
+ @clone_options[:associations]
18
+ end
19
+
20
+ def self.equivalent_associations
21
+ @clone_options[:equivalent_associations]
22
+ end
23
+
24
+ def self.unequal_attrs
25
+ unequal_attrs = ['id']
26
+ unequal_attrs.concat(@clone_options[:unequal_attributes]) if @clone_options[:unequal_attributes]
27
+ unequal_attrs
28
+ end
29
+
30
+ def self.ignore_attributes
31
+ ignore_attributes = ['created_at', 'updated_at', 'created_by_id', 'updated_by_id']
32
+ ignore_attributes << @clone_options[:parent_id_attr].first if @clone_options[:parent_id_attr]
33
+ ignore_attributes
34
+ end
35
+
36
+ def self.parent_id_attr
37
+ @clone_options[:parent_id_attr]
38
+ end
39
+
40
+ def deep_clone
41
+ recursive_clone
42
+ end
43
+
44
+ #TODO Should be private/protected
45
+ def recursive_clone(parent_object_id = nil,
46
+ clone_id_hash = {} )
47
+
48
+ self.transaction do
49
+ cloned_object = dup
50
+
51
+ unequal_attrs = self.class.clone_info[:unequal_attributes] || []
52
+ unequal_attrs.each do |a|
53
+ cloned_object.send("#{a.to_s}=", nil)
54
+ end
55
+
56
+ #Set parent object_id
57
+ if self.class.parent_id_attr and parent_object_id
58
+ cloned_object.send("#{self.class.parent_id_attr[0].to_s}=", parent_object_id)
59
+ end
60
+
61
+ begin
62
+ obj_attrs = cloned_object.attributes.clone
63
+ self.class.ignore_attributes.each { |a| obj_attrs.delete(a.to_s)}
64
+ if self.class.parent_id_attr and parent_object_id
65
+ obj_attrs["#{self.class.parent_id_attr[0].to_s}"] = parent_object_id
66
+ end
67
+
68
+ cloned_object.save!
69
+ clone_id_hash["#{self.class.table_name}_#{self.id}"] = cloned_object.id
70
+ rescue Exception => e
71
+ logger.info("deepclone: Clone save failed for " + cloned_object.inspect)
72
+ raise e
73
+ end
74
+
75
+ add_cloned_associations(cloned_object, clone_id_hash)
76
+ add_equivalent_associations(cloned_object, clone_id_hash)
77
+
78
+ clone_id_hash["#{self.class.table_name}_#{self.id}"] = cloned_object.id
79
+ cloned_object
80
+ end # transaction
81
+ end # recursive_clone
82
+
83
+ def add_equivalent_associations(cloned_object, clone_id_hash)
84
+ if self.class.equivalent_associations
85
+ self.class.equivalent_associations.each do |association|
86
+ assocn = self.class.reflect_on_association(association)
87
+ assocn_table_name = eval(assocn.class_name).table_name
88
+ assocn_id = send(assocn.foreign_key)
89
+ if assocn_id and (equivalent_id = clone_id_hash["#{assocn_table_name}_#{assocn_id}"])
90
+ cloned_object.send("#{assocn.foreign_key}=", equivalent_id)
91
+ end
92
+ end
93
+ cloned_object.save!
94
+ end
95
+ end
96
+
97
+ def add_cloned_associations(cloned_object, clone_id_hash)
98
+ if self.class.clone_associations
99
+ self.class.clone_associations.each do |association|
100
+ assocn = self.class.reflect_on_association(association)
101
+ if assocn.macro == :has_many
102
+ send(association).each do |obj|
103
+ c_obj = obj.respond_to?('deep_clone') ? obj.recursive_clone(cloned_object.id, clone_id_hash) : obj.dup
104
+ cloned_object.send(association) << c_obj unless c_obj.nil?
105
+ end
106
+ elsif assocn.macro == :has_and_belongs_to_many
107
+ cloned_object.send("#{association.to_s}=", send(association))
108
+ elsif (assocn.macro == :belongs_to) or (assocn.macro == :has_one)
109
+ source_obj = send(association)
110
+ unless source_obj.nil?
111
+ c_obj = source_obj.respond_to?('deep_clone') ? source_obj.recursive_clone(cloned_object.id, clone_id_hash) : source_obj.dup
112
+ cloned_object.send("#{association.to_s}=", c_obj) unless c_obj.nil?
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ end # class_eval
120
+ end # deep_clone_options
121
+ end # Base
122
+ end
@@ -0,0 +1,3 @@
1
+ module CloneUtil
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clone_util
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Srijith C
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: This gem helps us to copy the ActiveRecord objects recursively
42
+ email: srijithc038@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - LICENSE.txt
50
+ - README.md
51
+ - Rakefile
52
+ - clone_util.gemspec
53
+ - lib/clone_util.rb
54
+ - lib/clone_util/version.rb
55
+ homepage: ''
56
+ licenses:
57
+ - MIT
58
+ metadata: {}
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project:
75
+ rubygems_version: 2.2.2
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: Copy the ActiveRecord objects recursively
79
+ test_files: []