`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
What's Wrong with the Square and Rectangle Inheritance
Why Can't I Create an Array as a Column in a Table in Rails
Using Ruby and Mechanize to Fill in a Remote Login Form Mystery
Ruby Is Already Using the Class Name of My Model
Webmock Simulate Failing API (No Internet, Timeout ++)
Should Gemfile.Lock Be Committed to Source Control on Windows
Why Are My Rspec Tests Failing, But My App Is Working
When Passing Objects as Parameters, Are They Passed by Reference
How Would I Go About Converting This Time String to Epoch Time in Ruby
Ruby - Return Byte Array Containing Two's Complement Representation of Bignum/Fixnum
Ruby How to Merge Two CSV Files with Slightly Different Headers
Ssl_Connect Error When Accessing Shopify API with Rubygem
How to Stop Savon from Adding Prefixes to Soap.Body
Ruby on Rails: Params Is Nil. Undefined Method '[]' for Nil:Nilclass
+= Operator Appears to Modify Frozen String
How to "Extract" Values from a Multidimensional Array in a Smart Way