I am trying to disable the unused method in gem that is present in my rails app. Is it possible?
You can use remove_method http://apidock.com/ruby/Module/remove_method
I'm curious why you want to do this though.
You can override the method and let it behave differently or the below ruby built in approach:
undef_method http://ruby-doc.org/core-2.0.0/Module.html#method-i-undef_method
or
remove_method http://ruby-doc.org/core-2.0.0/Module.html#remove_method-method
If you want to remove method from the particular class (not from the ancestors) you should use remove_method.
If also you want to search superclasses and mixed-in modules for a receiver then use undef_method.
There's also undef keyword which acts similar as remove_method but probably a bit faster. It receives method name (not symbol or string).
Usage:
class Parent
def foo; end
def baz; end
end
class Child < Parent
def bar; end
end
Child.send :remove_method, :bar # I use send for space-economy.
# You should reopen the class
Child.new.bar # => NoMethodError
Child.send :remove_method, :foo # NameError: method `foo' not defined in Child
Child.send :undef_method, :foo
Child.new.foo # => NoMethodError
Parent.class_eval { undef baz }
Parent.new.baz # => NoMethodError
Related
A few days ago, when I looked up my Dash documents, I found a weird ruby code snippet.
include Process
fork { exit 99 } #=> 27429
wait #=> 27429
$?.exitstatus #=> 99
The thing shocked me is why the Object class get the 'wait' instance method when it include the Process mudule. the Process module has only a class method 'wait' as the document indicated.
Many Ruby stdlib modules are written in a way that allows one to use either:
FileUtils.mkdir_p
or
include FileUtils
mkdir_p
This is done by using module_function:
module FileUtils
def mkdir_p(*args)
...
end
module_function :mkdir_p
end
This makes it possible to use the method as a class method with FileUtils.mkdir_p and as an instance method mkdir_p when included. It makes the instance method private when included:
class Foo
include FileUtils
def test
mkdir_p
end
end
Foo.mkdir_p # => NoMethodError (undefined method `mkdir_p`...
Foo.new.mkdir_p # => NoMethodError (private method `mkdir_p`...
Foo.new.test # => no problem there
It's also possible to make module functions private by using module_function together with private_class_method:
module AlarmClock
def is_it_time?
morning_yet?
end
module_function :is_it_time?
def morning_yet?
(7..11).cover?(Time.now.hour)
end
module_function :morning_yet?
private_class_method :morning_yet?
end
Now you have a public module function which uses a private module function and your module is still includable and usable in another class/module:
AlarmClock.morning_yet? # => NoMethodError (private method `morning_yet?' ..
AlarmClock.is_it_time? # => true
class WristWatch
include AlarmClock
def start_beeping
return "beep" if is_it_time?
end
def stop_beeping
return "silence" if !morning_yet?
end
end
WristWatch.new.morning_yet? # => NoMethodError (private ..
WristWatch.new.is_it_time? # => NoMethodError (private ..
WristWatch.new.start_beeping => "beep"
WristWatch.new.stop_beeping "silence"
Some stdlib modules have a helper method for not having to write two extra lines, for example fileutils.rb:
module FileUtils
def self.private_module_function(name) #:nodoc:
module_function name
private_class_method name
end
...
end
Process is built-in and written in C, so it does not come from something like process.rb, but I assume it has been written in a similiar manner.
Wait is an instance method of class Concurrent::Event which in turn is inherting from Module whose superclass is Object, thus you are able to access wait method.
For Reference:
https://www.rubydoc.info/github/ruby-concurrency/concurrent-ruby/Concurrent%2FEvent:wait.
I'm creating a class (say, Bar) for an object to be returned by a method of another class (say, Foo#bar), pretty much MatchData object is returned by Regexp#match.
But the class MatchData does not have .new!
I know I don't need to imitate MatchData implementation, but I'd like to understand it and know how to do it when I find it interesting. Suppose I don't want clients creating Bar objects unless by calling Foo#bar.
Questions:
Internally, how is MatchData object created without .new?
How can I implement it (imitating MatchData or not)?
The MatchData.new method is being explicitly undefined:
rb_cMatch = rb_define_class("MatchData", rb_cObject);
rb_define_alloc_func(rb_cMatch, match_alloc);
rb_undef_method(CLASS_OF(rb_cMatch), "new"); // <- here
You can do the same in pure Ruby via undef_method:
class Bar
class << self
undef_method :new
end
def initialize
#bar = '123' # <- for demonstration purposes
end
end
Trying to call Bar.new will now result in an error:
Bar.new #=> undefined method `new' for Bar:Class (NoMethodError)
To create a new instance without a new method, you can call allocate manually (and maybe initialize, too):
bar = Bar.allocate #=> #<Bar:0x007f9eba047cd8>
Bar.send(:initialize) #=> "123"
bar #=> #<Bar:0x007fd8e0847658 #bar="123">
(send is needed because initialize is private)
Let me start with that you shouldn't. It's arubyic to go out of your way to constraint users to do what they want to do even if it's not public interface. A more idiomatic approach would be make it more explicit that it's not part of the public interface. You can do that by making the class private:
class RegexMockery
class MatchDataMockery
def initialize(whatever)
puts "I'm being created #{whatever}"
end
def [](_)
'42'
end
end
private_constant :MatchDataMockery
def match(string)
MatchDataMockery.new(string)
end
end
match_result = RegexMockery.new.match('foo')
# I'm being created foo
# => #<RegexMockery::MatchDataMockery:0x007fe990de2ed0>
match_result[0] # => '42'
RegexMockery::MatchDataMockery # !> NameError: private constant RegexMockery::MatchDataMockery referenced
But if you insist on people hating you, save the method, undef it and call it whenever you want to create instances:
class Foo
def initialize(whatever)
puts "Now you see me #{whatever}"
end
def brag
puts "I can create Foos and you can't!!!1!!"
end
end
class Bar
foos_new = Foo.method(:new)
Foo.singleton_class.send :undef_method, :new
define_method(:sorcery) do
foos_new.call('bar').brag
end
end
Bar.new.sorcery
# Now you see me bar
# I can create Foos and you can't!!!1!!
Foo.new # !> NoMethodError: undefined method `new' for Foo:Class
I am writing a method that will define an instance method inside a class; something similar to attr_accessor:
class Foo
custom_method(:foo)
end
I have implemented that by adding custom_method function to the Module module, and defining the method with define_method, which works fine. But I cannot figure out how to take into account visibility attributes from the class. For example, in the following class
class Foo
custom_method(:foo)
private
custom_method(:bar)
end
the first generated method (foo) must be public, and the second one (bar) must be private. How do I do that? Or, how do I find the context in which my custom_method is called: private, public, or protected?
Thanks!
After experimenting with this for a bit, I'm completely baffled. Initially, I thought that Ruby took the default visibility (public, private, or protected) into account when you call Module#define_method. It turns out though that on Ruby versions <= 2.0, that's not the case:
class Foo
private
define_method :foo do
puts "Foo called!"
end
end
Foo.new.foo # Prints "Foo called!"
On Ruby 2.1+, it's even more confusing. Module#define_method seems to take default method visibility into account:
class Foo
private
define_method :foo do
puts "Foo called!"
end
end
Foo.new.foo # NoMethodError: private method `foo' called for #<Foo:0x8cb75ac>
But it only works when you are calling define_method from directly inside the class. Calling a method which then calls define_method doesn't work:
class Foo
def self.hello_on name
define_method name do
puts "Hello, #{name}!"
end
end
private
hello_on :foo
end
Foo.new.foo # Prints "Hello, foo!"
Dang it Ruby! Why?
Okay, this calls for desperate measures...
module DefaultMethodVisibilityAccessor
attr_reader :current_default_method_visibility
def public(*args)
#current_default_method_visibility = :public if args.empty?
super
end
def protected(*args)
#current_default_method_visibility = :protected if args.empty?
super
end
def private(*args)
#current_default_method_visibility = :private if args.empty?
super
end
end
class Module
prepend DefaultMethodVisibilityAccessor
end
module MethodDefiner
def hello_on name
define_method name do
puts "Hello, #{name}!"
end
case current_default_method_visibility
when :public
public name
when :protected
protected name
when :private
private name
end
end
end
Usage:
class Foo
extend MethodDefiner
hello_on :foo
private
hello_on :bar
end
Foo.new.foo # Prints "Hello, foo!"
Foo.new.bar # NoMethodError: private method `bar' called for #<Foo:0x8ec18fc>
There, fixed!
I think this is impossible, because the scope visibility level set by Module.private is managed at the C virtual machine level and not exposed to Ruby.
EDIT: and it's only available in the same syntactical scope that it is called, so when you call custom_method it loses the visibility level set inside the class declaration.
It's set in set_visibility(), and used in vm_define_method(), but I can't find any reference to the corresponding variable being available from Ruby.
I suggest using some kind of custom parameter to specify the visibility level of your methods.
You can use Module#private_method_defined? to verify if a method is defined as private
Suppose I want to override a method of an existing class Array as below.
class Array
def to_s
self.join(',')
end
end
So my question is - How does this overriding work? Does this add this definition of method to_s to the class Array? I mean if the class contained 'n' method definitions, it would now contain 'n+1' method definitions. Also, is it that there are two definitions of to_s method and the one that is added last is the one that would work?
Thanks.
You aren't overriding the method, you are re-defining it. The one that was there is gone, replaced with what you put in. This is a risky thing to do w/the standard libraries, you don't know what behavior other code is relying upon.
You can try it w/your own class.
class Foo
def bar
puts 'One'
end
end
class Foo
def bar
puts 'Two'
end
end
Foo.new.bar
# Two
class Foo
def bar
puts 'Three'
super
end
end
Foo.new.bar
# Three
# test.rb:18:in `bar': super: no superclass method `bar'
# for #<Foo:0x007fd642029278> (NoMethodError)
I have a Ruby module for constants. It has a list of variables and one method which applies formatting.
I can't seem to access the method in this module. Any idea why?
If you include the module the method becomes an instance method but if you extend the module then it becomes a class method.
module Const
def format
puts 'Done!'
end
end
class Car
include Const
end
Car.new.format # Done!
Car.format # NoMethodError: undefined method format for Car:Class
class Bus
extend Const
end
Bus.format # Done!
Bus.new.format # NoMethodError: undefined method format
module Foo
def self.hello # This is a class method
puts "self.hello"
end
def hello # When you include this module, it becomes an instance method
puts "hello"
end
end
Foo.hello #=> self.hello
class Bar
include Foo
end
Bar.new.hello #=> hello
Generally, with modules, these things should be happening :
Autoload path in application.rb, add:
config.autoload_paths += %W(#{config.root}/lib)
Place module in /lib
Include module with include NAMEOFMODULE
If the module name has an underscore like "game_engine", you need to use include GameEngine