Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes a problem of ambiguous table names when using only_deleted meth… #379

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/paranoia.rb
Expand Up @@ -35,8 +35,9 @@ def only_deleted
# some deleted rows will hold a null value in the paranoia column
# these will not match != sentinel value because "NULL != value" is
# NULL under the sql standard
quoted_paranoia_column = connection.quote_column_name(paranoia_column)
with_deleted.where("#{quoted_paranoia_column} IS NULL OR #{quoted_paranoia_column} != ?", paranoia_sentinel_value)
# Scoping with the table_name is mandatory to avoid ambiguous errors when joining tables.
scoped_quoted_paranoia_column = "#{self.table_name}.#{connection.quote_column_name(paranoia_column)}"
with_deleted.where("#{scoped_quoted_paranoia_column} IS NULL OR #{scoped_quoted_paranoia_column} != ?", paranoia_sentinel_value)
end
alias_method :deleted, :only_deleted

Expand Down
55 changes: 55 additions & 0 deletions test/paranoia_test.rb
Expand Up @@ -40,6 +40,8 @@ def setup!
'unparanoid_unique_models' => 'name VARCHAR(32), paranoid_with_unparanoids_id INTEGER',
'active_column_models' => 'deleted_at DATETIME, active BOOLEAN',
'active_column_model_with_uniqueness_validations' => 'name VARCHAR(32), deleted_at DATETIME, active BOOLEAN',
'paranoid_model_with_belongs_to_active_column_model_with_has_many_relationships' => 'name VARCHAR(32), deleted_at DATETIME, active BOOLEAN, active_column_model_with_has_many_relationship_id INTEGER',
'active_column_model_with_has_many_relationships' => 'name VARCHAR(32), deleted_at DATETIME, active BOOLEAN',
'without_default_scope_models' => 'deleted_at DATETIME'
}.each do |table_name, columns_as_sql_string|
ActiveRecord::Base.connection.execute "CREATE TABLE #{table_name} (id INTEGER NOT NULL PRIMARY KEY, #{columns_as_sql_string})"
Expand Down Expand Up @@ -182,8 +184,11 @@ def test_scoping_behavior_for_paranoid_models
p2 = ParanoidModel.create(:parent_model => parent2)
p1.destroy
p2.destroy

assert_equal 0, parent1.paranoid_models.count
assert_equal 1, parent1.paranoid_models.only_deleted.count

assert_equal 2, ParanoidModel.only_deleted.joins(:parent_model).count
assert_equal 1, parent1.paranoid_models.deleted.count
assert_equal 0, parent1.paranoid_models.without_deleted.count
p3 = ParanoidModel.create(:parent_model => parent1)
Expand All @@ -192,6 +197,17 @@ def test_scoping_behavior_for_paranoid_models
assert_equal [p1,p3], parent1.paranoid_models.with_deleted
end

def test_only_deleted_with_joins
c1 = ActiveColumnModelWithHasManyRelationship.create(name: 'Jacky')
c2 = ActiveColumnModelWithHasManyRelationship.create(name: 'Thomas')
p1 = ParanoidModelWithBelongsToActiveColumnModelWithHasManyRelationship.create(name: 'Hello', active_column_model_with_has_many_relationship: c1)

c1.destroy
assert_equal 1, ActiveColumnModelWithHasManyRelationship.count
assert_equal 1, ActiveColumnModelWithHasManyRelationship.only_deleted.count
assert_equal 1, ActiveColumnModelWithHasManyRelationship.only_deleted.joins(:paranoid_model_with_belongs_to_active_column_model_with_has_many_relationships).count
end

def test_destroy_behavior_for_custom_column_models
model = CustomColumnModel.new
assert_equal 0, model.class.count
Expand Down Expand Up @@ -1112,6 +1128,45 @@ def paranoia_destroy_attributes
end
end

class ActiveColumnModelWithHasManyRelationship < ActiveRecord::Base
has_many :paranoid_model_with_belongs_to_active_column_model_with_has_many_relationships
acts_as_paranoid column: :active, sentinel_value: true

def paranoia_restore_attributes
{
deleted_at: nil,
active: true
}
end

def paranoia_destroy_attributes
{
deleted_at: current_time_from_proper_timezone,
active: nil
}
end
end

class ParanoidModelWithBelongsToActiveColumnModelWithHasManyRelationship < ActiveRecord::Base
belongs_to :active_column_model_with_has_many_relationship

acts_as_paranoid column: :active, sentinel_value: true

def paranoia_restore_attributes
{
deleted_at: nil,
active: true
}
end

def paranoia_destroy_attributes
{
deleted_at: current_time_from_proper_timezone,
active: nil
}
end
end

class NonParanoidModel < ActiveRecord::Base
end

Expand Down