Ruby class declaration question - ruby

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

Related

How to detect a BasicObject Proxy?

I am using a BasicObject Proxy and I need to detect whether I have passed an actual object OR such a proxy. Problem is that methods such as is_a? or class are not defined
module ControllerProxyable
extend ActiveSupport::Concern
included do
attr_reader :controller
delegate :current_user, to: :controller
end
def controller_proxy(controller)
# is_a? actually is NOT defined for a BasicObject causes the following to crash
#controller = if controller.is_a?(ControllerProxy)
controller
else
ControllerProxy.new(controller)
end
end
end
class ControllerProxy < BasicObject
def initialize(controller = nil)
#controller = controller
end
def some_proxy_method
end
# def respond_to and respond_to_missing not relevant here
end
This is an example of how I am using it :
class Foo
include ControllerProxyable
def initialize(controller: nil)
controller_proxy(controller)
end
def bar
bar ||= Bar.new(controller: controller)
end
end
class Bar
include ControllerProxyable
def initialize(controller: nil)
controller_proxy(controller)
end
end
The following therefore doesn't work
Foo.new(controller: nil).bar.some_proxy_method
How can I define is_a? for a Proxy (or actually identifying I am using a proxy) ?
Problem is that methods such as is_a? or class are not defined
The obvious solution to the problem "some method is not defined", is to define the method:
class ControllerProxy
def class; ControllerProxy end
def is_a?(mod)
self.class < mod
end
end
But! This defeats the whole purpose of a proxy, which is to be indistinguishable from the real thing. A better way would be IMO:
class ControllerProxy
def class; Controller end
def is_a?(mod)
Controller < mod
end
end
I actually found an answer for RUby 2 here. My question almost feels like a duplicate but in my case I was talking about an extension of the basicObject class not patching the BasicObject class itself
For such a use case this becomes :
def controller_proxy(controller)
# Note that is_a? is not defined for a proxy
#controller = if Kernel.instance_method(:class).bind(controller).call <= ServiceControllerProxy
controller
else
ServiceControllerProxy.new(controller)
end
end

Service objects pattern in Ruby on Rails

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

Rails - how to call methods from lib directory?

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

How to call super in an initialize method when both class inheritance and Module include is being used?

How does the look-path decide where to call "super" if I have a module included along with class inheritance. My hunch is that by default it will use the initialize method in the module. Is this correct? And if so, how do I explicitly tell the code to use the initialize method in the inherited class instead?
Posted below is an example:
I want the Employee class to inherit initialize from Other and not Subject.
module Subject
def initialize
#observers = []
end
end
class Other
def initialize
#other_stuff = []
end
end
class Employee < Other
include Subject
attr_reader :name
def initialize(name)
super()
end
end
My hunch is that by default it will use the initialize method in the module.
Correct. If a class includes a module then the methods of that module will be replace inherited methods of the same name.
And if so, how do I explicitly tell the code to use the initialize method in the inherited class instead?
You're probably best off refactoring so that you don't have this problem.
However, there are several ways you could make Other's initialize method get called instead of Subject's.
How about something like this:
module Subject
def initialize
puts "subject initialize"
#observers = []
end
end
class Other
def initialize
puts "other initialize"
#other_stuff = []
end
end
class Employee < Other
alias_method :other_initialize, :initialize
include Subject
attr_reader :name
def initialize(name)
other_initialize
end
end
Employee.new('test')
If you run this, you'll see that Other's initialize method is called. Writing code like this is not a good idea, however.

What's the purpose of singleton_class.send & singleton_class.class_eval in this metaprogramming example?

class Product < ActiveRecord::Base
set_table_name 'produce'
end
module ActiveRecord
class Base
def self.set_table_name name
define_attr_method :table_name, name
end
def self.define_attr_method(name, value)
singleton_class.send :alias_method, "original_#{name}", name
singleton_class.class_eval do
define_method(name) do
value
end
end
end
end
I'd like to understand how set_table_name becomes defined in this example.
Why is singleton_class.send needed here?
And why is class_eval called on singleton_class instead of on self?
The reason for using "singleton_class" is because you do not want to modify the ActiveRecord::Base class, but the Product class.
More info about metaptogramming and singleton class here: http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html

Resources