rubysherpas / paranoia

acts_as_paranoid for Rails 5, 6 and 7
Other
2.89k stars 528 forks source link

Act_as_paranoid for all models #198

Open krawa76 opened 9 years ago

krawa76 commented 9 years ago

Dear friends,

I'm trying to apply "paranoia" for all my app models, like this:

class MyModel < ActiveRecord::Base self.abstract_class = true acts_as_paranoid end

class Customer < MyModel ... end

Unfortunately this causes the "undefined method `to_sym' for nil:NilClass" exception fetching any data from the Customer model.

What am I doing wrong? :)

Regards, Serge.

elitenomad commented 9 years ago

May be you can try this....

Say you have a model Quality < ActiveRecord::Base and two dependent qualities ChoiceQuality < Quality and RangeQuality < Quality. Both has different associations and perform different functionalities in the app. Best way to proceed is to make sure acts_as_paranoid is added to subclasses instead of ParentClass.(I went with an assumption that only one database table exists and its name is Quality)

Class ChoiceQuality acts_as_paranoid has_many :quality_options, dependent: :destroy .... end

class RangeQuality acts_as_paranoid has_one :quality_integer_range, dependent: :destroy end

Let me know if this helps.

krawa76 commented 9 years ago

Yes, this works if I add acts_as_paranoid to the models.

However, I thought I could inherit all my models from some base abstract class and specify acts_as_paranoid in the base class so I don't have to do this in every model.

For some reason it doesn't work out, unfortunately.

elitenomad commented 9 years ago

:-) I think it makes sense as the base class can give rise to several child classes which will have different funcs and activemodel relationships. Making specific rows represented by a subclass soft deleted gives additional advantange. in my case i allow soft deletion of rows whose type is RangeQuality in the total Quality table represented by Quality Base class.

krawa76 commented 9 years ago

Well, it sounds reasonable to me to implement soft delete for all the models in the project (you see I'm extremely paranoid :), that's why I need this feature in the base class.

elitenomad commented 9 years ago

:-P

jerry-tao commented 9 years ago

Put this in your config/initializers/paranoia.rb

ActiveRecord::Base.module_eval do
  class << self
    def inherited_with_paranoid(subclass)
      skip_models = %w(schema_migrations)

      inherited_without_paranoid(subclass)

      table_name = subclass.table_name

      if !skip_models.include?(table_name) && table_name.present?
        subclass.send(:acts_as_paranoid)
      end
    end

    alias_method_chain :inherited, :paranoid
  end
end
h-z commented 8 years ago

We are experimenting with this approach:

class MyBaseModel < ActiveRecord::Base
    self.abstract_class = true
    def self.inherited(base)
        base.acts_as_paranoid
        super
    end
end

class MyCustomer < MyBaseModel
end

So far it works.