I have this method in the lib dir (file my_class_name.rb):
class MyClassName
def doSomething
...
end
...
end
in the controller:
class UsersController < ApplicationController
require 'my_class_name'
def show_stats
::MyClassName.doSomething()
end
end
returns
undefined method `doSomething' for MyClassName:Class
How to properly call this method?
You've written a class with an instance method, so if you want to call it how you've written it you'll need to write:
mcn = MyClassName.new
mcn.doSomething
(by creating an instance, and then calling the method on that instance)
If what you want is a class method, define it as:
class MyClassName
def self.doSomething
...
end
...
end
and call it like: MyClassName.doSomething
class MyClassName
def self.doSomething
...
end
...
end
You have made and instance method not class method, change your code as follow, plus i would suggest you instead of making it as a class make it a module and include in your model and call doSomething from model.
class MyClassName
def self.doSomething
...
end
...
end
class UsersController < ApplicationController
require 'my_class_name'
def show_stats
MyClassName.doSomething()
end
end
If you are looking to make it work as is (with tiny change) then you should create an instance of MyClassName e.g. ::MyClassName.new.doSomething()
class MyClassName
def doSomething
...
end
...
end
class UsersController < ApplicationController
require 'my_class_name'
def show_stats
::MyClassName.new.doSomething()
end
end
Related
I have the following classes:
Module
module AlertService
module MessageTemplate
def generate_message
"test"
end
end
end
Parent class:
module Client
def post uri, params={}
Net::HTTP.post_form uri, params
end
end
module AlertService
class BaseAlert
extend MessageTemplate
include Singleton
include Client
def initialize; end
end
end
Child Class:
module AlertService
class TestAlert < BaseAlert
include Singleton
def initialize
options = {
username: "Screen Alert Bot",
http_client: Client
}
#notifier = Slack::Notifier.new(rails.config.url, options)
end
def self.create_message
message = generate_message
end
def self.send_message
create_message
#notifier.post blocks: message
end
end
end
I can create the test alert like this: s= AlertService::TestAlert
But I get the error when I do this:
s.send_message
NoMethodError: undefined method `generate_message' for AlertService::TestAlert::Class
generate_message is a method from the MessageTemplate module included in the BaseAlert class. Why is it saying my inherited class doesn't have access to the method?
You're not using Singleton correctly. You're including it, but then not using it, instead bypassing that altogether and calling class methods that have nothing to do with Singleton. They're in turn calling class methods on the parent class that don't exist.
The solution is to use Singleton as intended:
module AlertService
class BaseAlert
include MessageTemplate
include Singleton
def initialize
end
end
end
module AlertService
class TestAlert < BaseAlert
def initialize
#notifier = Slack::Notifier.new(Rails.configuration.url, Rails.configuration.options)
end
def create_message
message = generate_message
end
def send_message
create_message
#notifier.post blocks: message
end
end
end
Where now you call with instance as documented:
AlertService::TestAlert.instance.send_message
What is the idea behind creating a new instance of a method inside the class << self construct?
I understand methods are put under the class << self block to make them class methods but what does it mean to create a new instance of the method itself?
class foo
class << self
def bar(param)
new.bar(some_param)
end
end
end
I think what your trying to describe is a convenience method:
class FooService
def initialize
#bar= Bar.new
end
# this does the actual work
def call
results = #bar.do_some_work
results.each do
# ...
end
end
# this is just a convenient wrapper
def self.call
new.call
end
end
This lets you call the FooService.call class method for instead of manually instantiating the class with FooService.new.call. It does not really look like that much from this simple example but its really useful for abstracting away object initialization in things like service objects or to combine initializer arguments with method arguments.
class ApiClient
def initialize(api_key)
#api_key = api_key
end
def get(path)
# ...
end
def self.get(path, api_key: ENV['API_KEY'])
new(api_key).call(path)
end
end
ApiClient.get('foo')
I´m trying to develop a service class that provides payment services in my Rails app, but it´s not working.
Service class (lib/paypal_service.rb) (not sure if it should be placed here, I read it in some posts):
class PaypalService
attr_reader :api #, :express_checkout_response
def initialize()
#api = PayPal::SDK::Merchant::API.new
end
def test()
puts "Congratulations, you have called test"
end
end
Controller (uses service):
class BookingsController < ApplicationController
include BoatsHelper
require 'paypal_service'
def create
PaypalService.test
end
...
In output I get:
NoMethodError (private method `test' called for PaypalService:Class):
It's because you are calling a class method, but you have defined an instance method.
Change you controller to this
def create
PaypalService.new.test
end
Or define a class method and leave your controller as is
class PaypalService
attr_reader :api #, :express_checkout_response
def initialize()
#api = PayPal::SDK::Merchant::API.new
end
def self.test
new.test
end
def test()
puts "Congratulations, you have called test"
end
end
Use PaypalService.new.test instead of PaypalService.test as test is an instance method of class PaypalService and not a class method. Update it as below:
class BookingsController < ApplicationController
include BoatsHelper
require 'paypal_service'
def create
PaypalService.new.test
end
...
NOTE:
If you want to call it as PaypalService.test then you can convert test to a class method as follows:
class PaypalService
attr_reader :api #, :express_checkout_response
def initialize
#api = PayPal::SDK::Merchant::API.new
end
def self.test
puts "Congratulations, you have called test"
end
end
Can't i do it like this:
class Hardware
before_filter
def before_filter
puts "ge"
end
end
It says before_filter is undefined method or variable when I instantiate it
hd = Hardware.new
because ive seen others put a method name in a class before. Just wondering how it works. Thanks
There's two problems with your code:
You are calling a class method, but your are defining an instance method.
You are calling the method before it has been defined.
Both of these obviously cannot work.
This would work:
class Hardware
def self.before_filter
puts "ge"
end
before_filter
end
before_filter is an ActiveRecord class method (see here) and so would only be available if your model inherited from ActiveRecord::Base (or a subclass). Can you be more specific about what you're trying to do?
You might just be looking for:
class Hardware
def initialize
super
before_filter
end
protected
def before_filter
# ...
end
end
Either change
def before_filter
to
def self.before_filter
and call it after defined
OR
Comment before_filter
class Hardware
def before_filter
puts "ge"
end
end
and Call like
hd = Hardware.new
hd.before_filter
I am trying to get the name of the class from within a static method within the class:
class A
def self.get_class_name
self.class.name.underscore.capitalize.constantize
end
end
Though this returns Class instead of A. Any thoughts on how do I get A instead?
Eventually I also want to have a class B that inherits from A that will use the same method and will return B when called.
The reason I am doing this is because I have another object under this domain eventually: A::SomeOtherClass which I want to use using the result I receive.
Remove .class:
class A
def self.get_class_name
self.name.underscore.capitalize.constantize
end
end
self in a context of a class (rather than the context of an instance method) refers to the class itself.
This is why you write def self.get_class_name to define a class method. This means add method get_class_name to self (aka A). It is equivalent to def A.get_class_method.
It is also why when you tried self.class.name you got Class - the Object#class of A is Class.
To make this clearer, consider the output of:
class A
puts "Outside: #{self}"
def self.some_class_method
puts "Inside class method: #{self}"
end
def some_instance_method
puts "Inside instance method: #{self}"
end
end
A.some_class_method
A.new.some_instance_method
Which is:
Outside: A
Inside class method: A
Inside instance method: #<A:0x218c8b0>
The output for this:
class NiceClass
def self.my_class_method
puts "This is my #{name}"
end
end
NiceClass.my_class_method
Will be:
This is my NiceClass