Skip to content
Browse files

Moving ActsAsArchive configuration to YAML file (config/acts_as_archi…

…ve.yml)
  • Loading branch information...
1 parent bb9f9ef commit dd7b490be0e2e5960d76b2bbd8e984ce531c0a7b @winton committed
View
28 README.md
@@ -32,23 +32,29 @@ gem 'acts_as_archive'
<pre>
require 'acts_as_archive'
-</pre>
-Add to models
--------------
+class Application &lt; Sinatra::Base
+ include ActsAsArchive::Adapters::Sinatra
+end
+</pre>
-Add <code>acts\_as\_archive</code> to your models:
+config/acts\_as\_archive.yml
+----------------------------
<pre>
-class Article &lt; ActiveRecord::Base
- acts_as_archive
-end
+Article:
+ - class: Article::Archive
+ table: archived_articles
</pre>
+Specify the name of your model, the name of the archive class, and the name of the archive table.
+
+If the archive model is created automatically if it does not exist.
+
Migrate
-------
-Next time you run <code>rake db:migrate</code>, your archive tables will be created automatically.
+Run <code>rake db:migrate</code>. Your archive table is created automatically.
That's it!
----------
@@ -60,9 +66,7 @@ Records move into the archive table instead of being destroyed.
Automatically archive relationships
-----------------------------------
-If your <code>acts\_as\_archive</code> model's relationship has the <code>:dependent</code> option and also uses <code>acts\_as\_archive</code>, that relationship will archive automatically.
-
-__To use this feature, you must declare your relationships before the <code>acts\_as\_archive</code> call within your model!__
+If your model's relationship has the <code>:dependent</code> option, and the relationship also uses <code>acts\_as\_archive</code>, that relationship will archive automatically.
What if my schema changes?
--------------------------
@@ -74,7 +78,7 @@ No action is necessary on your part.
Query the archive
-----------------
-Add <code>::Archive</code> to your ActiveRecord class:
+Use the Archive model you specified in the configuration:
<pre>
Article::Archive.first
View
2 config/gemsets.yml
@@ -7,4 +7,4 @@ acts_as_archive:
externals: =1.0.2
framework_fixture: =0.1.3
mover: =0.3.6
- rack-test: =0.5.7
+ rack-test: =0.5.6
View
98 lib/acts_as_archive.rb
@@ -4,6 +4,7 @@
require 'also_migrate'
require 'mover'
+require 'yaml'
$:.unshift File.dirname(__FILE__)
@@ -41,18 +42,34 @@ def find(from)
end
end
- def move(config, where, merge_options={})
- config[:to].each do |to|
- options = config[:options].dup.merge(merge_options)
- if options[:conditions]
- options[:conditions] += " AND #{where}"
- elsif where
- options[:conditions] = where
+ def load_from_yaml(root)
+ if File.exists?(yaml = "#{root}/config/acts_as_archive.yml")
+ YAML.load(File.read(yaml)).each do |klass, config|
+ klass = eval(klass) rescue nil
+ if klass
+ if (%w(class table) - config.last.keys).empty?
+ options = {}
+ else
+ options = config.pop
+ end
+ config.each do |c|
+ klass.acts_as_archive options.merge(c)
+ end
+ end
end
- config[:from].move_to(to, options)
end
end
+ def move(config, where, merge_options={})
+ options = config[:options].dup.merge(merge_options)
+ if options[:conditions]
+ options[:conditions] += " AND #{where}"
+ elsif where
+ options[:conditions] = where
+ end
+ config[:from].move_to(config[:to], options)
+ end
+
def update(*args)
deprecate "ActsAsArchive.update is deprecated and no longer necessary."
end
@@ -67,17 +84,17 @@ def self.included(base)
end
module ClassMethods
- def acts_as_archive(*args)
+ def acts_as_archive(options={})
return unless ActsAsArchive.find(self).empty?
ActsAsArchive.configuration ||= []
ActsAsArchive.configuration << (config = { :from => self })
- options = args.last.is_a?(::Hash) ? args.pop : {}
options[:copy] = true
if options[:archive]
options[:magic] = 'restored_at'
+ klass = options[:class]
else
options[:magic] = 'deleted_at' if options[:magic].nil?
options[:add] = [[ options[:magic], :datetime ]]
@@ -85,35 +102,49 @@ def acts_as_archive(*args)
options[:subtract] = 'restored_at'
options[:timestamps] = false if options[:timestamps].nil?
- if args.empty?
- class_eval <<-EVAL
- class Archive < ActiveRecord::Base
- set_table_name "archived_#{self.table_name}"
+ unless options[:class]
+ options[:class] = "#{self}::Archive"
+ end
+
+ unless options[:table]
+ options[:table] = "archived_#{self.table_name}"
+ end
+
+ klass = eval(options[:class]) rescue nil
+
+ if klass
+ klass.send :set_table_name, options[:table]
+ else
+ eval <<-EVAL
+ class ::#{options[:class]} < ActiveRecord::Base
+ set_table_name "#{options[:table]}"
end
EVAL
- args << self::Archive
+ klass = eval("::#{options[:class]}")
end
+
+ klass.record_timestamps = options[:timestamps].inspect
+ klass.acts_as_archive(:class => self, :archive => true)
- args.each do |klass|
- klass.class_eval <<-EVAL
- record_timestamps = #{options[:timestamps].inspect}
- acts_as_archive(#{self}, :archive => true)
- EVAL
- self.reflect_on_all_associations.each do |association|
- if !ActsAsArchive.find(association.klass).empty? && association.options[:dependent]
- opts = association.options.dup
- opts[:class_name] = "::#{association.class_name}::Archive"
- opts[:foreign_key] = association.primary_key_name
- klass.send association.macro, association.name, opts
- end
- end
- unless options[:migrate] == false
- self.also_migrate klass.table_name, options
+ self.reflect_on_all_associations.each do |association|
+ if !ActsAsArchive.find(association.klass).empty? && association.options[:dependent]
+ opts = association.options.dup
+ opts[:class_name] = "::#{association.class_name}::Archive"
+ opts[:foreign_key] = association.primary_key_name
+ klass.send association.macro, association.name, opts
end
end
+
+ unless options[:migrate] == false
+ AlsoMigrate.configuration ||= []
+ AlsoMigrate.configuration << options.merge(
+ :source => self.table_name,
+ :destination => klass.table_name
+ )
+ end
end
- config[:to] = args
+ config[:to] = klass
config[:options] = options
end
@@ -192,4 +223,7 @@ def delete_sql_with_archive(sql, name = nil)
end
::ActiveRecord::Base.send(:include, ::ActsAsArchive::Base)
-::ActiveRecord::ConnectionAdapters::DatabaseStatements.send(:include, ::ActsAsArchive::DatabaseStatements)
+::ActiveRecord::ConnectionAdapters::DatabaseStatements.send(:include, ::ActsAsArchive::DatabaseStatements)
+
+require "acts_as_archive/adapters/rails#{Rails.version[0..0]}" if defined?(Rails)
+require "acts_as_archive/adapters/sinatra" if defined?(Sinatra)
View
1 lib/acts_as_archive/adapters/rails2.rb
@@ -0,0 +1 @@
+ActsAsArchive.load_from_yaml(Rails.root)
View
9 lib/acts_as_archive/adapters/rails3.rb
@@ -0,0 +1,9 @@
+if Rails.root.nil?
+ class ActsAsArchiveRailtie < Rails::Railtie
+ initializer "acts_as_archive" do
+ ActsAsArchive.load_from_yaml(Rails.root)
+ end
+ end
+else
+ ActsAsArchive.load_from_yaml(Rails.root)
+end
View
12 lib/acts_as_archive/adapters/sinatra.rb
@@ -0,0 +1,12 @@
+class ActsAsArchive
+ module Adapters
+ module Sinatra
+
+ def self.included(klass)
+ if klass.root
+ ActsAsArchive.load_from_yaml(klass.root)
+ end
+ end
+ end
+ end
+end
View
3 spec/fixtures/config/acts_as_archive.yml
@@ -0,0 +1,3 @@
+Record:
+ - class: Record::Archive
+ table: archived_records
View
5 spec/fixtures/frameworks.yml
@@ -1,5 +1,7 @@
rails:
<3:
+ config: &c
+ - config/acts_as_archive.yml
frameworks/rails2:
- app/controllers/application_controller.rb
- config/database.yml
@@ -17,6 +19,7 @@ rails:
- app/models/has_one_through_through.rb
- app/models/record.rb
<4:
+ config: *c
frameworks/rails3:
- app/controllers/application_controller.rb
- config/database.yml
@@ -26,11 +29,13 @@ rails:
models: *m
sinatra:
<1:
+ config: *c
frameworks/sinatra: &s
- application.rb
helpers: *h
models: *m
<2:
+ config: *c
frameworks/sinatra: *s
helpers: *h
models: *m
View
2 spec/fixtures/frameworks/rails3/Gemfile
@@ -5,6 +5,8 @@ gem 'mysql2'
gem 'rails', '3.0.3'
gem 'rspec'
+gem 'also_migrate', :path => "../../../../vendor/also_migrate"
+gem 'mover', :path => "../../../../vendor/mover"
gem 'acts_as_archive', :path => "../../../../"
# Bundle edge Rails instead:
View
1 spec/fixtures/frameworks/sinatra/application.rb
@@ -8,6 +8,7 @@ class Application < Sinatra::Base
set :raise_errors, true
set :show_exceptions, false
+ include ActsAsArchive::Adapters::Sinatra
include SpecHelper
get '/pulse' do
View
2 spec/fixtures/models/record.rb
@@ -11,6 +11,4 @@ class Record < ActiveRecord::Base
has_one :has_one_through_through, :dependent => :destroy
has_one :has_one_through, :dependent => :destroy, :through => :has_one_through_through
-
- acts_as_archive
end
View
6 spec/spec_helper.rb
@@ -45,8 +45,6 @@
ActiveSupport::Dependencies.autoload_paths << "#{$root}/spec/fixtures/models"
ActiveSupport::Dependencies.autoload_paths << "#{$root}/spec/fixtures/helpers"
- Record # Load up an instance so first also_migrate works
-
include SpecHelper
end
@@ -57,6 +55,10 @@
)
$db.establish_connection
+unless FrameworkFixture.framework
+ ActsAsArchive.load_from_yaml("#{$root}/spec/fixtures")
+end
+
if FrameworkFixture.framework == 'sinatra'
FrameworkFixture.generate File.dirname(__FILE__) + '/fixtures'
end

3 comments on commit dd7b490

@grimen

=S Not wanna complain about a good maintainer's commits, but this one made me hurl a bit...really feels totally wrong DSL-wise to abstract out class names into a YAML file liek this. Code-smell, really. What is the motivation for moving like pure Ruby code to a YAML file? 0_o

@winton
Owner

My problem is that rake db:migrate does not load up Rails models (lazy loading). It was a choice between this or forcing eager loading of every model when rake tasks run to get the acts_as_archive configuration.

The old way of defining it in the model still works (backwards compatible), though you may have some issues with migrations not being applied to your archive table unless the model is initialized in your environment.rb. That issue was present before this fix.

If you can come up with another solution, I would be happy to change it.

@grimen

OK, I see. I will try it out next time i work on my ActAsArchived-enabled project to get a better feeling of it. I got some vague ideas, but need to try them out first.

Please sign in to comment.
Something went wrong with that request. Please try again.