If I want to call a class method (mailer method in rails), providing its name in a variable. How can I do that? For objects, we can use send, or we can use read_attribute to read some values
my_object.send("#{self.action_type(self)}")
my_object.read_attribute("#{self.action_type}_email")
But for class names, nothing is working as send is defined as instance method in object class. I want something like this, which will not work as send can't be applied on class:
Notifier.send("#{self.action_type(self)}").deliver
Use eval
eval("Notifier.#{self.action_type}(self).deliver")
Not safe but it should work.
Classes are objects. There is no difference in how you apply send.
Notifier.send(action_type, self).deliver
You can also do:
method = Notifier.method(action_type)
method.call(self).deliver
you can also use
self.class.send(:your_class_method)
Related
I want to create another name for a method that already exists, e.g. I want to call slice with only. I don't want to change anything about the behavior of that original method, so it's not a redefinition, but delegation. How can I do that?
There are a number of ways to do that in Ruby. Please check this post which may help you find your most suitable way of doing it.
http://gdakram.com/past/2010/12/2/multiple_ways_in_implementing_delegation_pattern_in_ruby/
class Whatever
def slice
# do something
end
alias :only :slice
end
Is there a class method to check if there is a certain instance method for that class? Something like respond_to? that is a class method.
Yes, you can use
method_defined?
,which is class method to check whether particular class has instance method defined or not.
Following link will explain you more
Given a class, see if instance has method (Ruby)
Use method_defined? on Class
Ex: Array.method_defined? :sort
I know about controller_name returning a string containing the controller's name but how can I retrieve the controller class (or object) from within a helper?
EDIT: The solution should also work when the controller is namespaced (eg. Admin::PostsController)
You can use the constantize method, like:
controller_name.constantize
Though I'm not sure how it will behave if you have a namespaced controller.
Update:
That one won't work for all controller names and/or namespaces. Though one can use the #controller method in combination with #class:
controller.class
A view probably shouldn't need to do this. Ideally whatever you're trying to do in the view that expects this, you would instead do in the controller.
Trying to think about why you'd want to do this, the best answer I can think of is that you want to invoke a helper method you've defined in the controller. There already exists a construct to do this, use helper_method.
For pretty much anything else, the controller should provide that data to the view. Not the view pulling it out of the controller. (e.g. even though you shouldn't need the class, the controller could provide it with #controller_class = self.class, which would then be available to the view)
In pure Ruby, because class names are constants, you can do this to get the class from a string:
classname = 'Posts'
p Kernel.const_get(classname).methods
There is a nice shortcut in Rails, constantize for just this:
p 'Posts'.constantize.methods
If the classname is eg 'editable_file', first call the camelize method:
p 'editable_file'.camelize.constantize # EditableFile
p 'extensions/editable_file'.camelize.constantize # Extensions::EditableFile
EDIT: If you really want to get the controller name un-demodulized, then this code in config/initializers/controller_name.rb should ensure it:
class ActionController::Metal
def self.controller_name
# #controller_name ||= self.name.demodulize.sub(/Controller$/, '').underscore
#controller_name ||= self.name.sub(/Controller$/, '').underscore
end
end
I have feeling, that if one defines a method
def test
puts 'Hi'
end
then there is a class to which this method belongs to (i.e. Unknown#test). So one probably has a possibility to list all methods defined "outside" of other classes. Or there is another way to do such listing?
If you define a method outside of any class, it will become a private method of the Object class.
A top-level method is a private method of Object.
Check out this question.
In future, to find what object a method belongs to, do this:
method(:test).owner
Output, for your example is Object
And you can then list all the methods of Object with
Object.send(:methods)
or
Object.send(:private_methods)
"abc".respond_to?(:sub) returns true, but String.respond_to?(:sub) returns false.
The second returns false, because it asks whether objects of the class Class have a method sub, as String is an Object of Class. It is the same for methods()…
How do I do these things and especialy respond_to?() without creating an Object of that class.
You can use method_defined? method, declared in Module class.
If you are trying to confirm whether a method exists, String.method_defined? :sub will work. If you are specifically interested in instance methods, use something like:
String.instance_methods.index 'sub'
Note that you have to use a string, not a symbol.