Accessing model methods from outside without creating an object - ruby

I have the following method:
class Store < ActiveRecord::Base
def my_func(str)
puts str
end
end
I can't seem to call it from outside the class like this:
Store::my_func("hi")
Any idea why?

What you have defined is an instance method. Basically this means you can only call it on instances of that class.
store = Store.new
store.my_func("hi")
If you want a class method, you need to define it a little differently. Either:
class Store < ActiveRecord::Base
def self.my_func(str)
puts str
end
end
Or (more useful if you're defining a lot of class methods):
class Store < ActiveRecord::Base
class << self
def my_func(str)
puts str
end
end
end
The above two work because classes are also instances of the class Class, so the implicit receiver self in the above two examples is that instance (the class itself).
You call a class method like this:
Store.my_func("hi")

Related

Define instance method of a class after class already defined in ruby

I have some problem with extending class with instance method after separate module is included into separate class
module ActsAsCommentable
def self.included(commentable)
Thread.class_eval do
def commentable
p "disqusable is #{commentable}"
p "disqusable class is #{commentable}"
end
end
end
end
class Thread
#some code...
end
class Asset
include ActsAsCommentable
end
And now I want to call this method somelike this:
thread = Thread.new
thread.commentable
The problem is, of course is that there is no binding with include method for class eval, and I could save variables that I want to pass into class eval in ActsAsCommentable module, but I dont want to. Is there a better way?
I tried to do instead
module ActsAsCommentable
def self.included(commentable)
class << Thread
define_method :commentable do
p "disqusable is #{commentable}"
p "disqusable class is #{commentable}"
end
end
end
end
But As I guessed this creates instance method for singletone object of class and therefore I can call it only through
Thread.commentable
And again, no binding...
If I understand you correctly, you need to be able to access the commentable variable inside your Thread extension, right?
If so, just change this:
Thread.class_eval do
To this:
Thread.class_exec(commentable) do |commentable|
And it should work.

Ruby dynamically instantiate class

How to reference to a class within a static method?
class Car
def self.new_from_xml(xml)
instance = self.class.new
#do some stuff with xml
instance
end
end
class Mercedes < Car
end
class Porsche < Car
end
IRB:
Mercedes.new_from_xml(somedata) # Output is #<Class:...>, should be #<Mercedes:...>
Porsche.new_from_xml(somedata) # Output is #<Class:...>, should be #<Porsche:...>
Instead of
instance=self.class.new
just write
instance = new
Why is this?
Well, in first place, you have to understand that you are calling a class method, thus you are at a class level already. The .new method is a class method, so you can call it directly without calling self.class.new.
Why does self.class.new return Class?
Because the class of the class Car is Class (I know, sounds weird ;), because classes in Ruby are instances of Class.
This is actually a pretty deep concept, I recommend you read more about it. One nice reference I have read is the book Metaprogramming Ruby by Paolo Perrotta (ISBN-10: 1934356476) [1].
http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Pros/dp/1934356476
Since you are already in a class method, you should use self.new (or simply new, as #tokland wrote) instead of self.class.new:
class Car
def self.new_from_xml(xml)
instance = new
#do some stuff with xml
end
end
class Mercedes < Car
end
class Porsche < Car
end
p Mercedes.new_from_xml(nil) #=> #<Mercedes:0x007f042d0db208>
p Porsche.new_from_xml(nil) #=> #<Porsche:0x007f042d0db118>
From a comment to this answer: Why does self.class reference to class? What's the logic here?
Inside a class block self references the class you are editing:
class Car
puts self #=> writes Car
end
Using def self.new_from_xml it is like if you are declaring def Car.new_from_xml, that is a method of the Car object (which is an instance of Class); so inside new_from_xml self coincides with Car.

Create property as method on class in Ruby

Rails has these cool properties that seem to be actually methods. For example:
class SomeController < ApplicationController
before_filter :authenticate!
end
What are these actually called and how would you create your own? For example, in one of my models I want to be able to have a dynamic property that selects an internal method for processing some results:
class MyModel < ActiveRecord::Base
active_method :some_class_method
end
How would I set this up so I can set active_method like that and be able to access the active_method symbol as an instance var?
Edit for elaboration:
So give this starter below, I need to figure out how to define "selected_method" so that it defines a accessor or instance variable so "called_selected_method" calls "method_b".
class MyClass
selected_method :method_b
def call_selected_method
end
private
def method_a
puts 'method_a'
end
def method_b
puts 'method_b'
end
end
c = MyClass.new
c.call_selected_method # should put 'method_b'
It's actually just a method call to a method defined on the class. before_filter is provided by a ruby Module, which is mixed in to ActionController.
Creating your own methods similar to before_filter is as easy as:
Define a class method on your Class
Call that method in any concrete implementations of your class.
Some example code:
class MyClass
class << self
def some_function(*args)
# your code here
end
end
some_function "foo"
end
If you wanted to abstract it further, you can put the class method in to a Module, and then include that module in to your class(es).
UPDATE:
In relation to your asking of how to get a call of some_function to set an instance variable on your class, you can't, as class methods cannot affect specific instances of that class.
I have to wonder, though... you're writing a method that will just act as a proxy to your other method, and would be hard-coded in to the class definition. That offers no benefit to you, and would just make your code redundantly complicated.

How can I write derived Ruby classes that call a base class's method when they're defined?

Let's say I have this class:
class ComponentLibrary
def self.register(klass); ...; end
end
And suppose I also have this base class:
class BaseComponent
ComponentLibrary.register self
end
How can I write derivative classes, with a minimum of repetition, that will register themselves with ComponentLibrary when they're defined? (In other words, I'd prefer not to keep writing ComponentLibrary.register self everywhere.)
Just to be clear, I'm talking about writing other classes like:
class RedComponent < BaseComponent
# ...
end
class BlueComponent < BaseComponent
# ...
end
but I don't want to write ComponentLibrary.register self for each one.
class BaseComponent
def self.inherited(base)
ComponentLibrary.register(base)
end
end
class RedComponent < BaseComponent
end
Something along these lines might work for you.
Edit: changed to #inherited.

How do I see where in the Class Hierarchy a Method was defined and Overridden in Ruby?

Is there a way to know whether or not a method has been overridden by a subclass programmatically? Something that works like this:
class BaseModel
def create
puts "superclass"
end
end
class SomeModel < BaseModel
def create
puts "subclass"
end
end
puts SomeModel.overridden_instance_methods #=> [:create]
Any ideas?
SomeModel.instance_methods(false) & BaseModel.instance_methods
The false makes instance_methods not include inherited methods. We then use set intersection to find all the methods that were defined on SomeModel which have previously been defined on BaseModel (or Object).

Resources