goncalossilva / acts_as_paranoid Goto Github PK
View Code? Open in Web Editor NEWActiveRecord (>=3.0) plugin which allows you to hide and restore records without actually deleting them.
License: MIT License
ActiveRecord (>=3.0) plugin which allows you to hide and restore records without actually deleting them.
License: MIT License
It would be appreciated to get a new gem out at least with the fix for the persisted?
check (#94).
We've been leaning on Github for bundling everything for a while now.
I guess I'm wondering if this will break if I include another AR plugin with a similar design? You are playing with default_scope and unscoped. For example if my other plugin also has its own default_scope, and I do a with_deleted operation, will the other plugin's default_scope (and/or any standard default_scope declaration) be defeated since with_deleted uses unscoped?
Greetings
I just realized that, even though a model is marked as paranoid, the uniqueness validations are not taking that into account explicitly:
class Bong < ActiveRecord::Base
has_many :tests
end
class Test < ActiveRecord::Base
acts_as_paranoid
belongs_to :bong
validates :bong_id, :uniqueness => { :scope => [:bong_id, :deleted_at] }
validates :bong_id, :uniqueness => { :scope => :bong_id }
end
first validation works. Second doesn't. I haven't tried with uniqueness => true, but chances are, it is also incorrect. Basically, I would like not to be explicit about deleted_at, since the model is already marked as paranoid, it should take this information into account.
Unfortunately can't find how to fix
cr = Contract.new
cr.contract_histories.build status: 'A'
cr.save!
cr is saved, history is not, active-record does not generate INSERT (both models are acts_as_paranoid and have relations :has_many and :belongs_to)
This is a tricky situation.
I want to allow users to access their destroyed resources via the web.
The polymorphic route generation in Rails checks to see if the model is persisted?
.
But persisted?
checks if it is not destroyed?
.
Maybe it would be best to change persisted?
to be true
and continue to have destroyed?
be dependent on paranoid_column
.
Could anyone provide instructions on how to upgrade my code to work with 0.4.0 from 0.2.2? I was running 0.2.5. Then I may have soft deleted a couple records (not totally sure, I didn't know this gem was enabled until recently). When I went to update my Gemfile to 0.4.0 I kept getting
.rvm/gems/ruby-1.9.3-p194/bin/ruby_noexec_wrapper:14: stack level too deep (SystemStackError)
And rails wouldn't start. I rolled back to 0.2.5, but it still wasn't working. I then rolled back one minor version at a time and I can run 0.2.2 just fine, but if I try to upgrade to 0.2.3 I get stack level too deep errors. Any code upgrade advice would be greatly appreciated as it's a fairly large codebase I'm working with. Happy to provide more details if needed.
More specifically I'm trying to ultimately fix this code which is supposed to permanently destroy and Incexp object and its dependent objects(installments) permanently.
def destroy_with_installments_permanently!
Incexp.transaction do
installments.each do |i|
i.destroy!
end
self.installments(true)
self.destroy!
end
end
Getting the following error:
NoMethodError (undefined method start_date' for nil:NilClass): app/models/audit_observer.rb:166:in
object_description'
app/models/audit_observer.rb:54:in after_destroy' app/models/incexp.rb:58:in
block (2 levels) in destroy_with_installments_permanently!'
app/models/incexp.rb:57:in block in destroy_with_installments_permanently!' app/models/incexp.rb:56:in
destroy_with_installments_permanently!'
app/controllers/ledger_controller.rb:62:in delete' app/controllers/application_controller.rb:148:in
log_audit_events'
I thought a more recent version of the code would have fixed this bug and I could simply call self.destroy! in the method.
Shouldn't the default column type be datetime instead of time. That way you could retrieve all deleted records based on day, month, and year. instead of time. Who retrieves archived records 2 minutes from now. You retrieve archived records days, months, and even years from now!
Rails 3.2.13 has deprecated before_destroy callbacks so this line:
https://github.com/goncalossilva/acts_as_paranoid/blob/rails3.2/lib/acts_as_paranoid/core.rb#L107 will try to run destroy callbacks but it not work because the destroy callbacks are deprecated. instead of:
run_callbacks :destroy do
do this:
run_callbacks :save do
Because it is not a destroy action, it is an update.
This is my suggestion https://gist.github.com/victorhazbunanuff/5777082
Thanks!
I can't see a way around the N+1 problem without using :includes in my Active Record queries. Per the documentation:
class ParanoiacParent < ActiveRecord::Base
has_many :children, :class_name => "ParanoiacChild"
end
class ParanoiacChild < ActiveRecord::Base
belongs_to :parent, :class_name => "ParanoiacParent"
belongs_to :parent_with_deleted, :class_name => "ParanoiacParent", :with_deleted => true
end
However if the following is called in a controller:
@paranoiac_children = ParanoiacChild.includes(:parent_with_deleted).all
The log load statement shows a "('paranoiac_parents'.'deleted_at' IS NULL)" in the WHERE clause resulting in undefined method
errors. I guess I'm forced to avoid using :includes. Is this behavior by design?
In other words, an alternative to calling the #with_deleted method before the find call.
Thanks
I have a relation in model Advertiser
has_and_belongs_to_many :agencies
In advertiser's edit form, I have multiselect for :agency_ids and I would like to see deleted agencies here too (if they were assigned and then deleted)
= f.select :agency_ids, Agency.all.collect{|f| [f.name, f.id]}, {}, {:multiple => true, :size => 5}
I need something like
has_and_belongs_to_many :agencies, :with_deleted => true
This work already for has_many
and belongs_to
, but it is missing for has_and_belongs_to_many
.
After the latest update of this gem, I can't migrate my db. Error is:
undefined local variable or method
`acts_as_paranoid' for User(Table doesn't exist):Class
Before update all works greate!
problem with devise route:
devise_for :users, :path_prefix => 'd', :controllers => { :registrations => :registrations, :omniauth_callbacks => "users/omniauth_callbacks" }
ActionController::RoutingError (undefined local variable or method `acts_as_paranoid' for #<Class:0xc4a01d0>):
# encoding: utf-8
class User < ActiveRecord::Base
acts_as_paranoid
end
tl;dr - We add acts as paranoid. Its doing soft deletes correctly, but updates with models with many associations are taking a long time or stalling.
We are working with a data model with many nested level associations -- a person has many dogs, dogs has many toys, toys has many properties, etc. Each of these models has acts_as_paranoid setup correctly on themselves.
When we have a person that has lots of dogs, who have lots of toys, etc, and try to update the name of a person and then save, the save stalls. Our logs show no SQL queries happening and nothing is getting destroyed.
We just wanted to ask, if anyone else had experienced a similar behavior? We are still investigating the problem, but wanted to start a dialog of our findings.
_
Maybe try to extend ActiveSupport::Concern instead of using class_eval so heavily. Good work though!
We use this plugin with Rails 3.1 but due to the way the plugin initializes itself we get an error whilst running the 'rake assets:precompile' task on deployment to Heroku.
Essentially the plugin forces ActiveRecord to be loaded during initialization, which in turn forces a database connection to be attempted. This probably doesn't matter that much when deploying elsewhere but Heroku builds a 'slug' with all the precompiled assets - at which point the database connection isn't available.
See: http://devcenter.heroku.com/articles/rails31_heroku_cedar#troubleshooting
If the initialization stuff could be rewritten to use Railties it would work nicely on Heroku. Will_paginate is a nice example of this.
Cheers!
Hi,
When I try to update a deleted record the guard sql clause get appended:
>> initiative.update_column(:organization_id, organization.id)
SQL (24.6ms) UPDATE `product` SET `organization_id` = 30685 WHERE `product`.`id` = 8 AND (`product`.`deleted` = 0)
=> false
the only workaround I found is:
>> Initiative.with_deleted.where(id: initiative.id).update_all(organization_id: organization.id)
SQL (35.3ms) UPDATE `product` SET organization_id = 30685 WHERE `product`.`id` = 8
Am I missing something ?
Regards.
I'm running Rails 3.0.1 and on some of my large table I noticed some slowness when using #with_deleted. I do the following to show the queries that are being executed:
ActiveRecord::Base.logger = Logger.new(STDOUT)
And when I use #with_deleted I see it selecting * from every row in the table before moving onto the real query. I think this has to do with the following change:
Is it possible to change the "reload" back to "where" but put an empty string as an argument (as in: ".where('')")? I'm not sure which tests were failing. This works for me and doesn't cause the query of the whole table. Is there a better solution, perhaps?
I was using this plugin with my rails3 app on ruby 1.9.2 and found that recovering a deleted record and after_destroy callback are not working.
I have a parent model call Member which has many memberhips. I am not using dependent => :destroy but when I using nested-attributes by assigning:
'memberships_attributes' => {'0' => {'_destroy' => '1'}}
It will still do a hard destroy. Is there something that I am doing wrong?
I'm running 1.9.2-p180 with RoR 3.0.9
In some cases Rails decides what to do based on a record being persisted?
, for example in UniquenessValidator. The specific situation I have is updating a deleted record that has a :unique
validation.
The problem is that if a record is "deleted" (== destroyed?
) then it doesn't consider the existing record as the same one to be updated.
I'm thinking to remove the :destroyed?
alias and just depend on :deleted?
from ActsAsParanoid, and let Rails keep :destroyed?
The other option might be to also override persisted?
. Any thoughts?
This is my scenario.
class Message < ActiveRecord::Base
belongs_to :user, :foreign_key => "from_user_id"
has_many :message_recipients, :include => [:user], :dependent => :destroy
has_many :recipients, :through => :message_recipients, :source => :user
end
class MessageRecipient < ActiveRecord::Base
belongs_to :user
belongs_to :message, :include => :message_recipients
end
class User < ActiveRecord::Base
acts_as_paranoid
has_many :message_recipients
end
@test=Message.new
@test.name="Test";
@test.recipients.push(User.find(1))
@test.save
Without paranoid: The above code works fine if i remove acts_as_paranoid from user model.
WIth paranoid: It saves only the parent record(Message) but fails to save the child record(MessageRecipient) in rails 3.2.13.But the same code works fine with rails 3.2.12. It seems to be a wierd behaviour.
Here is an example:
Installation.deleted_after_time(Time.now)
this will produce
SELECT "installations".* FROM "installations"
WHERE ("installations"."deleted_at" IS NULL) AND (deleted_at > '2013-04-02 05:29:26.156025')
As you can see from WHERE clause that it will never return values.
Are you using any US-ASCII character in your code or comments? We got an invalid byte sequence in US-ASCII (ArgumentError) while trying to install this in an EngineYard server(confirmed this by commenting out rails3-acts-as-paranoid from Gemfile)
It seems that EngineYard is not(or IS) using UTF8(dunno about locales that much to understand the problem) but it seems you are using an invalid character on your code? It does work on my local, but just wanted to ask what this was all about.
Hi Hi,
I just found a nuisance concerning writing scopes. Lets say I have a Class1, and a Class2 that is paranoid. If somehow I end up writing a scope (or for that matter, just using plain ARel) in the Class1 that joins with Class2, and if instead of writing the SQL myself, I use the symbolic way of writing it, the deleted_at condition doesn't get added. Something like this:
class Class1 < ActiveRecord::Base
has_many :class2s
scope with_class2s, joins(:class2s).where(:field1 => true)
end
just by using the to_sql function, you can see that the condition " AND 'class2'.'deleted_at' IS NULL " isn't part of the ON condition block from the INNER JOIN. Is there a way to fix that?
Cheers,
Tiago
Dirty tracking doesn't seem to work properly in the after_recover callback:
before_recover :do_something_before
after_recover :do_something_after
def do_something_before
deleted_at # => 2013-07-01 10:58:49
end
def do_something_after
deleted_at # => nil
deleted_at_changed? # => false, should be true
deleted_at_was? # => nil, should be 2013-07-01 10:58:49
end
Is this expected behaviour? It feels like I should be able to access the old deleted_at timestamp in the after_recover callback because it is still part of the record's lifecycle.
It's weird that validates_uniqueness_of_without_deleted does not work on Rails 3.2 on my local, I use PostgreSQL 9.2 database
Here is in my user model
validates_as_paranoid
validates_presence_of :username
validates_uniqueness_of_without_deleted :username
validates_length_of :username, :within => 3..20
validates_presence_of :email, :on => :create
validates_uniqueness_of_without_deleted :email
And here is from console
[root@localhost yutongo]# rails c
Loading development environment (Rails 3.2.13)
1.9.3p429 :001 > User.where(:username => "lungtung")
User Load (1.3ms) SELECT "users".* FROM "users" WHERE "users"."username" = 'lungtung' AND ("users"."deleted_at" IS NULL)
=> []
1.9.3p429 :002 > u = User.create(:username => "lungtung", :email => "[email protected]", :password => "123123", :password_confirmation => "123123", :first_name => "Lung", :last_name => "Tung")
(0.4ms) BEGIN
User Exists (1.2ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('[email protected]') LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."username") = LOWER('lungtung') LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."persistence_token" = '10c17c557b1cad788e7899814f3775dbee96ddcfc9e3303366d520352a2b8d0aeeab87c1d7f77e6214895e5f06b43f4a6b6744b8f9a4c13ea8750946cfc0b291' LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."single_access_token" = 'c28EpYl9H7xaWsyUnL8' LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = 'lungtung' AND ("users"."deleted_at" IS NULL) LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' AND ("users"."deleted_at" IS NULL) LIMIT 1
(2.1ms) ROLLBACK
=> #<User id: nil, username: "lungtung", first_name: "Lung", string: nil, last_name: "Tung", email: "[email protected]", crypted_password: "19f93a82f7fd26b4589c4da100d68978ea2dea5c435c0c25c45...", password_salt: "G2IpO17Fx4QbEuYZY2lW"deleted_at: nil>
1.9.3p429 :003 > u.errors.full_messages
=> ["Email has already been taken", "Username has already been taken"]
Does anyone knows why?
Great gem!
I'm running into an issue where I can destroy models and their associations just fine, but when I do a recover on the parent it is not recovering the children as well. The parent is recovered just fine.
In my sandbox I have narrowed this behavior down to a conflict with the 'acts_as_tenant' gem.
Basically when I have my Child model roughly:
class Child::AR
belongs_to :Parent
acts_as_tenant(:account)
acts_as_paranoid
it is NOT recovered when recover the parent. The parent model has:
class Parent::AR
has_many :Child, :dependent => :destroy
acts_as_tenant(:account)
acts_as_paranoid
When I comment out the acts_as_tenant, it recovers just fine.
I'm thinking acts_as_tenant is messing with the scoping (but weird that it's only doing it on the children, not the parent.)
Any ideas on how I can get around this issue?
Many thanks for the great gem!
Could you provide a gemspec file for installing it via rubygems?
Thx
# it's ok
Model.last.to_param
link_to 'Model item', Model.last
# exeption
Model.select(:id).last.to_param
link_to 'Model item', Model.select(:id).last
ActionView::Template::Error (missing attribute: deleted_at):
You can't truly be paranoid without being able to go on witch hunts, commie cleansings, and general finger-pointing. It'd be nice to have built support for tracking who's responsible for deletions with some helpers, such as
acts_as_paranoid :responsible => 'users', :responsible_column => 'deleted_by'
# Attributes on paranoid instances
Paranoiac.with_deleted.first.deleted_by
#=> #<User 234234234>
Paranoiac.with_deleted.first.deleted_by?(User.first)
#=> true
# Scope on paranoid models
# All paranoiacs User has ever deleted, recovered or not
Paranoiac.deleted_by(User.first)
#=> [ #<Paranoiac 123412341>, #<Paranoiac 0945890456>, #<Paranoiac 999999999> ]
# All paranoiacs User has currently deleted
Paranoiac.with_deleted.deleted_by(User.first)
#=> [ #<Paranoiac 123412341>, #<Paranoiac 0945890456> ]
# Mass paranoia!
Paranoiac.with_deleted.deleted_by(User.first, User.last)
#=> [ #<Paranoiac 123412341>, #<Paranoiac 0945890456>, #<Paranoiac 456983543> ]
When trying to use :with_deleted on a has_many I get an error.
Code:
has_many :phone_numbers, :autosave => true, :validate => true, :dependent => :destroy, :with_deleted => true
Error:
/sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/core_ext/hash/keys.rb:51:in block in assert_valid_keys': Unknown key: with_deleted (ArgumentError) from /sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/core_ext/hash/keys.rb:50:in
each_key'
from /sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/core_ext/hash/keys.rb:50:in assert_valid_keys' from /sharehome/billinb/gem/gems/activerecord-3.2.8/lib/active_record/associations/builder/association.rb:33:in
validate_options'
from /sharehome/billinb/gem/gems/activerecord-3.2.8/lib/active_record/associations/builder/association.rb:24:in build' from /sharehome/billinb/gem/gems/activerecord-3.2.8/lib/active_record/associations/builder/collection_association.rb:23:in
build'
from /sharehome/billinb/gem/gems/activerecord-3.2.8/lib/active_record/autosave_association.rb:139:in build' from /sharehome/billinb/gem/gems/activerecord-3.2.8/lib/active_record/associations/builder/has_many.rb:10:in
build'
from /sharehome/billinb/gem/gems/activerecord-3.2.8/lib/active_record/associations/builder/collection_association.rb:13:in build' from /sharehome/billinb/gem/gems/activerecord-3.2.8/lib/active_record/associations.rb:1195:in
has_many'
from /sharehome/billinb/workspace/edb/app/models/contact.rb:23:in <class:Contact>' from /sharehome/billinb/workspace/edb/app/models/contact.rb:1:in
<top (required)>'
from /sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:251:in require' from /sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:251:in
block in require'
from /sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:236:in load_dependency' from /sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:251:in
require'
from /sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:359:in require_or_load' from /sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:313:in
depend_on'
from /sharehome/billinb/gem/gems/activesupport-3.2.8/lib/active_support/dependencies.rb:225:in require_dependency' from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/engine.rb:439:in
block (2 levels) in eager_load!'
from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/engine.rb:438:in each' from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/engine.rb:438:in
block in eager_load!'
from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/engine.rb:436:in each' from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/engine.rb:436:in
eager_load!'
from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/application/finisher.rb:53:in block in <module:Finisher>' from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/initializable.rb:30:in
instance_exec'
from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/initializable.rb:30:in run' from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/initializable.rb:55:in
block in run_initializers'
from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/initializable.rb:54:in each' from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/initializable.rb:54:in
run_initializers'
from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/application.rb:136:in initialize!' from /sharehome/billinb/gem/gems/railties-3.2.8/lib/rails/railtie/configurable.rb:30:in
method_missing'
from /sharehome/billinb/workspace/edb/config/environment.rb:5:in <top (required)>' from /sharehome/billinb/workspace/edb/test/test_helper.rb:2:in
require'
from /sharehome/billinb/workspace/edb/test/test_helper.rb:2:in <top (required)>' from /sharehome/billinb/workspace/edb/test/unit/contact_test.rb:1:in
require'
from /sharehome/billinb/workspace/edb/test/unit/contact_test.rb:1:in <top (required)>' from /sharehome/billinb/gem/gems/rake-0.9.2.2/lib/rake/rake_test_loader.rb:15:in
require'
from /sharehome/billinb/gem/gems/rake-0.9.2.2/lib/rake/rake_test_loader.rb:15:in block in <main>' from /sharehome/billinb/gem/gems/rake-0.9.2.2/lib/rake/rake_test_loader.rb:4:in
select'
from /sharehome/billinb/gem/gems/rake-0.9.2.2/lib/rake/rake_test_loader.rb:4:in `
Hi,
I have an issue with the name. Currently I am bundling a Sinatra Gem with AR3, and I need my models to be paranoid. And this gem has been doing the gem. Granted, it's still not deployed, maybe I'm forgetting some dependency. But if all goes well and it indeed all runs well, I don't see why I have to have a gem rails3-prefixed in a sinatra app. I can see the issues with the renaming (projects depending on it, etc.) but I'd say it'd be more consistent. Please tell me what u think.
Regards
Tiago
I don't want my :deleted_at column to be in attr_accessible columns.
How about this? :)
Acts_as_paranoid is not picking association model condition,
e.g
object = Opportunity.with_deleted.find(2)
log : Opportunity Load (1.4ms) SELECT "opportunities".* FROM "opportunities" WHERE "opportunities"."id" = 2 LIMIT 1object.comments.where("title in ('Comment','Note')").order("created_at DESC")
log : SELECT "comments".* FROM "comments" WHERE (comments.deleted_at IS NULL) AND ("comments".commentable_id = 2 AND "comments".commentable_type = 'Opportunity') AND (title in ('Comment','Note')) ORDER BY created_at DESCobject.comments.with_deleted.where("title in ('Comment','Note')").order("created_at DESC")
log : SELECT "comments".* FROM "comments" WHERE (title in ('Comment','Note')) ORDER BY created_at DESC
Now as we see when I use with_deleted it is not passing objects condition to comment.
object.comments.where pass condition (comments.deleted_at IS NULL) AND ("comments".commentable_id = 2 AND "comments".commentable_type = 'Opportunity') like object.comments.with_deleted.where should pass
NoMethodError (undefined method `mount_sql_and_params' for #ParanoidValidations:UniquenessWithoutDeletedValidator:0x11e79418):
please it's more easy to use different version of your plugin if new version create bugs on our project.
thanks again !
I have models Client, User and ClientUser with following associations:
https://gist.github.com/793920
ruby-1.8.7-p302 > Client.first.client_users.count
=> 3
ruby-1.8.7-p302 > Client.first.users.count
=> 3
ruby-1.8.7-p302 > Client.first.client_users.last.destroy
=> 1
ruby-1.8.7-p302 > Client.first.client_users.count
=> 2
ruby-1.8.7-p302 > Client.first.users.count
=> 3
ruby-1.8.7-p302 >
As you see, deleted_at field not affect on has_many :through association
This would substitute unscoped()
on paranoid models.
Say I have a model:
class Attachment < ActiveRecord::Base
acts_as_paranoid
end
and another
class Photo < Attachment
end
When I try to do a Photo.destroy it fails on the command Photo.paranoid_column. I tried adding acts_as_paranoid to the Photo class as well, but it still errors out. The only way I could get Photo to have acts_as_paranoid working was removing it from the attachment model and only including it in the Photo model. Let me know if you need any more information. Great work other than that ;)
acts_as_paranoid :mass_assignable => true
Hi,
I noticed that you have the following lines:
default_scope where("#{paranoid_column_reference} IS ?", nil) # Magic!
and
def only_deleted
self.unscoped.where("#{paranoid_column_reference} IS NOT ?", nil)
end
This would work ok for relatively smaller table, but not a huge one, where I would add index for is_deleted field.
Could you please add the support for is_deleted field and assuming the default to be set to false rather than NULL?
Thanks
-lei
Let's say we have a model
class Article
acts_as_paranoid
scope :latest, order('created_at DESC')
end
Then
Article.with_deleted.latest
produces only undeleted articles, and
Article.latest.with_deleted
produces all articles, including deleted ones, but without any ordering.
This is expectable since with_deleted
is basically an alias to unscoped
, but it's not the right nor the obvious way how this scope should work.
I have an issue when I fetch only an attribute subset from my paranoid model using
Object.select([:id, :relation_id, :type]).first
on a PostgreSQL DB, which return only an instance with these attributes, and when I try to generate a route for this instance, acts_as_paraonoid break since the column :deteled_at is not present
# acts_as_paranoid/core.rb - line 70
def paranoid_value
self.send(self.class.paranoid_column)
end
Should I had the deleted_at attribute in my select each time ? Or should the core of acts_as_paranoid check if the instance respond to :deteled_at ?
Have a model in Rails 3.2.6, Ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.4.0] like:
class SomeModel < ActiveRecord::Base
set_primary_key :some_id
acts_as_paranoid column: 'some_column', column_type: 'string', deleted_value: 'some_value'
has_many :other_models
end
There are four rows of data in this table and the value in some_column is populated but is not 'some_value'. However, SomeModel.count returns 0 when using latest rails3_acts_as_paranoid 0.2.4. If I comment acts_as_paranoid in the model, then SomeModel.count returns 4.
How to reproduce:
class Parent < ActiveRecord::Base
acts_as_paranoid
has_many :children
end
class Child < ActiveRecord::Base
belongs_to :parent
acts_as_paranoid
default_scope includes(:parent).order('parents.position DESC')
end
When you try to destroy a Child, it can't because the default scope is not called:
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'parents.position' in 'order clause': UPDATE `children` SET deleted_at = '2013-05-10 15:41:09' WHERE `children`.`id` = 5 ORDER BY parents.position ASC
Can anyone reproduce it?
Thanks.
Hi,
Let's assume we have theses 2 classes:
Class Thing < ActiveRecord::Base
acts_as_paranoid
end
Class Example < ActiveRecord::Base
has_many :things
end
Now calling Example.new.things.with_deleted returns all Thing records in db, instead of none...
SQL: "SELECT things
.* FROM things
WHERE things
.example_id
IS NULL"
I need to create a deleted object.
Code: record = Mymodel.create(:name => "obj_name", :deleted_at => DateTime.now)
results in: ActiveRecord::RecordNotSaved: You cannot call create unless the parent is saved
I use ruby 1.8.7, rails 3.1.11 and "rails3_acts_as_paranoid", "> 0.1.4"> 0.0.9"
It did work fine with 'rails', '3.0.20' and "rails3_acts_as_paranoid", "
Hi,
I'm having some issues with the with_deleted option. First, I can't seem to use it in classes that are not paranoid. Well, I think I should do that, because in such cases the association should be paranoid. Something like this:
class NotParanoid < ActiveRecord::Base
# not calling acts_as_paranoid here
:belongs_to :paranoid_object, :with_deleted => true
end
I found a workaround, which was to include the following line:
include ActsAsParanoid::Associations
right before the association definition. Still, I think that the belongs_to_with_deleted options should be included in AR, and not only made acessible when one calls acts_as_paranoid. This was at least the behaviour in rails 2, which was quite alright semantically.
Another issue is that it doesn't work very well for the polymorphic case. Consider this definition:
class NotParanoid < ActiveRecord::Base
include ActsAsParanoid::Associations
:belongs_to :paranoid_object, :polymorphic => true, :with_deleted => true
end
paranoid_android = NotParanoid.new
paranoid_android.paranoid_object
#=> NoMethodError: undefined method `paranoid?' for nil:NilClass
from /Users/tiagocardoso/Projects/restorm-com/vendor/bundler_gems/ruby/1.8/gems/rails3_acts_as_paranoid-0.2.2/lib/acts_as_paranoid/associations.rb:19:in `changeable'
as you can see in the source code, this error comes from line 20 of the associations.rb file:
return #{target}_without_unscoped(*args) unless association(:#{target}).klass.paranoid?
so, what's missing here (and correct me if I'm wrong) is to check the options parameter of the association (to see if it is polymorphic) and see if by any chance the class is defined by a field from the object. So, I would replace this line with:
asso = association(:#{target})
klass = if asso.options[:polymorphic]
klass = asso.owner.send(:#{target}_type)
klass.constantize unless klass.nil?
else
asso.klass
end
return nil if klass.nil?
return #{target}_without_unscoped(*args) unless klass.paranoid?
it can get syntactically prettier, but it works. So, tell me what you think of this.
Abraço,
Tiago
ActsAsParanoid::Associations
is only added to class acting as paranoid.
To get a non paranoid class to belong_to :with_deleted => true
you have to include ActsAsParanoid::Associations
.
class MyClassWithoutActsAsParanoid < ActiveRecord::Base
include ActsAsParanoid::Associations
belongs_to :paranoiac_model, :with_deleted => true
end
What about including ActsAsParanoid::Associations
to ActiveRecord::Base
by default?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.