How Are Respond_To and Respond_To_Missing Different

`respond_to?` vs. `respond_to_missing?`

Without respond_to_missing? defined, trying to get the method via method will fail:

class Foo
def method_missing name, *args
p args
end

def respond_to? name, include_private = false
true
end
end

f = Foo.new
f.bar #=> []
f.respond_to? :bar #=> true
f.method :bar # NameError: undefined method `bar' for class `Foo'

class Foo
def respond_to? *args; super; end # “Reverting” previous redefinition

def respond_to_missing? *args
true
end
end

f.method :bar #=> #<Method: Foo#bar>

Marc-André (a Ruby core committer) has a good blog post on respond_to_missing?.

Ruby respond_to_missing? Call super or not?

It depends on the implementation of the class and the behavior you want out of #respond_to_missing?. Looking at ActiveSupport::TimeWithZone, it is a proxy wrapper for Time. It tries to mimic it, fooling you into thinking it is an instance of Time. TimeWithZone#is_a? would respond true when passed Time, for example.

# Say we're a Time to thwart type checking.
def is_a?(klass)
klass == ::Time || super
end
alias_method :kind_of?, :is_a?

respond_to_missing? should catch cases that would be caught by method_missing, so you have to look at both methods. TimeWithZone#method_missing delegates missing methods to Time instead of super.

def method_missing(sym, *args, &block)
wrap_with_time_zone time.__send__(sym, *args, &block)
rescue NoMethodError => e
raise e, e.message.sub(time.inspect, inspect), e.backtrace
end

So it makes sense that it would delegate respond_to_missing? to Time as well.

# Ensure proxy class responds to all methods that underlying time instance
# responds to.
def respond_to_missing?(sym, include_priv)
return false if sym.to_sym == :acts_like_date?
time.respond_to?(sym, include_priv)
end

How to solve Rubocop respond_to_missing? offence

Rubocop expects super to be called without arguments. As the arguments you are passing to super are the same as those you received, you can simply remove the arguments:

def method_missing(name, *args, &block)
if name =~ /(.+)\=/
self[$1.to_sym] = args[0]
elsif has_index?(name)
self[name]
else
super
end
end

Rspec - Argument error after overwriting method_missing and respond_to_missing

Ruby Delegator#respond_to_missing? is method take responsible for returning whether a missing method be able to handled by the object or not, it takes 2 parameters: the missing method name and the option include_private.

The best practice is: always define respond_to_missing? when overriding method_missing.

However i do not prefer the way you applied, the reason behind that is The Rule of Least Surprise, take a look:

class DataHelper
def method_missing(method_name, *args, &block)
if method_name.to_s.start_with?('delegate')
puts "a delegate method"
else
super
end
end

def respond_to_missing?(method_name, include_private = false)
true
end
end

d = DataHelper.new
d.respond_to?(:answer) # true
d.answer # `method_missing': undefined method `answer' ... SURPRISE

as you can see, d response that he can responsible for the answer method but when call that method, a method_missing error be raised.

So, you need to make both method_missing and respond_to_missing? match together:

class DataHelper
def method_missing(method_name, *args, &block)
if can_handle?(method_name)
puts "a delegate method"
else
super
end
end

def respond_to_missing?(method_name, include_private = false)
return true if can_handle?(method_name)
super
end

private

def can_handle?(method_name)
method_name.to_s.start_with?('delegate')
end
end

d = D.new
d.respond_to?(:delegate_answer) # true
d.delegate_answer # delegate method
d.respond_to?(:answer) # false
d.answer # error

__getattr__ on a module

A while ago, Guido declared that all special method lookups on
new-style classes bypass __getattr__ and __getattribute__. Dunder methods had previously worked on modules - you could, for example, use a module as a context manager simply by defining __enter__ and __exit__, before those tricks broke.

Recently some historical features have made a comeback, the module __getattr__ among them, and so the existing hack (a module replacing itself with a class in sys.modules at import time) should be no longer necessary.

In Python 3.7+, you just use the one obvious way. To customize attribute access on a module, define a __getattr__ function at the module level which should accept one argument (name of attribute), and return the computed value or raise an AttributeError:

# my_module.py

def __getattr__(name: str) -> Any:
...

This will also allow hooks into "from" imports, i.e. you can return dynamically generated objects for statements such as from my_module import whatever.

On a related note, along with the module getattr you may also define a __dir__ function at module level to respond to dir(my_module). See PEP 562 for details.

PORO presenter breaks url helpers

Try defining a to_param method

class BandPresenter
def to_param
@band.id
end

def model_name
@band.model_name
end
end

Another option that might help is defining respond_to_missing?, see here: http://robots.thoughtbot.com/always-define-respond-to-missing-when-overriding

class BandPresenter
def respond_to_missing?(method_name, include_private = false)
@band.respond_to?(method_name, include_private) || super
end
end

Why does the number of rows change during AIC in R? How to ensure that this doesn't happen?

From the Warnings section of ?step:

The model fitting must apply the models to the same dataset. This may be a problem if there are missing values and R's default of na.action = na.omit is used. We suggest you remove the missing values first.

So you should do:

no.na.data <- na.omit(data[c(predictors, response)])
model <- lm(formula=as.formula(paste(paste(response,'~', sep=''),
paste(predictors,collapse='+'), sep='')),
no.na.data)
step(model)


Related Topics



Leave a reply



Submit