I have two classes. I want to namespace them. I also have a bit of functionality that they share. I do something like this:
module Talker
def say_bye
puts 'bye'
end
class Bob
include Talker
def say_yo
puts 'yo'
end
end
class Tom
include Talker
def say_hello
puts 'hello'
end
end
end
These are all valid method calls.
Talker::Bob.new.say_yo
Talker::Bob.new.say_bye
Talker::Tom.new.say_hello
Talker::Tom.new.say_bye
I was told: "This include is going to include Bob again. You should close the Talker module before starting a class that includes Talker." Can somebody explain to me if I'm doing something that results in unexpected ruby behavior or is considered taboo? Is it a bad practice to include a module like this from inside a class within that module? What might be a criticism for this pattern? Should I use inheritance here?
I figured it out. The include ends up being somewhat recursive. The code above will do things like this:
Talker::Bob::Bob
Talker::Bob::Tom
Talker::Bob::Bob::Bob::Tom::Bob::Tom
And that is not something to have. So he was right when he said it would re-include the other classes in the module into each class that includes the module.
Related
I want to be able to extend a module with the methods and constants of a submodule.
If I use extend I receive undefined constant.
The only way I made it work is using both extend and include. I tried also using self.method on submodule.
module Car
module Container
HOLA = 'Helloo!'
def testing
HOLA
end
end
include Container
extend Container
end
So this both should work:
Car.testing # Hello!
Car::HOLA # Hello!
I guess this is a code smell..., but what other ways to make it work you know?
As per the description shared, it seems like you want to access the nested module constants and methods in some_other_class.
This is the module definition as mentioned in the post.
module Car
module Container
HOLA = 'Helloo!'
def testing
HOLA
end
end
end
Now Suppose , that you want to use this method in some class say Vehicle
require 'car' #this is the module file since it is residing in some other file
class Vehicle
extend Car
def test
Car.testing
end
end
Now calling Vehicle.new.test will print
"Helloo!"
Hope it helps!!
I'm new to rspec. The following syntax is confusing:
describe MyClass::Something do
What does Something refer to? The rspec tests I'm looking over contain the above line. However MyClass doesn't contain anything related to Something.
You are confused by Ruby syntax, not RSpec syntax. MyClass is a module, and Something is a class or module inside the MyClass module. The :: is the scope resolution operator to tell Ruby which Something you are looking for.
module Foo
class Bar
def say_hello
puts "hello"
end
end
end
foo = Foo::Bar.new
foo.say_hello
#prints "hello"
See http://ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html for more on modules.
This is not related to Rspec. The answer you are seeking is that Something is an inner class or module within MyClass. Something refers to a class/module named Something within the class/module MyClass. Here is an example:
class MyClass
module Something
end
end
I encountered a problem when trying to test a module with Test::Unit. What I used to do is this:
my_module.rb:
class MyModule
def my_func
5 # return some value
end
end
test_my_module.rb:
require 'test/unit'
require 'my_module'
class TestMyModule < Unit::Test::TestCase
include MyModule
def test_my_func
assert_equal(5, my_func) # test the output value given the input params
end
end
Now the problem is, if my_module declares an initialize method, it gets included in the test class and this causes a bunch of problems since Test::Unit seems to override/generate an initialize method. So I'm wondering what is the best way to test a module?
I'm also wondering wether my module should become a class at this point since the initialize method is made for initializing the state of something. Opinions?
Thanks in advance !
Including an initialize method in a module feels very wrong to me, so I'd rethink that at the very least.
To answer your question about testing this as a module more directly, though, I would create a new, empty class, include your module in it, create an instance of that class, and then test against that instance:
class TestClass
include MyModule
end
class TestMyModule < Unit::Test::TestCase
def setup
#instance = TestClass.new
end
def test_my_func
assert_equal(5, #instance.my_func) # test the output value given the input params
end
end
Yeah, your initialize should definitely suggest that you're going towards a class. A module in ruby often feels like an interface in other languages, as long as you implement some basic things when you include the module you'll get a lot for free.
Enumerable is a great example, as long as you define [] and each when you include Enumerable you suddenly get pop, push, etc.
So my gut feeling about testing modules is that you should probably be testing classes that include the module rather than testing the module itself unless the module is designed to not be included in anything, it's simply a code storage mechanism.
I have a large class with lots of methods and it's starting to get a bit unorganized and hard to navigate. I'd like to break it up into modules, where each module is a collection of class and instance methods. Perhaps something like this:
UPDATE: I've now realized that this is a pretty poor example. You probably wouldn't want to move validations or attributes out of the core class.
class Large
include Validations
include Attributes
include BusinessLogic
include Callbacks
end
After reading Yehuda's post about Better Ruby Idioms, I'm curious how others are tackling this problem. Here's the two methods I can think of.
First Method
module Foo
module Validations
module ClassMethods
def bar
"bar"
end
end
module InstanceMethods
def baz
"baz"
end
end
end
class Large
extend Validations::ClassMethods
include Validations::InstanceMethods
end
end
Second Method
module Foo
module Validations
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def bar
"bar"
end
end
def baz
"baz"
end
end
class Base
include Validations
end
end
My questions are:
Is there a better way to do this?
How do you get a one-liner module mixin for a set of class/instance methods with the least amount of magic?
How do you namespace these modules to the base class without namespacing the class itself?
How do you organize these files?
Breaking a class into modules, while tempting (because it's so easy in Ruby), is rarely the right answer. I usually regard the temptation to break out modules as the code's way of telling me it wants to be split into more tightly-focussed classes. A class that's so big you want to break it into multiple files is pretty much guaranteed to be violating the Single Responsibility Principle.
EDIT: To elaborate a bit on why breaking code into modules is a bad idea: it's confusing to the reader/maintainer. A class should represent a single tightly-focussed concept. It's bad enough when you have to scroll hundreds of lines to find the definition of an instance method used at the other end of a long class file. It's even worse when you come across an instance method call and have to go looking in another file for it.
After doing what Avdi said, these are the things I would do before putting anything into a module:
Whether this module can or will be used in any other class?
Would it make sense to extract the functionality of these modules into a different or base class?
If the answer for 1 is no and 2 is yes then IMHO that indicates to better have a class rather a module.
Also, I think putting attributes in a module is conceptually wrong because classes never share their attributes or instance variables or in other words their internal state with any other class. The attributes of a class belongs to that class only.
Business logics do definitely belong to the class itself and if the business logic of class A has some common responsibilities with class C then that needs to be extracted into a base class to make it clear instead of just putting it into a module.
The standard idiom seems to be
foo.rb
foo/base.rb
foo/validations.rb
foo/network.rb
foo/bar.rb
and foo.rb would be something like
class Foo
include Foo::Base
include Foo::Validations
include Foo::Network
include Foo::Bar
end
This is the standard idiom, and it works fairly well for letting you break things up. Don't do class methods vs instance methods. Those are generally pretty arbitrary distinctions, and you're better off putting code that deals with similar subjects together. That will minimize how many files you have to touch for any given change.
BEWARE: Rails can get confused by nesting models like this, at least if everything were classes. I think it'll do better with all the nested files just being modules, but you'll have to see. I'm still suggesting this because it's the normal idiom used by the Ruby community, but you may have to avoid having both a foo.rb and a foo/ directory amongst your Rails models (if that's the kind of class you're talking about).
Although including different modules will work, it is generally more troublesome than simply reopening the class in multiple places.
There is a (very simple) gem that you can use to makes this as pretty as can be: concerned_with
Example (from the readme)
# app/models/user.rb
class User < ActiveRecord::Base
concerned_with :validations,
:authentication
end
# app/models/user/validations.rb
class User < ActiveRecord::Base
validates_presence_of :name
end
#app/models/user/authentication.rb
class User < ActiveRecord::Base
def self.authenticate(name, password)
find_by_name_and_password(name, password)
end
end
I tend to use Ruby's duck typing approach to interfaces, which basically allows you to send any message to any object, which then evaluates what to do with it.
This approach allows me to stick to the same pattern Avdi mentions, keeping classes small and concise- only ever being responsible for one thing.
The great thing about Ruby is that you can delegate responsibilities to other concise classes, without muddling any of the logic together. For example:
class Dog
def initialize(name)
#name = name
end
def bark
"woof"
end
def fetch(object)
"here's that #{object}"
end
def sit
"sitting down"
end
private
attr_accessor :name
end
Here we have my dog class that has loads of dog related methods. They're all specific to dog, so could happily reside here. However, there would be a problem if these methods got a bit complex, calling other methods or perhaps this dog learns a bunch of new tricks!? So I could separate these out into their own classes and then delegate responsibility to those, like so:
class Tricks
def initialize(name)
#name = name
end
def fetch(object)
"here's that #{object}"
end
def sit
"sitting down"
end
def come_when_called(my_name)
"I'm coming" if my_name == name
end
def put_toy_away(object)
"#{fetch(object)}, I'll put it away"
end
private
attr_reader :name
end
class Dog
def initialize(name)
#name = name
end
delegate :sit, :fetch, :come_when_called, :put_away_toy, to: :tricks_klass
def bark
"woof"
end
private
attr_accessor :name
def tricks_klass
#tricks_klass ||= Tricks.new(name)
end
end
So now, that Dog class really starts to behave like an interface to dog-related behaviors, whilst these tricks are no longer coupled to it. This'll make testing easier by being able to instantiate a Tricks object and test it more generically, without the need for a Dog (because they don't always listen).
Now, we could have a Cat class that delegates responsibility to this Tricks class as well- although, that'd be one smart Cat!
You could also now use the Tricks class on its own- that's the power encapsulating single behavior its own class. You could even separate these behaviors even further- but only you as the developer know if that's worth while!
John Nunemaker recently blogged about the various ways to define class methods in Ruby, giving these three alternatives:
# Way 1
class Foo
def self.bar
puts 'class method'
end
end
# Way 2
class Foo
class << self
def bar
puts 'class method'
end
end
end
# Way 3
class Foo; end
def Foo.bar
puts 'class method'
end
What's your preferred way to do this?
Do you prefer something other than those above?
If you use more than one way, under what circumstances do you use them?
I consistently use Way 1:
class Foo
def self.bar
puts 'class method'
end
end
It's not verbose, and it keeps the method in the same context of the class.
I generally prefer def self.foo for single methods, and class << self for long stretches of class methods. I feel it makes the distinction between the class method part and the instance method part of the class definition.
I prefer Way 1 as it isn't context sensitive. I dislike jumping into the middle of a file and then having to scroll up or down to see if the indentation means I'm in a class << self block or if it's just a nested module.
Agree with most of the users. I tend to use primarily the
# Way 1
class Foo
def self.bar
puts 'class method'
end
end
There are some small differences, if I recall correctly, that are shown on the Pragmatic Programmers Metaprogramming talks (which I recommend), which relate to how the class code is called and executed.
They were quite small, though and mostly things we won't have to deal with on a normal basis. Will see if I can check them out and post it.
I view << for adding a method as too unusual (though I happily use << with strings and IO).
I avoid Foo.bar because it means repeating yourself.
I use Way #3, but I think Way #1 is great also. It depends on your usage. If you want your code to be "cut/pastable" into other modules and classes, then Way #1 is better. I use Way #3 to actually make it more of pain to cut/paste code, b/c Ruby's mantra is "don't repeat yourself" so you shouldn't cut/paste code very often..