acts_as_edition 1.0.0

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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 388edb3ce642edfbaf91712cc920565da99eeea0
4
+ data.tar.gz: 5e0c5d7465099a15ddd8da0af55acd76c43d391e
5
+ SHA512:
6
+ metadata.gz: e5a69c47e155918e75720f5ad38017d3f0fb1046df4089cdb248c5615f95bfbb0425cf1353b7c86857600a100bb3ed1d1cceafa8a7524e7a4a38f8dcf1edcb89
7
+ data.tar.gz: e7a587b15fe382e379e0e6f66f72d6592d7232ca4d25f524ab63f61c23b9cd64e097537d549a247028289d9f994f2b6a48389bca5a811a223c953ac6bdbd8535
data/.gitignore ADDED
@@ -0,0 +1,17 @@
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
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in acts_as_edition.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Virginia Department of Education
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,114 @@
1
+ ActsAsEdition
2
+ =============
3
+
4
+ acts_as_edition is a ruby gem for creating new editions of a tree (think
5
+ document) of ActiveRecord models.
6
+
7
+ Each new edition tree is a deep clone of the previous tree. The edition tree is
8
+ defined using an acts_as_edition declaration on each model in the tree. Using
9
+ the resources option, acts_as_edition supports management of relationships
10
+ between models in the edition tree and those outside it. A selection of hooks
11
+ provide additional control over the cloning process. Conditions can be
12
+ specified on models in the tree to determine when/if they are cloned. Finally,
13
+ each object in the tree maintains a simple belongs_to relationship with its
14
+ ancestor in the previous edition.
15
+
16
+ If you are considering acts_as_edition, you should also evaluate
17
+ acts_as_versioned and deep_cloning:
18
+
19
+ http://github.com/technoweenie/acts_as_versioned
20
+ http://github.com/DefV/deep_cloning
21
+
22
+ Install
23
+ =======
24
+
25
+ gem install acts_as_versioned
26
+
27
+ Example
28
+ =======
29
+
30
+ First, add ancestor_id column to every table in the tree, using a migration
31
+ thusly:
32
+
33
+ class AddEditionMigration < ActiveRecord::Migration
34
+ def self.up
35
+ add_column :mymodel, :ancestor_id, :integer
36
+ end
37
+
38
+ def self.down
39
+ remove_column :mymodel, :ancestor_id
40
+ end
41
+ end
42
+
43
+ rake db:migrate
44
+
45
+ Then declare acts_as_edition in the model class:
46
+
47
+ class Guide < ActiveRecord::Base
48
+ acts_as_edition :edition_chain => [:abbreviation, :imprint, :places],
49
+ :resources => [:country, :retailers, :authors],
50
+ :pre_hook => :unpublish_self,
51
+ :after_clone => :increment_descendant_year,
52
+ :post_hook => :publish_descendant
53
+ :conditions => { :returns_true => true }
54
+ has_one :abbreviation
55
+ belongs_to :imprint
56
+ has_many :places
57
+ has_one :country
58
+ has_many :retailers
59
+ has_and_belongs_to_many :authors
60
+
61
+ protected
62
+
63
+ def unpublish_self
64
+ self.published = false
65
+ self.save!
66
+ end
67
+
68
+ def increment_descendant_year
69
+ self.year = (self.year.to_i + 1).to_s
70
+ self.save!
71
+ end
72
+
73
+ def publish_descendant
74
+ self.descendant.published = true
75
+ self.descendant.save!
76
+ end
77
+
78
+ def returns_true
79
+ name != 'Noclonelandia'
80
+ end
81
+ end
82
+
83
+ class Abbreviation < ActiveRecord::Base
84
+ . . .
85
+ end
86
+
87
+ And so on -- these models are taken from the tests if you need more context.
88
+
89
+ To clone:
90
+
91
+ new_edition = Guide.first.clone_edition!
92
+ new_edition.ancestor # == Guide.first
93
+ Guide.first.descendant # == new_edition
94
+
95
+ Attributes listed in edition_chain are cloned. Note that their model classes
96
+ must also have acts_as_edition declarations.
97
+
98
+ Atributes listed in resources are not cloned. The relationship between these
99
+ resource objects and objects in the previous edition tree are reestablished in
100
+ the new edition tree. NOTE: the relatishionship of the resource to the original
101
+ object may be broken. The exception is resources in a habtm relationship with
102
+ edition objects. In these cases, the relationship to the new edition is
103
+ additive.
104
+
105
+ pre_hook and post_hook are called at the beginning and end of the process on
106
+ the original object. The after_clone hook is called *on the newly cloned
107
+ object* before it is saved to the database.
108
+
109
+ If an object does not meet all conditions specified in the conditions
110
+ options hash, clone_edition! on that object will return nil and the object will
111
+ not be copied into the new tree.
112
+
113
+ Copyright (c) 2010, 2013 Virginia Department of Education, released under the MIT
114
+ license
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rdoc/task'
5
+
6
+ desc 'Default: run unit tests.'
7
+ task :default => :test
8
+
9
+ desc 'Test the acts_as_edition plugin.'
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.libs << 'lib'
12
+ t.libs << 'test'
13
+ t.pattern = 'test/**/*_test.rb'
14
+ t.verbose = true
15
+ end
16
+
17
+ desc 'Generate documentation for the acts_as_edition plugin.'
18
+ Rake::RDocTask.new(:rdoc) do |rdoc|
19
+ rdoc.rdoc_dir = 'rdoc'
20
+ rdoc.title = 'ActsAsEdition'
21
+ rdoc.options << '--line-numbers' << '--inline-source'
22
+ rdoc.rdoc_files.include('README')
23
+ rdoc.rdoc_files.include('lib/**/*.rb')
24
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'acts_as_edition/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "acts_as_edition"
8
+ spec.version = ActsAsEdition::VERSION
9
+ spec.authors = ["Lee Capps"]
10
+ spec.email = ["himself@leecapps.com"]
11
+ spec.description = %q{Editions for ActiveRecord models}
12
+ spec.summary = %q{acts_as_edition is a ruby gem for creating new editions of trees of ActiveRecord objects.}
13
+ spec.homepage = "https://github.com/jlcapps/acts_as_edition"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency('activerecord', ["~> 3.2.13"])
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "sqlite3"
24
+ end
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'acts_as_edition'
2
+
3
+ ActiveRecord::Base.extend ActsAsEdition
@@ -0,0 +1,3 @@
1
+ module ActsAsEdition
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,95 @@
1
+ # ActsAsEdition
2
+ module ActsAsEdition
3
+ # :pre_hook and :post_hook run on the original object. :after_clone
4
+ # runs on the cloned object before it is saved.
5
+ # Attributes listed in :edition_chain are cloned and related to
6
+ # self.descendant. Those listed in :resources are related to the
7
+ # self.descendant and are otherwise left as is.
8
+ # NOTE: habtm realtionships are handled differently from other
9
+ # resources. For the resource, the change is additive. The resource
10
+ # will have a relationship with original *and* cloned edition object.
11
+ def acts_as_edition(options = {})
12
+ belongs_to :ancestor, :class_name => name, :foreign_key => :ancestor_id
13
+ has_one :descendant, :class_name => name, :foreign_key => :ancestor_id
14
+
15
+ cattr_accessor :edition_chain, :resources, :pre_hook, :after_clone,
16
+ :post_hook, :conditions
17
+ self.edition_chain = Array((options[:edition_chain] || []))
18
+ self.resources = Array((options[:resources] || []))
19
+ self.pre_hook = options[:pre_hook]
20
+ self.after_clone = options[:after_clone]
21
+ self.post_hook = options[:post_hook]
22
+ self.conditions = (options[:conditions] || {})
23
+
24
+ include InstanceMethods
25
+ end
26
+
27
+ module InstanceMethods
28
+ def clone_edition!
29
+ self.class.transaction do
30
+ self.send("#{self.pre_hook}") if self.pre_hook
31
+ cloned = ActiveRecord::VERSION::MAJOR==3 ? self.dup : self.clone
32
+ cloned.send("#{self.after_clone}") if self.after_clone
33
+ cloned.ancestor = self
34
+ cloned.save!
35
+ self.reload
36
+ clone_edition_chain
37
+ clone_resource_chain
38
+ self.send("#{self.post_hook}") if self.post_hook
39
+ cloned.save!
40
+ cloned.reload
41
+ end if aae_conditions_met
42
+ end
43
+
44
+ protected
45
+
46
+ def aae_conditions_met
47
+ self.conditions.keys.collect do |k|
48
+ self.send(k) == self.conditions[k]
49
+ end.all?
50
+ end
51
+
52
+ def clone_edition_chain
53
+ self.edition_chain.each do |association|
54
+ case self.class.reflect_on_association(association).macro
55
+ when :has_one, :belongs_to
56
+ cloned = (self.send(association) &&
57
+ (self.send(association).descendant ||
58
+ self.send(association).clone_edition!))
59
+ self.descendant.send("#{association}=", cloned) unless cloned.nil?
60
+ self.descendant.save!
61
+ when :has_many, :has_and_belongs_to_many
62
+ self.send(association) && self.send(association).each do |associated|
63
+ cloned = associated.descendant || associated.clone_edition!
64
+ unless (self.descendant.send("#{association}").include?(cloned) ||
65
+ cloned.nil?)
66
+ self.descendant.send("#{association}") << cloned
67
+ self.descendant.save!
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def clone_resource_chain
75
+ self.reload
76
+ self.resources.reject { |r| r.to_s.empty? }.each do |association|
77
+ case self.class.reflect_on_association(association).macro
78
+ when :has_one
79
+ resource = self.send(association)
80
+ self.descendant.send("#{association}=", resource)
81
+ self.descendant.save!
82
+ when :has_many, :has_and_belongs_to_many
83
+ resources = self.send(association)
84
+ resources.each do |resource|
85
+ self.descendant.send("#{association}") << resource
86
+ end
87
+ self.descendant.save!
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ ActiveRecord::Base.extend ActsAsEdition
95
+
@@ -0,0 +1,219 @@
1
+ require 'test_helper'
2
+
3
+ class ActsAsEditionTest < ActiveSupport::TestCase
4
+ fixtures :all
5
+
6
+ test "should respond to #ancestor" do
7
+ assert_respond_to Guide.new, :ancestor
8
+ end
9
+
10
+ test "should respond to #descendant" do
11
+ assert_respond_to Guide.new, :descendant
12
+ end
13
+
14
+ test "#ancestor and #descendant work as expected" do
15
+ guide = guides(:scotland)
16
+ cloned = guide.clone
17
+ cloned.ancestor = guide
18
+ cloned.save!
19
+ assert_equal cloned.ancestor, guide
20
+ assert_equal guide.descendant, cloned
21
+ end
22
+
23
+ test "should respond to #clone_edition!" do
24
+ assert_respond_to guides(:scotland), :clone_edition!
25
+ end
26
+
27
+ test "#clone_edition! clones edition" do
28
+ orig = guides(:scotland)
29
+ cloned = orig.clone_edition!
30
+ assert_equal cloned.ancestor, orig
31
+ assert_equal orig.descendant, cloned
32
+ assert_equal orig.name, cloned.name
33
+ end
34
+
35
+ test ":edition_chain and :resources options are stored as class attrs" do
36
+ assert_respond_to guides(:scotland), :edition_chain
37
+ assert guides(:scotland).edition_chain.include? :abbreviation
38
+ assert_respond_to Law.new, :resources
39
+ end
40
+
41
+ test ":conditions is stored as class attr" do
42
+ assert_respond_to guides(:scotland), :conditions
43
+ assert guides(:scotland).conditions.keys.include? :returns_true
44
+ end
45
+
46
+ test "should not clone if conditions not met" do
47
+ assert_equal guides(:noclonelandia).clone_edition!, nil
48
+ end
49
+
50
+ test "guide and abbreviation are properly related" do
51
+ assert_equal guides(:scotland).abbreviation, abbreviations(:sco)
52
+ end
53
+
54
+ test "should clone has_one specified in edition_chain" do
55
+ orig = guides(:scotland)
56
+ cloned = orig.clone_edition!
57
+ assert_equal orig.abbreviation, cloned.abbreviation.ancestor
58
+ assert_equal orig.abbreviation.descendant, cloned.abbreviation
59
+ end
60
+
61
+ test "should not clone has_one in edition_chain if conditions not met" do
62
+ orig = guides(:england)
63
+ cloned = orig.clone_edition!
64
+ assert_equal orig.abbreviation.descendant, nil
65
+ assert_equal cloned.abbreviation, nil
66
+ end
67
+
68
+ test "should clone belongs_to specified in edition_chain" do
69
+ orig = guides(:scotland)
70
+ cloned = orig.clone_edition!
71
+ orig.reload
72
+ cloned.reload
73
+ assert_equal orig.imprint, orig.descendant.imprint.ancestor
74
+ assert_equal cloned.imprint, orig.imprint.descendant
75
+ assert orig.imprint.descendant.guides.include? orig.descendant
76
+ end
77
+
78
+ test "should maintain belongs_to relationship in resources" do
79
+ orig = guides(:scotland)
80
+ cloned = orig.clone_edition!
81
+ orig.reload
82
+ cloned.reload
83
+ assert_equal orig.abbreviation.alphabet.id,
84
+ orig.descendant.abbreviation.alphabet.id
85
+ end
86
+
87
+ test "should clone has_manys specified in edition_chain" do
88
+ orig = guides(:scotland)
89
+ cloned = orig.clone_edition!
90
+ orig.reload
91
+ cloned.reload
92
+ orig.places.select { |p| p.cloneme? }.each do |place|
93
+ assert cloned.places.include? place.descendant
94
+ assert_equal place.descendant.guide, cloned
95
+ end
96
+ cloned.places.each do |place|
97
+ assert orig.places.include? place.ancestor
98
+ assert_equal place.ancestor.guide, orig
99
+ end
100
+ end
101
+
102
+ test "should not clone edition_chain has_manys if conditions not met" do
103
+ orig = guides(:scotland)
104
+ cloned = orig.clone_edition!
105
+ orig.reload
106
+ cloned.reload
107
+ assert_equal orig.places.count, cloned.places.count + 1
108
+ orig.places.select { |p| !p.cloneme? }.each do |place|
109
+ assert !cloned.places.include?(place)
110
+ end
111
+ end
112
+
113
+ test "should clone nested has_manys" do
114
+ orig = guides(:scotland)
115
+ cloned = orig.clone_edition!
116
+ orig.reload
117
+ cloned.reload
118
+ orig_maps_count = cloned_maps_count = 0
119
+ orig.places.each { |place| orig_maps_count += place.maps.count }
120
+ cloned.places.each { |place| cloned_maps_count += place.maps.count }
121
+ assert_equal orig_maps_count, cloned_maps_count
122
+ cloned.places.each do |place|
123
+ place.maps.each do |map|
124
+ assert place.ancestor.maps.include? map.ancestor
125
+ end
126
+ end
127
+ end
128
+
129
+ test "should clone has_and_belongs_to_manys specified in edition_chain" do
130
+ orig = guides(:scotland)
131
+ cloned = orig.clone_edition!
132
+ orig.reload
133
+ cloned.reload
134
+ orig_laws = cloned_laws = []
135
+ orig.places.each do |place|
136
+ orig_laws += place.laws.select { |l| l.cloneme? }
137
+ end
138
+ cloned.places.
139
+ each { |place| cloned_laws += place.laws.select { |l| l.cloneme? } }
140
+ assert_equal orig_laws.count, cloned_laws.count
141
+ orig_laws.each do |orig_law|
142
+ assert_equal 1, Law.find_all_by_ancestor_id(orig_law.id).count
143
+ assert !cloned_laws.include?(orig_law)
144
+ assert cloned_laws.include?(orig_law.descendant)
145
+ orig_law.places.each do |orig_place|
146
+ assert !orig_law.descendant.places.include?(orig_place)
147
+ end
148
+ end
149
+ cloned_laws.each do |cloned_law|
150
+ assert orig_laws.include?(cloned_law.ancestor)
151
+ end
152
+ end
153
+
154
+ test "should update relationship to has_ones spec'd in resources" do
155
+ # XXX this is a contrived case; would probably want to clone . . .
156
+ orig = guides(:scotland)
157
+ country = orig.country
158
+ cloned = orig.clone_edition!
159
+ orig.reload
160
+ cloned.reload
161
+ assert_equal orig.country, nil
162
+ assert_equal cloned.country, country
163
+ end
164
+
165
+ test "should updated relationship to has_manys spec'd in resources" do
166
+ orig = guides(:scotland)
167
+ retailer_ids = orig.retailers.collect { |r| r.id }
168
+ cloned = orig.clone_edition!
169
+ orig.reload
170
+ assert_equal 0, orig.retailers.count
171
+ assert_equal retailer_ids.count, cloned.retailers.count
172
+ cloned.retailers.each do |retailer|
173
+ assert retailer_ids.include?(retailer.id)
174
+ end
175
+ cloned_ids = cloned.retailers.collect { |r| r.id }
176
+ retailer_ids.each do |id|
177
+ assert cloned_ids.include?(id)
178
+ end
179
+ end
180
+
181
+ test "should update relationship to has_and_belongs_to_many resources" do
182
+ # habtm realtionships are handled differently from other resources.
183
+ # For the resource, the change is additive. The resource will have
184
+ # a relationship with original *and* cloned edition object.
185
+ orig = guides(:scotland)
186
+ author_ids = orig.authors.collect { |a| a.id }
187
+ cloned = orig.clone_edition!
188
+ orig.reload
189
+ assert_equal cloned.authors.count, orig.authors.count
190
+ assert_equal cloned.authors.first.guides.count, 2
191
+ orig.authors.each { |author| assert cloned.authors.include?(author) }
192
+ cloned.authors.each { |author| assert orig.authors.include?(author) }
193
+ end
194
+
195
+ test "should execute pre_hook" do
196
+ orig = guides(:scotland)
197
+ assert orig.published?
198
+ cloned = orig.clone_edition!
199
+ orig.reload
200
+ assert !orig.published?
201
+ end
202
+
203
+ test "should execute after_clone" do
204
+ orig = guides(:scotland)
205
+ orig_year = orig.year.to_i
206
+ cloned = orig.clone_edition!
207
+ orig.reload
208
+ assert_equal orig_year + 1, cloned.year.to_i
209
+ assert_equal orig.year.to_i, orig_year
210
+ end
211
+
212
+ test "should execute post_hook" do
213
+ orig = guides(:scotland)
214
+ cloned = orig.clone_edition!
215
+ orig.reload
216
+ assert !orig.published?
217
+ assert cloned.published?
218
+ end
219
+ end
data/test/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: ":memory:"
@@ -0,0 +1,6 @@
1
+ class Abbreviation < ActiveRecord::Base
2
+ acts_as_edition :resources => [:alphabet],
3
+ :conditions => { :cloneme? => true }
4
+ belongs_to :guide
5
+ belongs_to :alphabet
6
+ end
@@ -0,0 +1,11 @@
1
+ sco:
2
+ name: SCO
3
+ guide: scotland
4
+ alphabet: latin
5
+ cloneme: true
6
+
7
+ eng:
8
+ name: ENG
9
+ guide: england
10
+ alphabet: latin
11
+ cloneme: false
@@ -0,0 +1,2 @@
1
+ class Alphabet < ActiveRecord::Base
2
+ end
@@ -0,0 +1,2 @@
1
+ latin:
2
+ name: Latin
@@ -0,0 +1,3 @@
1
+ class Author < ActiveRecord::Base
2
+ has_and_belongs_to_many :guides
3
+ end
@@ -0,0 +1,8 @@
1
+ laura:
2
+ name: Laura
3
+
4
+ darren:
5
+ name: Darren
6
+
7
+ mary:
8
+ name: Mary
@@ -0,0 +1,3 @@
1
+ scotland_country:
2
+ name: Scotland
3
+ guide: scotland
@@ -0,0 +1,3 @@
1
+ class Retailer < ActiveRecord::Base
2
+ belongs_to :guide
3
+ end
@@ -0,0 +1,35 @@
1
+ class Guide < ActiveRecord::Base
2
+ acts_as_edition :edition_chain => [:abbreviation, :imprint, :places],
3
+ :resources => [:country, :retailers, :authors],
4
+ :pre_hook => :unpublish_self,
5
+ :after_clone => :increment_descendant_year,
6
+ :post_hook => :publish_descendant,
7
+ :conditions => { :returns_true => true }
8
+ has_one :abbreviation
9
+ belongs_to :imprint
10
+ has_many :places
11
+ has_one :country
12
+ has_many :retailers
13
+ has_and_belongs_to_many :authors
14
+
15
+ protected
16
+
17
+ def unpublish_self
18
+ self.published = false
19
+ self.save!
20
+ end
21
+
22
+ def increment_descendant_year
23
+ self.year = (self.year.to_i + 1).to_s
24
+ self.save!
25
+ end
26
+
27
+ def publish_descendant
28
+ self.descendant.published = true
29
+ self.descendant.save!
30
+ end
31
+
32
+ def returns_true
33
+ name != 'Noclonelandia'
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ scotland:
2
+ name: Scotland
3
+ imprint: fodors
4
+ published: true
5
+ year: 2009
6
+ authors: mary, darren, laura
7
+
8
+ noclonelandia:
9
+ name: Noclonelandia
10
+ imprint: fodors
11
+ published: true
12
+ year: 2009
13
+ authors: lee
14
+
15
+ england:
16
+ name: England
17
+ imprint: fodors
18
+ published: true
19
+ year: 2009
20
+ authors: peggy
@@ -0,0 +1,4 @@
1
+ class Imprint < ActiveRecord::Base
2
+ acts_as_edition
3
+ has_many :guides
4
+ end
@@ -0,0 +1,2 @@
1
+ fodors:
2
+ name: Fodors
@@ -0,0 +1,6 @@
1
+ class Law < ActiveRecord::Base
2
+ acts_as_edition :edition_chain => [], :resources => '',
3
+ :conditions => { :cloneme? => true }
4
+ has_and_belongs_to_many :places
5
+
6
+ end
@@ -0,0 +1,12 @@
1
+ edinburg_law:
2
+ name: No left on red
3
+ places: edinburgh
4
+
5
+ national:
6
+ name: Drive on the wrong side of the road
7
+ places: edinburgh, glasgow
8
+
9
+ common:
10
+ name: Common law
11
+ places: glasgow
12
+ cloneme: false
@@ -0,0 +1,4 @@
1
+ class Map < ActiveRecord::Base
2
+ acts_as_edition
3
+ belongs_to :place
4
+ end
@@ -0,0 +1,3 @@
1
+ hwy:
2
+ name: Highway Map
3
+ place: edinburgh
@@ -0,0 +1,7 @@
1
+ class Place < ActiveRecord::Base
2
+ acts_as_edition :edition_chain => [:maps, :laws],
3
+ :conditions => { :cloneme? => true }
4
+ belongs_to :guide
5
+ has_many :maps
6
+ has_and_belongs_to_many :laws
7
+ end
@@ -0,0 +1,12 @@
1
+ edinburgh:
2
+ name: Edinburgh
3
+ guide: scotland
4
+
5
+ glasgow:
6
+ name: Glasgow
7
+ guide: scotland
8
+
9
+ aberdeen:
10
+ name: Aberdeen
11
+ guide: scotland
12
+ cloneme: false
@@ -0,0 +1,3 @@
1
+ class Country < ActiveRecord::Base
2
+ belongs_to :guide
3
+ end
@@ -0,0 +1,7 @@
1
+ amazon:
2
+ name: Amazon UK
3
+ guide: scotland
4
+
5
+ waterstones:
6
+ name: "Waterstone's"
7
+ guide: scotland
data/test/schema.rb ADDED
@@ -0,0 +1,69 @@
1
+ ActiveRecord::Schema.define(:version => 1) do
2
+ create_table :guides, :force => true do |t|
3
+ t.column :name, :string
4
+ t.column :ancestor_id, :integer, :default => nil
5
+ t.column :imprint_id, :integer, :default => nil
6
+ t.column :published, :boolean, :default => false
7
+ t.column :year, :string
8
+ end
9
+
10
+ create_table :places, :force => true do |t|
11
+ t.column :name, :string
12
+ t.column :guide_id, :integer
13
+ t.column :ancestor_id, :integer, :default => nil
14
+ t.column :cloneme, :boolean, :default => true
15
+ end
16
+
17
+ create_table :laws, :force => true do |t|
18
+ t.column :name, :string
19
+ t.column :ancestor_id, :integer, :default => nil
20
+ t.column :cloneme, :boolean, :default => true
21
+ end
22
+
23
+ create_table "laws_places", :id => false, :force => true do |t|
24
+ t.integer "place_id"
25
+ t.integer "law_id"
26
+ end
27
+
28
+ create_table :maps, :force => true do |t|
29
+ t.column :name, :string
30
+ t.column :place_id, :integer
31
+ t.column :ancestor_id, :integer, :default => nil
32
+ end
33
+
34
+ create_table :alphabets, :force => true do |t|
35
+ t.column :name, :string
36
+ end
37
+
38
+ create_table :abbreviations, :force => true do |t|
39
+ t.column :name, :string
40
+ t.column :alphabet_id, :integer
41
+ t.column :guide_id, :integer
42
+ t.column :ancestor_id, :integer, :default => nil
43
+ t.column :cloneme, :boolean, :default => true
44
+ end
45
+
46
+ create_table :imprints, :force=> true do |t|
47
+ t.column :name, :string
48
+ t.column :ancestor_id, :integer, :default => nil
49
+ end
50
+
51
+ create_table :countries, :force=> true do |t|
52
+ t.column :name, :string
53
+ t.column :guide_id, :integer, :default => nil
54
+ end
55
+
56
+ create_table :retailers, :force=> true do |t|
57
+ t.column :name, :string
58
+ t.column :guide_id, :integer, :default => nil
59
+ end
60
+
61
+ create_table :authors, :force=> true do |t|
62
+ t.column :name, :string
63
+ end
64
+
65
+ create_table "authors_guides", :id => false, :force => true do |t|
66
+ t.integer "author_id"
67
+ t.integer "guide_id"
68
+ end
69
+ end
@@ -0,0 +1,38 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
2
+ RAILS_ROOT = File.dirname(__FILE__)
3
+
4
+ require 'active_record'
5
+ require 'active_record/fixtures'
6
+ require 'active_support'
7
+ require 'active_support/test_case'
8
+ require 'rubygems'
9
+ require 'test/unit'
10
+
11
+ require "#{File.dirname(__FILE__)}/../init"
12
+
13
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
14
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
15
+ ActiveRecord::Base.configurations = { "test" => config[ENV['DB'] || 'sqlite3'] }
16
+ ActiveRecord::Base.establish_connection(
17
+ ActiveRecord::Base.configurations['test']
18
+ )
19
+
20
+ load(File.dirname(__FILE__) + "/schema.rb")
21
+
22
+ class ActiveSupport::TestCase #:nodoc:
23
+ include ActiveRecord::TestFixtures
24
+ self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
25
+ $LOAD_PATH.unshift(self.fixture_path)
26
+ def create_fixtures(*table_names)
27
+ if block_given?
28
+ Fixtures.create_fixtures(self.fixture_path,
29
+ table_names
30
+ ) { yield }
31
+ else
32
+ Fixtures.create_fixtures(self.fixture_path, table_names)
33
+ end
34
+ end
35
+
36
+ self.use_transactional_fixtures = true
37
+ self.use_instantiated_fixtures = false
38
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_edition
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Lee Capps
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.13
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 3.2.13
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Editions for ActiveRecord models
70
+ email:
71
+ - himself@leecapps.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - MIT-LICENSE
79
+ - README
80
+ - Rakefile
81
+ - acts_as_edition.gemspec
82
+ - init.rb
83
+ - lib/acts_as_edition.rb
84
+ - lib/acts_as_edition/version.rb
85
+ - test/acts_as_edition_test.rb
86
+ - test/database.yml
87
+ - test/fixtures/abbreviation.rb
88
+ - test/fixtures/abbreviations.yml
89
+ - test/fixtures/alphabet.rb
90
+ - test/fixtures/alphabets.yml
91
+ - test/fixtures/author.rb
92
+ - test/fixtures/authors.yml
93
+ - test/fixtures/countries.yml
94
+ - test/fixtures/country.rb
95
+ - test/fixtures/guide.rb
96
+ - test/fixtures/guides.yml
97
+ - test/fixtures/imprint.rb
98
+ - test/fixtures/imprints.yml
99
+ - test/fixtures/law.rb
100
+ - test/fixtures/laws.yml
101
+ - test/fixtures/map.rb
102
+ - test/fixtures/maps.yml
103
+ - test/fixtures/place.rb
104
+ - test/fixtures/places.yml
105
+ - test/fixtures/retailer.rb
106
+ - test/fixtures/retailers.yml
107
+ - test/schema.rb
108
+ - test/test_helper.rb
109
+ homepage: https://github.com/jlcapps/acts_as_edition
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.0.0
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: acts_as_edition is a ruby gem for creating new editions of trees of ActiveRecord
133
+ objects.
134
+ test_files:
135
+ - test/acts_as_edition_test.rb
136
+ - test/database.yml
137
+ - test/fixtures/abbreviation.rb
138
+ - test/fixtures/abbreviations.yml
139
+ - test/fixtures/alphabet.rb
140
+ - test/fixtures/alphabets.yml
141
+ - test/fixtures/author.rb
142
+ - test/fixtures/authors.yml
143
+ - test/fixtures/countries.yml
144
+ - test/fixtures/country.rb
145
+ - test/fixtures/guide.rb
146
+ - test/fixtures/guides.yml
147
+ - test/fixtures/imprint.rb
148
+ - test/fixtures/imprints.yml
149
+ - test/fixtures/law.rb
150
+ - test/fixtures/laws.yml
151
+ - test/fixtures/map.rb
152
+ - test/fixtures/maps.yml
153
+ - test/fixtures/place.rb
154
+ - test/fixtures/places.yml
155
+ - test/fixtures/retailer.rb
156
+ - test/fixtures/retailers.yml
157
+ - test/schema.rb
158
+ - test/test_helper.rb