acts_as_paranoid 0.1.7 → 0.2

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 CHANGED
@@ -1,3 +1,7 @@
1
+ *0.2.0* (6 Nov 2005)
2
+
3
+ * Upgrade to Rails 1.0 RC4. ActiveRecord::Base#constrain has been replaced with scope_with.
4
+
1
5
  *0.1.7* (22 Oct 2005)
2
6
 
3
7
  * Added :with_deleted as a valid option of ActiveRecord::Base#find
@@ -45,6 +45,7 @@ module ActiveRecord #:nodoc:
45
45
  class << self
46
46
  alias_method :original_find, :find
47
47
  alias_method :count_with_deleted, :count
48
+ alias_method :clobbering_with_scope, :with_scope
48
49
  end
49
50
  end
50
51
  include ParanoidMethods
@@ -53,9 +54,6 @@ module ActiveRecord #:nodoc:
53
54
 
54
55
  module ParanoidMethods #:nodoc:
55
56
  def self.included(base) # :nodoc:
56
- class << base
57
- alias_method :clobbering_constrain, :constrain
58
- end
59
57
  base.extend ClassMethods
60
58
  end
61
59
 
@@ -65,7 +63,7 @@ module ActiveRecord #:nodoc:
65
63
  call_original_find = lambda { original_find(*(args << options)) }
66
64
 
67
65
  if !options[:with_deleted]
68
- constrain(scope_constrains.merge(:conditions => deleted_constrain)) { return call_original_find.call }
66
+ with_deleted_scope { return call_original_find.call }
69
67
  end
70
68
 
71
69
  call_original_find.call
@@ -76,36 +74,53 @@ module ActiveRecord #:nodoc:
76
74
  end
77
75
 
78
76
  def count(conditions = nil, joins = nil)
79
- constrain(scope_constrains.merge(:conditions => deleted_constrain)) { count_with_deleted(conditions, joins) }
77
+ with_deleted_scope { count_with_deleted(conditions, joins) }
80
78
  end
81
79
 
82
- # Override #constrain so that nested constrains don't clobber each other.
83
- #
84
- # Entry.constrain(:conditions => 'published_at IS NOT NULL') do
85
- # Entry.constrain(:conditions => 'deleted_at IS NULL') do
86
- # Entry.find(:all)
87
- # end
88
- # end
89
- def constrain(options = {}, &block)
90
- begin
91
- is_new_scope = scope_constrains.empty?
92
- self.scope_constrains = options
93
- block.call if block_given?
94
- ensure
95
- self.scope_constrains = nil if is_new_scope
80
+ def with_scope(method_scoping = {}, is_new_scope = true)
81
+ # Dup first and second level of hash (method and params).
82
+ method_scoping = method_scoping.inject({}) do |hash, (method, params)|
83
+ hash[method] = params.dup
84
+ hash
85
+ end
86
+
87
+ method_scoping.assert_valid_keys [:find, :create]
88
+ if f = method_scoping[:find]
89
+ f.assert_valid_keys [:conditions, :joins, :offset, :limit, :readonly]
90
+ f[:readonly] = true if !f[:joins].blank? && !f.has_key?(:readonly)
96
91
  end
92
+
93
+ raise ArgumentError, "Nested scopes are not yet supported: #{scoped_methods.inspect}" unless scoped_methods.nil?
94
+
95
+ self.scoped_methods = method_scoping
96
+ yield
97
+ ensure
98
+ self.scoped_methods = nil if is_new_scope
97
99
  end
98
100
 
99
101
  protected
100
- def deleted_constrain
102
+ def with_deleted_scope(&block)
101
103
  deleted_cond = "#{table_name}.deleted_at IS NULL"
102
- case scope_constrains[:conditions]
103
- when /#{deleted_cond}/ then scope_constrains[:conditions]
104
- when NilClass then deleted_cond
105
- else "#{scope_constrains[:conditions]} AND #{deleted_cond}"
104
+ if scoped_methods.nil?
105
+ is_new_scope = true
106
+ current_scope = {}
107
+ else
108
+ is_new_scope = false
109
+ current_scope = scoped_methods.clone
110
+ self.scoped_methods = nil
106
111
  end
112
+
113
+ current_scope ||= {}
114
+ current_scope[:find] ||= {}
115
+ if not current_scope[:find][:conditions] =~ /#{deleted_cond}/
116
+ current_scope[:find][:conditions] = current_scope[:find][:conditions].nil? ?
117
+ deleted_cond :
118
+ "(#{current_scope[:find][:conditions]}) AND #{deleted_cond}"
119
+ end
120
+
121
+ with_scope(current_scope, is_new_scope, &block)
107
122
  end
108
-
123
+
109
124
  def validate_find_options(options)
110
125
  options.assert_valid_keys [:conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :with_deleted]
111
126
  end
@@ -0,0 +1,18 @@
1
+ sqlite:
2
+ :adapter: sqlite
3
+ :dbfile: acts_as_paranoid_plugin.sqlite.db
4
+ sqlite3:
5
+ :adapter: sqlite3
6
+ :dbfile: acts_as_paranoid_plugin.sqlite3.db
7
+ postgresql:
8
+ :adapter: postgresql
9
+ :username: postgres
10
+ :password: postgres
11
+ :database: acts_as_paranoid_plugin_test
12
+ :min_messages: ERROR
13
+ mysql:
14
+ :adapter: mysql
15
+ :host: localhost
16
+ :username: rails
17
+ :password:
18
+ :database: acts_as_paranoid_plugin_test
@@ -1,4 +1,4 @@
1
- require 'abstract_unit'
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
2
 
3
3
  class Widget < ActiveRecord::Base
4
4
  acts_as_paranoid
@@ -78,20 +78,20 @@ class ParanoidTest < Test::Unit::TestCase
78
78
  assert Widget.find(1)
79
79
  end
80
80
 
81
- def test_should_not_override_constrains_when_counting
82
- assert_equal 1, Widget.constrain(:conditions => "title = 'widget 1'") { Widget.count }
83
- assert_equal 0, Widget.constrain(:conditions => "title = 'deleted widget 2'") { Widget.count }
84
- assert_equal 1, Widget.constrain(:conditions => "title = 'deleted widget 2'") { Widget.count_with_deleted }
81
+ def test_should_not_override_scopes_when_counting
82
+ assert_equal 1, Widget.with_scope(:find => { :conditions => "title = 'widget 1'" }) { Widget.count }
83
+ assert_equal 0, Widget.with_scope(:find => { :conditions => "title = 'deleted widget 2'" }) { Widget.count }
84
+ assert_equal 1, Widget.with_scope(:find => { :conditions => "title = 'deleted widget 2'" }) { Widget.count_with_deleted }
85
85
  end
86
86
 
87
- def test_should_not_override_constrains_when_finding
88
- assert_equal [1], Widget.constrain(:conditions => "title = 'widget 1'") { Widget.find(:all) }.ids
89
- assert_equal [], Widget.constrain(:conditions => "title = 'deleted widget 2'") { Widget.find(:all) }.ids
90
- assert_equal [2], Widget.constrain(:conditions => "title = 'deleted widget 2'") { Widget.find_with_deleted(:all) }.ids
87
+ def test_should_not_override_scopes_when_finding
88
+ assert_equal [1], Widget.with_scope(:find => { :conditions => "title = 'widget 1'" }) { Widget.find(:all) }.ids
89
+ assert_equal [], Widget.with_scope(:find => { :conditions => "title = 'deleted widget 2'" }) { Widget.find(:all) }.ids
90
+ assert_equal [2], Widget.with_scope(:find => { :conditions => "title = 'deleted widget 2'" }) { Widget.find_with_deleted(:all) }.ids
91
91
  end
92
92
 
93
- def test_should_allow_multiple_constrained_calls_when_finding
94
- Widget.constrain(:conditions => "title = 'deleted widget 2'") do
93
+ def test_should_allow_multiple_scoped_calls_when_finding
94
+ Widget.with_scope(:find => { :conditions => "title = 'deleted widget 2'" }) do
95
95
  assert_equal [2], Widget.find_with_deleted(:all).ids
96
96
  assert_equal [2], Widget.find_with_deleted(:all).ids, "clobbers the constrain on the unmodified find"
97
97
  assert_equal [], Widget.find(:all).ids
@@ -99,8 +99,8 @@ class ParanoidTest < Test::Unit::TestCase
99
99
  end
100
100
  end
101
101
 
102
- def test_should_allow_multiple_constrained_calls_when_counting
103
- Widget.constrain(:conditions => "title = 'deleted widget 2'") do
102
+ def test_should_allow_multiple_scoped_calls_when_counting
103
+ Widget.with_scope(:find => { :conditions => "title = 'deleted widget 2'" }) do
104
104
  assert_equal 1, Widget.count_with_deleted
