简体   繁体   中英

How to replace exiting class in Rails console?

In console:

class Logger
end
l = Logger.new

Throws error: ArgumentError: wrong number of arguments (0 for 1) from /home/zzz/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/logger.rb:268:in 'initialize'

Why is it using the Logger in /home/zzz/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/logger.rb ?

I'll try to answer to your second question. So, why is Ruby using some other Logger class and not the one you tried to define yourself?

One of the fundamental features of Ruby is re-opening of classes. Let's say you have some class that is already defined and loaded in your app:

class A
  def foo
    puts 'foo'
  end
end

A.new.foo
#=> foo

If after that Ruby interpreter encounters something like:

class A
  def bar
    puts 'bar'
  end
end

it doesn't redefine class A , but simply appends this definition to the previous one. In the result already defined class A gets new instance method bar :

A.new.foo # still works
#=> foo
A.new.bar # new method
#=> bar

Because of the way Ruby handles methods calling, all instances of class A that were initialized before the second definition (actually, re-opening) of class A also get this new method bar . So every time you reopen a class you add new functionality to the class itself and to all previously initialized instances of this class.

Classes reopening also allows rewriting methods of an existing class:

class A
  def foo
    puts 'new foo'
  end
end

A.new.foo
#=> new_foo

With that feature in mind and the fact that Rails has already loaded standard Logger class for you, your definition only reopens the class, but doesn't even change anything.

That class was already loaded, presumably because rails was using it: you haven't redefined the class, you were merely re-opening it.

You could remove the existing class

Object.send(:remove_const, :Logger)

In this case the class formerly known as Logger still exists, it just isn't bound to the constant Logger any more, so when you do

class Logger
end

you'll be creating a new class not reopening the old one. You may of course end up breaking code that assumed the presence of the old Logger class.

If you're doing this in tests, you may be interested in the new constant stubbing in rspec 2.11

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM