acts_as_paranoid 0.1.3

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.
data/CHANGELOG ADDED
@@ -0,0 +1,15 @@
1
+ *0.1.3* (18 Sep 2005)
2
+
3
+ * ignore multiple calls to acts_as_paranoid on the same model
4
+
5
+ *0.1.2* (18 Sep 2005)
6
+
7
+ * fixed a bug that kept you from selecting the first deleted record
8
+
9
+ *0.1.1* (18 Sep 2005)
10
+
11
+ * Fixed bug that kept you from selecting deleted records by ID
12
+
13
+ *0.1* (17 Sep 2005)
14
+
15
+ * Initial gem
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2005 Rick Olson
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,16 @@
1
+ = acts_as_paranoid
2
+
3
+ Overrides some basic methods for the current model so that calling #destroy sets a 'deleted_at' field to the
4
+ current timestamp. ActiveRecord is required.
5
+
6
+ == Download
7
+
8
+ Gem installation:
9
+
10
+ gem install acts_as_paranoid --source=http://techno-weenie.net/code
11
+
12
+ Get a gzipped tar at http://techno-weenie.net/code/pkg
13
+
14
+ == Usage
15
+
16
+ RDocs are online at http://techno-weenie.net/code/doc/acts_as_paranoid/.
@@ -0,0 +1,41 @@
1
+ == Creating the test database
2
+
3
+ The default name for the test databases is "activerecord_paranoid". If you
4
+ want to use another database name then be sure to update the connection
5
+ adapter setups you want to test with in test/connections/<your database>/connection.rb.
6
+ When you have the database online, you can import the fixture tables with
7
+ the test/fixtures/db_definitions/*.sql files.
8
+
9
+ Make sure that you create database objects with the same user that you specified in i
10
+ connection.rb otherwise (on Postgres, at least) tests for default values will fail.
11
+
12
+ == Running with Rake
13
+
14
+ The easiest way to run the unit tests is through Rake. The default task runs
15
+ the entire test suite for all the adapters. You can also run the suite on just
16
+ one adapter by using the tasks test_mysql_ruby, test_ruby_mysql, test_sqlite,
17
+ or test_postresql. For more information, checkout the full array of rake tasks with "rake -T"
18
+
19
+ Rake can be found at http://rake.rubyforge.org
20
+
21
+ == Running by hand
22
+
23
+ Unit tests are located in test directory. If you only want to run a single test suite,
24
+ or don't want to bother with Rake, you can do so with something like:
25
+
26
+ cd test; ruby -I "connections/native_mysql" base_test.rb
27
+
28
+ That'll run the base suite using the MySQL-Ruby adapter. Change the adapter
29
+ and test suite name as needed.
30
+
31
+ == Faster tests
32
+
33
+ If you are using a database that supports transactions, you can set the
34
+ "AR_TX_FIXTURES" environment variable to "yes" to use transactional fixtures.
35
+ This gives a very large speed boost. With rake:
36
+
37
+ rake AR_TX_FIXTURES=yes
38
+
39
+ Or, by hand:
40
+
41
+ AR_TX_FIXTURES=yes ruby -I connections/native_sqlite3 base_test.rb
@@ -0,0 +1,112 @@
1
+ module ActiveRecord #:nodoc:
2
+ module Acts #:nodoc:
3
+ # Overrides some basic methods for the current model so that calling #destroy sets a 'deleted_at' field to the current timestamp.
4
+ # This assumes the table has a deleted_at date/time field. Most normal model operations will work, but there will be some oddities.
5
+ #
6
+ # class Widget < ActiveRecord::Base
7
+ # acts_as_paranoid
8
+ # end
9
+ #
10
+ # Widget.find(:all)
11
+ # # SELECT * FROM widgets WHERE widgets.deleted_at IS NULL
12
+ #
13
+ # Widget.find(:first, :conditions => ['title = ?', 'test'], :order => 'title')
14
+ # # SELECT * FROM widgets WHERE widgets.deleted_at IS NULL AND title = 'test' ORDER BY title LIMIT 1
15
+ #
16
+ # Widget.find_with_deleted(:all)
17
+ # # SELECT * FROM widgets
18
+ #
19
+ # Widget.find(:all, :with_deleted => true)
20
+ # # SELECT * FROM widgets
21
+ #
22
+ # Widget.count
23
+ # # SELECT COUNT(*) FROM widgets WHERE widgets.deleted_at IS NULL
24
+ #
25
+ # Widget.count ['title = ?', 'test']
26
+ # # SELECT COUNT(*) FROM widgets WHERE widgets.deleted_at IS NULL AND title = 'test'
27
+ #
28
+ # Widget.count_with_deleted
29
+ # # SELECT COUNT(*) FROM widgets
30
+ #
31
+ # @widget.destroy
32
+ # # UPDATE widgets SET deleted_at = '2005-09-17 17:46:36' WHERE id = 1
33
+ #
34
+ # @widget.destroy!
35
+ # # DELETE FROM widgets WHERE id = 1
36
+ module Paranoid
37
+ def self.included(base) # :nodoc:
38
+ base.extend ClassMethods
39
+ end
40
+
41
+ module ClassMethods
42
+ def acts_as_paranoid
43
+ return if self.included_modules.include?(ActiveRecord::Acts::Paranoid::ParanoidMethods) # don't let AR call this twice
44
+ class_eval do
45
+ alias_method :destroy_without_callbacks!, :destroy_without_callbacks
46
+ class << self
47
+ alias_method :original_find, :find
48
+ alias_method :count_with_deleted, :count
49
+ end
50
+ include ParanoidMethods
51
+ end
52
+ end
53
+ end
54
+
55
+ module ParanoidMethods #:nodoc:
56
+ def self.included(base) # :nodoc:
57
+ base.extend ClassMethods
58
+ end
59
+
60
+ module ClassMethods
61
+ def find(*args)
62
+ options = extract_options_from_args!(args)
63
+ call_original_find = lambda { original_find(*(args << options)) }
64
+
65
+ if !options[:with_deleted]
66
+ constrain = "#{table_name}.deleted_at IS NULL"
67
+ constrains = (scope_constrains.nil? or scope_constrains[:conditions].nil? or scope_constrains[:conditions] == constrain) ?
68
+ constrain :
69
+ "#{scope_constrains[:conditions]} AND #{constrain}"
70
+ constrain(:conditions => constrains) { return call_original_find.call }
71
+ end
72
+
73
+ call_original_find.call
74
+ end
75
+
76
+ def find_with_deleted(*args)
77
+ original_find(*(args << extract_options_from_args!(args).merge(:with_deleted => true)))
78
+ end
79
+
80
+ def count(conditions = nil, joins = nil)
81
+ constrain(:conditions => "#{table_name}.deleted_at IS NULL") { count_with_deleted(conditions, joins) }
82
+ end
83
+ end
84
+
85
+ def destroy_without_callbacks
86
+ unless new_record?
87
+ sql = self.class.send(:sanitize_sql,
88
+ ["UPDATE #{self.class.table_name} SET deleted_at = ? WHERE id = ?",
89
+ self.class.default_timezone == :utc ? Time.now.utc : Time.now, id])
90
+ self.connection.update(sql)
91
+ end
92
+ freeze
93
+ end
94
+
95
+ def destroy_with_callbacks!
96
+ return false if callback(:before_destroy) == false
97
+ result = destroy_without_callbacks!
98
+ callback(:after_destroy)
99
+ result
100
+ end
101
+
102
+ def destroy!
103
+ transaction { destroy_with_callbacks! }
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ ActiveRecord::Base.class_eval do
111
+ include ActiveRecord::Acts::Paranoid
112
+ end
@@ -0,0 +1,25 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'active_record'
6
+ require 'active_record/fixtures'
7
+ require 'active_support/binding_of_caller'
8
+ require 'active_support/breakpoint'
9
+ require 'connection'
10
+ require 'acts_as_paranoid'
11
+
12
+ class Test::Unit::TestCase #:nodoc:
13
+ def create_fixtures(*table_names)
14
+ if block_given?
15
+ Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures/", table_names) { yield }
16
+ else
17
+ Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures/", table_names)
18
+ end
19
+ end
20
+ end
21
+
22
+ Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
23
+ Test::Unit::TestCase.use_instantiated_fixtures = false
24
+ Test::Unit::TestCase.use_transactional_fixtures = (ENV['AR_TX_FIXTURES'] == "yes")
25
+
@@ -0,0 +1,14 @@
1
+ print "Using native DB2\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ db1 = 'arparanoid'
7
+
8
+ ActiveRecord::Base.establish_connection(
9
+ :adapter => "db2",
10
+ :host => "localhost",
11
+ :username => "arunit",
12
+ :password => "arunit",
13
+ :database => db1
14
+ )
@@ -0,0 +1,14 @@
1
+ print "Using native MySQL\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ db1 = 'activerecord_paranoid'
7
+
8
+ ActiveRecord::Base.establish_connection(
9
+ :adapter => "mysql",
10
+ :host => "localhost",
11
+ :username => "rails",
12
+ :password => "",
13
+ :database => db1
14
+ )
@@ -0,0 +1,15 @@
1
+ print "Using OCI Oracle\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new STDOUT
5
+ ActiveRecord::Base.logger.level = Logger::WARN
6
+
7
+ db1 = 'activerecord_paranoid'
8
+
9
+ ActiveRecord::Base.establish_connection(
10
+ :adapter => 'oci',
11
+ :host => '', # can use an oracle SID
12
+ :username => 'arunit',
13
+ :password => 'arunit',
14
+ :database => db1
15
+ )
@@ -0,0 +1,14 @@
1
+ print "Using native PostgreSQL\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ db1 = 'activerecord_paranoid'
7
+
8
+ ActiveRecord::Base.establish_connection(
9
+ :adapter => "postgresql",
10
+ :host => nil,
11
+ :username => "postgres",
12
+ :password => "postgres",
13
+ :database => db1
14
+ )
@@ -0,0 +1,34 @@
1
+ print "Using native SQlite\n"
2
+ require 'logger'
3
+ ActiveRecord::Base.logger = Logger.new("debug.log")
4
+
5
+ class SqliteError < StandardError
6
+ end
7
+
8
+ BASE_DIR = File.expand_path(File.dirname(__FILE__) + '/../../fixtures')
9
+ sqlite_test_db = "#{BASE_DIR}/activerecord_paranoid.sqlite"
10
+
11
+ def make_connection(clazz, db_file, db_definitions_file)
12
+ unless File.exist?(db_file)
13
+ puts "SQLite database not found at #{db_file}. Rebuilding it."
14
+ sqlite_command = %Q{sqlite #{db_file} "create table a (a integer); drop table a;"}
15
+ puts "Executing '#{sqlite_command}'"
16
+ raise SqliteError.new("Seems that there is no sqlite executable available") unless system(sqlite_command)
17
+ clazz.establish_connection(
18
+ :adapter => "sqlite",
19
+ :dbfile => db_file)
20
+ script = File.read("#{BASE_DIR}/db_definitions/#{db_definitions_file}")
21
+ # SQLite-Ruby has problems with semi-colon separated commands, so split and execute one at a time
22
+ script.split(';').each do
23
+ |command|
24
+ clazz.connection.execute(command) unless command.strip.empty?
25
+ end
26
+ else
27
+ clazz.establish_connection(
28
+ :adapter => "sqlite",
29
+ :dbfile => db_file)
30
+ end
31
+ end
32
+
33
+ make_connection(ActiveRecord::Base, sqlite_test_db, 'sqlite.sql')
34
+
@@ -0,0 +1,33 @@
1
+ print "Using native SQLite3\n"
2
+ require 'logger'
3
+ ActiveRecord::Base.logger = Logger.new("debug.log")
4
+
5
+ class SqliteError < StandardError
6
+ end
7
+
8
+ BASE_DIR = File.expand_path(File.dirname(__FILE__) + '/../../fixtures')
9
+ sqlite_test_db = "#{BASE_DIR}/activerecord_paranoid.sqlite3"
10
+
11
+ def make_connection(clazz, db_file, db_definitions_file)
12
+ unless File.exist?(db_file)
13
+ puts "SQLite3 database not found at #{db_file}. Rebuilding it."
14
+ sqlite_command = %Q{sqlite3 #{db_file} "create table a (a integer); drop table a;"}
15
+ puts "Executing '#{sqlite_command}'"
16
+ raise SqliteError.new("Seems that there is no sqlite3 executable available") unless system(sqlite_command)
17
+ clazz.establish_connection(
18
+ :adapter => "sqlite3",
19
+ :dbfile => db_file)
20
+ script = File.read("#{BASE_DIR}/db_definitions/#{db_definitions_file}")
21
+ # SQLite-Ruby has problems with semi-colon separated commands, so split and execute one at a time
22
+ script.split(';').each do
23
+ |command|
24
+ clazz.connection.execute(command) unless command.strip.empty?
25
+ end
26
+ else
27
+ clazz.establish_connection(
28
+ :adapter => "sqlite3",
29
+ :dbfile => db_file)
30
+ end
31
+ end
32
+
33
+ make_connection(ActiveRecord::Base, sqlite_test_db, 'sqlite.sql')
@@ -0,0 +1,14 @@
1
+ print "Using native SQLServer\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ db1 = 'activerecord_paranoid'
7
+
8
+ ActiveRecord::Base.establish_connection(
9
+ :adapter => "sqlserver",
10
+ :host => "localhost",
11
+ :username => "sa",
12
+ :password => "",
13
+ :database => db1
14
+ )
@@ -0,0 +1,15 @@
1
+ print "Using native SQLServer via ODBC\n"
2
+ require 'logger'
3
+
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ dsn1 = 'activerecord_paranoid'
7
+
8
+ ActiveRecord::Base.establish_connection(
9
+ :adapter => "sqlserver",
10
+ :mode => "ODBC",
11
+ :host => "localhost",
12
+ :username => "sa",
13
+ :password => "",
14
+ :dsn => dsn1
15
+ )
@@ -0,0 +1,9 @@
1
+ category_1:
2
+ id: 1
3
+ widget_id: 1
4
+ title: 'category 1'
5
+ category_2:
6
+ id: 2
7
+ widget_id: 1
8
+ title: 'category 2'
9
+ deleted_at: '2005-01-01 00:00:00'
@@ -0,0 +1,6 @@
1
+ cw_1:
2
+ category_id: 1
3
+ widget_id: 1
4
+ cw_2:
5
+ category_id: 2
6
+ widget_id: 1
@@ -0,0 +1,3 @@
1
+ drop table categories_widgets;
2
+ drop table categories;
3
+ drop table widgets;
@@ -0,0 +1,19 @@
1
+ CREATE TABLE widgets (
2
+ id SERIAL,
3
+ title VARCHAR(50),
4
+ deleted_at TIMESTAMP
5
+ );
6
+ SELECT setval('widgets_id_seq', 100);
7
+
8
+ CREATE TABLE categories (
9
+ id SERIAL,
10
+ widget_id INT,
11
+ title VARCHAR(50),
12
+ deleted_at TIMESTAMP
13
+ );
14
+ SELECT setval('categories_id_seq', 100);
15
+
16
+ CREATE TABLE categories_widgets (
17
+ category_id INT,
18
+ widget_id INT
19
+ );
@@ -0,0 +1,3 @@
1
+ DROP TABLE 'categories_widgets';
2
+ DROP TABLE 'categories';
3
+ DROP TABLE 'widgets';
@@ -0,0 +1,17 @@
1
+ CREATE TABLE 'widgets' (
2
+ 'id' INTEGER NOT NULL PRIMARY KEY,
3
+ 'title' VARCHAR(50),
4
+ 'deleted_at' DATETIME
5
+ );
6
+
7
+ CREATE TABLE 'categories' (
8
+ 'id' INTEGER NOT NULL PRIMARY KEY,
9
+ 'widget_id' INTEGER,
10
+ 'title' VARCHAR(50),
11
+ 'deleted_at' DATETIME
12
+ );
13
+
14
+ CREATE TABLE 'categories_widgets' (
15
+ 'category_id' INTEGER,
16
+ 'widget_id' INTEGER
17
+ );
@@ -0,0 +1,7 @@
1
+ widget_1:
2
+ id: 1
3
+ title: 'widget 1'
4
+ widget_2:
5
+ id: 2
6
+ title: 'deleted widget 2'
7
+ deleted_at: '2005-01-01 00:00:00'
@@ -0,0 +1,80 @@
1
+ require 'abstract_unit'
2
+
3
+ class Widget < ActiveRecord::Base
4
+ has_many :categories, :dependent => true
5
+ has_and_belongs_to_many :habtm_categories, :class_name => 'Category'
6
+ acts_as_paranoid
7
+ end
8
+
9
+ class Category < ActiveRecord::Base
10
+ belongs_to :widget
11
+ acts_as_paranoid
12
+ end
13
+
14
+ class ParanoidTest < Test::Unit::TestCase
15
+ fixtures :widgets, :categories, :categories_widgets
16
+
17
+ def test_should_set_deleted_at
18
+ assert_equal 1, Widget.count
19
+ assert_equal 1, Category.count
20
+ widgets(:widget_1).destroy
21
+ assert_equal 0, Widget.count
22
+ assert_equal 0, Category.count
23
+ assert_equal 2, Widget.count_with_deleted
24
+ assert_equal 2, Category.count_with_deleted
25
+ end
26
+
27
+ def test_should_destroy
28
+ assert_equal 1, Widget.count
29
+ assert_equal 1, Category.count
30
+ widgets(:widget_1).destroy!
31
+ assert_equal 0, Widget.count
32
+ assert_equal 0, Category.count
33
+ assert_equal 1, Widget.count_with_deleted
34
+ # Category doesn't get destroyed because the dependent before_destroy callback uses #destroy
35
+ assert_equal 2, Category.count_with_deleted
36
+ end
37
+
38
+ def test_should_not_count_deleted
39
+ assert_equal 1, Widget.count
40
+ assert_equal 1, Widget.count(['title=?', 'widget 1'])
41
+ assert_equal 2, Widget.count_with_deleted
42
+ end
43
+
44
+ def test_should_not_find_deleted
45
+ assert_equal [widgets(:widget_1)], Widget.find(:all)
46
+ assert_equal [1, 2], Widget.find_with_deleted(:all, :order => 'id').collect { |w| w.id }
47
+ end
48
+
49
+ def test_should_not_find_deleted_associations
50
+ assert_equal 2, Category.count_with_deleted('widget_id=1')
51
+
52
+ assert_equal 1, widgets(:widget_1).categories.size
53
+ assert_equal [categories(:category_1)], widgets(:widget_1).categories
54
+
55
+ assert_equal 1, widgets(:widget_1).habtm_categories.size
56
+ assert_equal [categories(:category_1)], widgets(:widget_1).habtm_categories
57
+ end
58
+
59
+ def test_should_find_first_with_deleted
60
+ assert_equal widgets(:widget_1), Widget.find(:first)
61
+ assert_equal 2, Widget.find_with_deleted(:first, :order => 'id desc').id
62
+ end
63
+
64
+ def test_should_find_single_id
65
+ assert Widget.find(1)
66
+ assert Widget.find_with_deleted(2)
67
+ assert_raises(ActiveRecord::RecordNotFound) { Widget.find(2) }
68
+ end
69
+
70
+ def test_should_find_multiple_ids
71
+ assert_equal [1,2], Widget.find_with_deleted(1,2).sort_by { |w| w.id }.collect { |w| w.id }
72
+ assert_equal [1,2], Widget.find_with_deleted([1,2]).sort_by { |w| w.id }.collect { |w| w.id }
73
+ assert_raises(ActiveRecord::RecordNotFound) { Widget.find(1,2) }
74
+ end
75
+
76
+ def test_should_ignore_multiple_includes
77
+ Widget.class_eval { acts_as_paranoid }
78
+ assert Widget.find(1)
79
+ end
80
+ end
data/test/tests.rb ADDED
@@ -0,0 +1,2 @@
1
+ $:.unshift "../lib"
2
+ Dir["**/*_test.rb"].each { |f| load f }
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.10
3
+ specification_version: 1
4
+ name: acts_as_paranoid
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.3
7
+ date: 2005-09-18
8
+ summary: acts_as_paranoid keeps models from actually being deleted by setting a deleted_at field.
9
+ require_paths:
10
+ - lib
11
+ email: technoweenie@gmail.com
12
+ homepage: http://techno-weenie.net
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: acts_as_paranoid
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ authors:
28
+ - Rick Olson
29
+ files:
30
+ - lib/acts_as_paranoid.rb
31
+ - test/abstract_unit.rb
32
+ - test/connections
33
+ - test/fixtures
34
+ - test/paranoid_test.rb
35
+ - test/tests.rb
36
+ - test/connections/native_db2
37
+ - test/connections/native_mysql
38
+ - test/connections/native_oci
39
+ - test/connections/native_postgresql
40
+ - test/connections/native_sqlite
41
+ - test/connections/native_sqlite3
42
+ - test/connections/native_sqlserver
43
+ - test/connections/native_sqlserver_odbc
44
+ - test/connections/native_db2/connection.rb
45
+ - test/connections/native_mysql/connection.rb
46
+ - test/connections/native_oci/connection.rb
47
+ - test/connections/native_postgresql/connection.rb
48
+ - test/connections/native_sqlite/connection.rb
49
+ - test/connections/native_sqlite3/connection.rb
50
+ - test/connections/native_sqlserver/connection.rb
51
+ - test/connections/native_sqlserver_odbc/connection.rb
52
+ - test/fixtures/activerecord_paranoid.sqlite
53
+ - test/fixtures/categories.yml
54
+ - test/fixtures/categories_widgets.yml
55
+ - test/fixtures/db_definitions
56
+ - test/fixtures/widgets.yml
57
+ - test/fixtures/db_definitions/postgresql.drop.sql
58
+ - test/fixtures/db_definitions/postgresql.sql
59
+ - test/fixtures/db_definitions/sqlite.drop.sql
60
+ - test/fixtures/db_definitions/sqlite.sql
61
+ - README
62
+ - MIT-LICENSE
63
+ - CHANGELOG
64
+ - RUNNING_UNIT_TESTS
65
+ test_files:
66
+ - test/tests.rb
67
+ rdoc_options: []
68
+ extra_rdoc_files: []
69
+ executables: []
70
+ extensions: []
71
+ requirements: []
72
+ dependencies: []