I have an embarrassingly basic question:
I'm working on a plain-old-ruby model that deals with money, and some of the class methods return prices which need to be formatted for display.
In the past I've used include ActionView::Helpers::NumberHelper to stick the number_to_currency method in a model, but that only works for instance methods.
How do you get that method to be accessible from a class method?
Use extend:
class MyClass
extend ActionView::Helpers::NumberHelper
end
Related
How do you define a method on an instance of a class and this method is only for the instance and not others?
Please can someone provide a use case for this feature?
Defining a singleton method on an object gives you an object with some new properties. That's it, not more, not less.
Sure, you could achieve the same in another way - create a new class with the desired properties and instantiate it, mix in a module that adds the necessary behavior. And in most practical cases you'd probably do just that.
But think about tests for example where you need to mock some object's method (sure, RSpec framework provides a better way to do this, but still). Or you're debugging the code in REPL and would like to mock some method (for example, to avoid unnecessary side effects). In such cases defining a singleton method is the easiest (fastest) way to get things done.
Just don't think about this "feature" as a separate feature. Because it's not. It is just a consequence of how the Ruby object model works - focus on the latter. I strongly recommend this book for that...
Class methods are called on the class itself which is why in the method declaration, it will always state def self.class_method_name.
Whereas instance methods are called on a particular instance of the class (Not class itself) and they are declared like regular methods i.e def instance_method_name.
For example:
class Car
def self.class_method
puts "It's a class method"
end
def instance_method
puts "It's an instance method"
end
end
Car.class_method => "It's a class method"
Cat.instance_method => undefined method 'instance_method' for Car:Class
Car.new.instance_method => "It's an instance method"
Car.new.class_method => undefined method 'class_method' for Car:Class
For the usecase, here is an example from the Rails:
class Car < ApplicationRecord
belongs_to :owner
has_many :passengers
def self.get_cars(owner) # This is a class method
Car.includes(:passengers).where(owner: owner).order(created_at: :desc)
end
end
With Car.get_cars(owner) method, you can get all the cars with your own logic.
I'm learning how to use Sinatra. I figured out that when I pass object as locals, e.g.:
product = FetchProduct.new.call(id) #function finds exact Product instance
erb :"products/show", locals: { product: product }
I can use product object in my views with all instance methods I declared. But I can't use any class method, any attempt to do so gives me uninitialized constant error. What should I do if I want to use Product.format_price(product.price) method? Is there any way to pass class methods to Sinatra views?
klass = const_get( product.class )
klass.format_price
But that doesn't really make sense because you already know you want Product.format_price. So why don't you use Product.format_price?
It's generally a bad idea to run that kind of logic in your views. Best practice is to, wherever possible, serve to the view whatever it needs.
NB the reason you can't run the class method in your view is because Product is not accessible in your view and, to be honest, it shouldn't be if you want to follow MVC principles.
If it's just the format_price method you need in the view (especially since you seem to be passing an instance of Product into Product.format_price which is rather strange and a big code smell), then either create a helper method called format_price that is accessible by the view or, probably better, create a helper method called format_price in your controller (or in a helper module included in your controller) and pass the return value as a local i.e.
get '/' do
product = FetchProduct.new.call(id)
erb :'products/show', locals: {
product: product,
price: format_price(product)
}
end
private
def format_price(product)
# awesome formatting logic
end
Learning ruby and oop in general, I came upon class methods which as far as I understand are like instance methods but are accessed from the class rather than from an object and can have only one running at the same time.
However, I don't understand why you would use a class method versuses a normal method (outside a class) and what is even their use?
For example:
#Why would you use:
class Foo
def self.bar
puts "Class method"
end
end
#Versus simply:
def bar
puts "Normal method"
end
Foo.bar # => Class method
bar # => Normal method
As they both produce the same result?
I'm quite confused about them so please correct if I'm misunderstanding any/everything here.
Your example isn't a good one.
Class methods might deal with managing all instances that exist of a class, and instance methods deal with a single instance at a time.
class Book
def self.all_by_author(author)
# made up database call
database.find_all(:books, where: { author: author }).map do |book_data|
new book_data # Same as: Book.new(book_data)
end
end
def title
#title
end
end
books = Book.all_by_author('Jules Vern')
books[0].title #=> 'Journey to the Center of the Earth'
In this example we have a class named Book. It has a class method all_by_author. It queries some pretend database and returns an array of Book instances. The instance method title fetches the title of a single Book instance.
So the class method managing a collection of instances, and the instance method manages just that instance.
In general, if a method would operate on a group of instances, or is code related to that class but does not directly read or update a single instance, then it probably should be a class method.
This is more an OOP question than a ruby one. Class methods in ruby are used the same as in other OO programming languages. This means:
class methods are run in the context of a class (and have access only to class variables)
instance methods are run in the context of an object (and have access to object's or instance variables)
Here is a better example:
class Foo
def self.bar
puts 'class method'
end
def baz
puts 'instance method'
end
end
Foo.bar # => "class method"
Foo.baz # => NoMethodError: undefined method ‘baz’ for Foo:Class
Foo.new.baz # => instance method
Foo.new.bar # => NoMethodError: undefined method ‘bar
Here you can see that class method is accessed through a class, while instance method is accessed through an instance or object of a class (Foo.new).
Example is copied from here, where you can also find more information on this subject.
Keep in mind: although any code can be put into a class or a instance method, each has it's own use cases and own pros and contras. In OOP we strive for reusable, flexible and readable code, which means that we usually want to put most of the code as structured as instance methods in a sensible domain model.
Just as you said, they are:
"accessed from the class rather than from an object and"
"can have only one running at the same time."
remember, too, that the class is portable
The most important thing is that it keeps your code organized. When you have hundreds of thousands of lines of code, having them all haphazardly throwing stuff around in the same namespace can become a nightmare. Organization is really important, and namespaces are an easy way to get modularity with support from the language.
Somewhat less importantly, class/module methods can share state without leaking it all over the place (e.g. classes can have instance variables), and they can have private support methods to allow for better factoring, while global methods can't effectively be made private.
You have lots of misunderstanding,
In ruby, we can define class and instance method.
Class method is used to do provide processing at class level i.e. data which can only be available at class level or related to all the objects. For example, to count the number of objects belongs to class you need class method. Like
Foo.count
In same way, to process single object you need object method to process a single object like,
obj.save
So, class method is example of singletone design pattern where object can have there own implementation of same method.
Is there a difference in usage between
class Helper
class << self
# ...
end
end
and
module Helper
class << self
# ...
end
end
When would you use one over the other?
The class<<self seems to be a red herring, as the only difference here is a class versus a module. Perhaps you're asking "I want to create an object that I do not intend to instantiate, but which exists only as a namespace for some methods (and possibly as a singleton with its own, global, state)."
If this is the case, both will function equally well. If there is any chance that you might want to create a derivative (another object inheriting the same methods) then you should use a class as it slightly is easier to write:
class Variation < Helper
instead of
module Helper
module OwnMethods
# Put methods here instead of class << self
end
extend OwnMethods
end
module Variation
extend Helper::OwnMethods
However, for just namespacing I would generally use a module over a class, as a class implies that instantiation will occur.
The difference between a Module and a Class is that you can make an instance of a Class, but not a Module. If you need to create an instance of Helper (h = Helper.new) then it should be a class. If not, it is probably best to remain a module. I'm not sure how the rest of your code is relevant to the question; whether you have class methods on a Module or a Class is not relevant to whether you need to create instances of that object.
It seems commonplace to name classes "Base" in Ruby. I'm not sure why, nor how I feel about it.
Consider, for example, ActiveRecord. ActiveRecord is a module that contains a number of classes such as Observer and Migration, as well as a class called Base. What's the benefit of this, as opposed to having an ActiveRecord class that contains Observer and Migration?
class ActiveRecord
class Observer
[...]
end
class Migration
[...]
end
end
vs
module ActiveRecord
class Base
[...]
end
class Observer
[...]
end
class Migration
[...]
end
end
The Base class is commonly used to identify an abstract class, intended to be extended and implemented in a concrete class by the developer.
For instance, ActiveRecord::Base is the abstract class for any Active Record model in a Rails project. A model looks like
class User < ActiveRecord::Base
end
Likewise, Observer defines its own Observer::Base and Action Controller defines ActionController::Base which, in a Rails project, is immediately implemented by ApplicationController::Base.
Ruby doesn't provide and language-level keyword or syntax to define abstract classes. Technically speaking, ActiveRecord::Base it's not a real abstract class, but it's a kind of convention to use Base for this pattern.