It seems there are 3 ways of defining class methods (at least in common
usage):
1) Defining a method on self:
def self.method
2) Opening up self and defining the methods directly:
class << self
def method
...
end
3) Placing class methods into a module, and extending a class with that:
module ClassMethods
def method
...
end
extend ClassMethods
···
--
Which of these do you use and which do you prefer? Do you use all three? Do
you think class << self is fugly and confusing?
I used to use class << self quite frequently and have been shifting to using
modules when dealing with a large number of class methods. I can't really
say I'm a huge fan.
I use all three, depending on the situation. Generally, I use method 2
(class << self), but if I have an idea that I will be needing only
one, or two class methods (like Module.included) I use method 1 (def
self.foo). If it makes sense to separate the class methods from the
core definition of a class (like helper/utility functions), I define
them in a module in a separate file.
I do not find class << self to be ugly and confusing :).
I picked up the following pattern going through DataMapper's code (or,
was it Ruby Best Practices?).
module Foo
def instance_method; puts "im"; end
module ClassMethods
def class_method1; puts "cm" end
end
def self.included(klass)
klass.extend(ClassMethods)
end
end
class Moo
include Foo
end
Foo.class_method #=> cm
Foo.new.instance_method #=> im
Foo.new.class_method #=> NoMethodError
A use case of this pattern for me was defining a Helper module for
Sinatra (modular) app where some helpers will be used in the
request-response context, while some in the context of the class that
inherits from Sinatra::Base.
···
On Thu, Feb 17, 2011 at 1:17 AM, Tony Arcieri <tony.arcieri@medioh.com> wrote:
It seems there are 3 ways of defining class methods (at least in common
usage):
1) Defining a method on self:
def self.method
2) Opening up self and defining the methods directly:
class << self
def method
...
end
3) Placing class methods into a module, and extending a class with that:
module ClassMethods
def method
...
end
extend ClassMethods
--
Which of these do you use and which do you prefer? Do you use all three? Do
you think class << self is fugly and confusing?
i usually use this one since
1 it's visibly specified. The definition matches the use.
2 don't need to press pgup just to see who is self
3 if i change class name, it self checks itself since i need to retype.
4 less prone to self abuse
best regards -botp
best regards -botp
···
On Thu, Feb 17, 2011 at 3:47 AM, Tony Arcieri <tony.arcieri@medioh.com> wrote:
It seems there are 3 ways of defining class methods (at least in common
usage):
1) Defining a method on self:
2) Opening up self and defining the methods directly:
3) Placing class methods into a module, and extending a class with that:
I don't mean it as a put-down; I suspect the only person I'm putting down is myself. But I don't find that class methods actually come up much in my Ruby coding; when I find myself coding one I tend to stop and think hard about whether I actually need it.
And when I do use one it's always your type (1). Why would I want to define a class method anywhere else but in the class? I do understand that for DSLs, all the rest of this syntax is really useful. But -- showing my ignorance here -- is it really of any practical value elsewhere?
···
--
A boss with no humor is like a job that's no fun.
It depends on whether and how you want to allow methods to be
overridden. Using #extend and 'def self.xxx' are not the same, viz:
module A
def run
puts "A"
end
end
class Foo
extend A
end
class Bar
extend A
end
Foo.run # => "A"
Bar.run # => "A"
module B
def run
puts "B"
end
end
class Foo
def self.run
puts "foo"
end
end
Foo.extend(B)
Bar.extend(B)
Foo.run # => "foo" - extend does not
override a def self.method
Bar.run # => "B" - but it does override a
previously defined extension
class Foo
class << self
def run
puts "bar"
end
end
end
Foo.run # => "bar" - using 'class << self;
def method' ... same as 'def self.method'
Personally, I've come to prefer using #extend.
Regards,
Sean
···
On Wed, Feb 16, 2011 at 7:47 PM, Tony Arcieri <tony.arcieri@medioh.com> wrote:
It seems there are 3 ways of defining class methods (at least in common
usage):
1) Defining a method on self:
def self.method
2) Opening up self and defining the methods directly:
class << self
def method
...
end
3) Placing class methods into a module, and extending a class with that:
module ClassMethods
def method
...
end
extend ClassMethods
--
Which of these do you use and which do you prefer? Do you use all three? Do
you think class << self is fugly and confusing?
I used to use class << self quite frequently and have been shifting to using
modules when dealing with a large number of class methods. I can't really
say I'm a huge fan.
It seems there are 3 ways of defining class methods (at least in common
usage):
There's lots of ways to add a class method; Ruby is not a very
prescriptive language. Two more interesting examples that are used:
there's `instance_eval` on a Class instance:
X = Class.new
X.instance_eval do
def foo; "calling #foo!"; end
end
X.foo
# => "calling #foo!"
or #class_eval on the class of your `Class` instance (which will be `Class`):
X.class.class_eval do
def bar; "calling #bar!"; end
end
X.bar
# => "calling #bar!"
It's not very complicated, but `class_eval` on a Class instance is
typically used only in some rather advanced (and/or cryptic)
metaprogramming, so you don't see it floating around a lot.
On Wed, Feb 16, 2011 at 21:55, botp <botpena@gmail.com> wrote:
On Thu, Feb 17, 2011 at 3:47 AM, Tony Arcieri <tony.arcieri@medioh.com> wrote:
It seems there are 3 ways of defining class methods (at least in common
usage):
1) Defining a method on self:
2) Opening up self and defining the methods directly:
3) Placing class methods into a module, and extending a class with that:
4) Explicit definition
def C.m
...
end
i usually use this one since
1 it's visibly specified. The definition matches the use.
2 don't need to press pgup just to see who is self
3 if i change class name, it self checks itself since i need to retype.
4 less prone to self abuse
Indeed. Class methods in Ruby are a code smell: not always wrong, but
you should always think about why you're choosing a class-level method
instead of instance-level.
I think most of the class/module-level methods I write are "macros" -
e.g. methods along the lines of Ruby's #attr_accessor.
···
On Thu, Feb 17, 2011 at 4:41 AM, Shadowfirebird <shadowfirebird@gmail.com> wrote:
I don't mean it as a put-down; I suspect the only person I'm putting down is myself. But I don't find that class methods actually come up much in my Ruby coding; when I find myself coding one I tend to stop and think hard about whether I actually need it.
Well, more specific than DSLs: metaprogramming, and DSLs that generate code.
Some of the more abject design patterns, such as the factory pattern, can
often be avoid thanks to a combination of Ruby's dynamism and class methods.
The class is also a great place to stick state shared by all instances of
that class, such as the configuration details for accessing a particular
network service.
···
On Thu, Feb 17, 2011 at 2:41 AM, Shadowfirebird <shadowfirebird@gmail.com>wrote:
And when I do use one it's always your type (1). Why would I want to define
a class method anywhere else but in the class? I do understand that for
DSLs, all the rest of this syntax is really useful. But -- showing my
ignorance here -- is it really of any practical value elsewhere?
Indeed. Class methods in Ruby are a code smell: not always wrong, but
you should always think about why you're choosing a class-level method
instead of instance-level.
I don't know if I'd go so far as to say they're a code smell. Without
class methods a number of very useful Ruby DSLs wouldn't exist in
their current form (RSpec, Cucumber, Rails, etc., just to name a few).
I agree that they can be abused or misused, but that's true of pretty
much any construct in any language, isn't it?
I'd probably arrange my skepticism of a class method from lowest to
highest in this way, depending on its features:
* part of a DSL (`describe`, `Before`, `callback { ... }`, etc.)
* repository pattern (Widget.find(...))
* factory pattern (Widget.orange # => <orange Widget instance>)
* method takes more than a parameter or two
* non-factory class method with variable args
* instance of the class method's class is in the arguments/params
list (often very questionable)
On Thu, Feb 17, 2011 at 10:03, Avdi Grimm <groups@inbox.avdi.org> wrote:
On Thu, Feb 17, 2011 at 4:41 AM, Shadowfirebird > <shadowfirebird@gmail.com> wrote:
I don't mean it as a put-down; I suspect the only person I'm putting down is myself. But I don't find that class methods actually come up much in my Ruby coding; when I find myself coding one I tend to stop and think hard about whether I actually need it.
Indeed. Class methods in Ruby are a code smell: not always wrong, but
you should always think about why you're choosing a class-level method
instead of instance-level.
I think most of the class/module-level methods I write are "macros" -
e.g. methods along the lines of Ruby's #attr_accessor.