105
105
  assert_equal 1, Widget.count_with_deleted, "clobbers the constrain on the unmodified find"
106
106
  assert_equal 0, Widget.count
@@ -0,0 +1,19 @@
1
+ ActiveRecord::Schema.define(:version => 1) do
2
+
3
+ create_table :widgets, :force => true do |t|
4
+ t.column :title, :string, :limit => 50
5
+ t.column :deleted_at, :timestamp
6
+ end
7
+
8
+ create_table :categories, :force => true do |t|
9
+ t.column :widget_id, :integer
10
+ t.column :title, :string, :limit => 50
11
+ t.column :deleted_at, :timestamp
12
+ end
13
+
14
+ create_table :categories_widgets, :force => true, :id => false do |t|
15
+ t.column :category_id, :integer
16
+ t.column :widget_id, :integer
17
+ end
18
+
19
+ end
@@ -0,0 +1,36 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'test/unit'
4
+ #require 'active_record'
5
+ #require 'active_support/binding_of_caller'
6
+ #require 'active_support/breakpoint'
7
+ require "#{File.dirname(__FILE__)}/../../../../config/environment"
8
+ require 'active_record/fixtures'
9
+ require "#{File.dirname(__FILE__)}/../init"
10
+
11
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
12
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
13
+ ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite'])
14
+
15
+ load(File.dirname(__FILE__) + "/schema.rb")
16
+
17
+ Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
18
+ $LOAD_PATH.unshift(Test::Unit::TestCase.fixture_path)
19
+
20
+ class Test::Unit::TestCase #:nodoc:
21
+ def create_fixtures(*table_names)
22
+ if block_given?
23
+ Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names) { yield }
24
+ else
25
+ Fixtures.create_fixtures(Test::Unit::TestCase.fixture_path, table_names)
26
+ end
27
+ end
28
+
29
+ # Turn off transactional fixtures if you're working with MyISAM tables in MySQL
30
+ self.use_transactional_fixtures = true
31
+
32
+ # Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
33
+ self.use_instantiated_fixtures = false
34
+
35
+ # Add more helper methods to be used by all tests here...
36
+ end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: acts_as_paranoid
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.7
7
- date: 2005-10-22
6
+ version: "0.2"
7
+ date: 2005-11-15
8
8
  summary: acts_as_paranoid keeps models from actually being deleted by setting a deleted_at field.
9
9
  require_paths:
10
10
  - lib
@@ -28,42 +28,20 @@ authors:
28
28
  - Rick Olson
29
29
  files:
30
30
  - lib/acts_as_paranoid.rb
31
- - test/abstract_unit.rb
32
- - test/connections
31
+ - test/database.yml
33
32
  - test/fixtures
34
33
  - 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
34
+ - test/schema.rb
35
+ - test/test_helper.rb
53
36
  - test/fixtures/categories.yml
54
37
  - test/fixtures/categories_widgets.yml
55
- - test/fixtures/db_definitions
56
38
  - 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
39
  - README
62
40
  - MIT-LICENSE
63
41
  - CHANGELOG
64
42
  - RUNNING_UNIT_TESTS
65
43
  test_files:
66
- - test/tests.rb
44
+ - test/paranoid_test.rb
67
45
  rdoc_options: []
68
46
  extra_rdoc_files: []
69
47
  executables: []
@@ -1,25 +0,0 @@
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
-
@@ -1,14 +0,0 @@
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
- )
@@ -1,14 +0,0 @@
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
- )
@@ -1,15 +0,0 @@
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
- )
@@ -1,14 +0,0 @@
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
- )
@@ -1,34 +0,0 @@
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
-
@@ -1,33 +0,0 @@
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')
@@ -1,14 +0,0 @@
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
- )
@@ -1,15 +0,0 @@
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
- )
@@ -1,3 +0,0 @@
1
- drop table categories_widgets;
2
- drop table categories;
3
- drop table widgets;
@@ -1,19 +0,0 @@
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
- );
@@ -1,3 +0,0 @@
1
- DROP TABLE 'categories_widgets';
2
- DROP TABLE 'categories';
3
- DROP TABLE 'widgets';
@@ -1,17 +0,0 @@
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
- );
@@ -1,2 +0,0 @@
1
- $:.unshift "../lib"
2
- Dir["**/*_test.rb"].each { |f| load f }