Ruby 1.9.3 & # 8594; 2.0 alias_method and extends

I am trying to upgrade a Ruby 1.9.3 application to 2.0, and everything seems to have gone smoothly, with the exception of one hiccup. I wrote a module that I include in my models to override activerecord destroy. It pseudonizes the existing destroy method to destroy! and then overrides destroy to change the deleted_at to entries. Only when upgrading to ruby ​​2.0 destroy! no longer destroys the record, but behaves just like my new override method. Any idea why this would be? Below is a more relevant section of code. Full text here .

  def self.included(base) base.class_eval do alias_method :destroy!, :destroy alias_method :delete!, :delete default_scope -> { where(:deleted_at => nil) } end base.send :extend, ClassMethods base.send :include, InstanceMethods end 
+6
source share
3 answers

If you use a method that is not directly defined in the current class, then alias looks for the method in the closest ancestor of the class in which it was executed.

When you include Trashable::InstanceMethods in one of your models, it is inserted at the beginning of this chain of ancestors of this model. Hence the call to destroy! in this model, calls the destroy method on Trashable::InstanceMethods .

If you move def destroy from InstanceMethods to base.class_eval , then it will be defined in the inclusion model directly, and the closest ancestor of this model containing "destroy" will be the corresponding module in ActiveRecord. Therefore call destroy! will invoke SQL DELETE as expected.

See class.ancestors for further study of this behavior.

0
source

Look at the paranoia gem . This is a Rails 3/4 compliant soft deletion implementation that does what you need. If all you want to do is provide soft removal, I would use the gem and do away with it. If you want to implement soft deletions yourself, then the implementation may give you some idea of ​​how this was done before.

+1
source

In Ruby 2.0, they introduced the concept of add-on modules, so you can insert behavior between your model and ActiveRecord :: Base. I would suggest moving your code to a module, and instead of including this model, you can add it. Keeps smoothing methods around.

Here are some articles related to the new prepend functionality:

https://gist.github.com/mattetti/5104790

http://blog.crowdint.com/2012/11/05/3-killer-features-that-are-coming-on-ruby-2-0.html

http://dev.af83.com/2012/10/19/ruby-2-0-module-prepend.html

0
source

Source: https://habr.com/ru/post/958525/


All Articles