acts_as_edition 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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