FactoryMethod pattern on Ruby - ruby

I'm learning the design patterns. How do you think is it an appropriate example of FactoryMethod pattern?
There are Unit and its subclasses: Soldier and Doctor. They can greet somehow. There are also UnitFactory, SoldierFactory and DoctorFactory. They produce according units.
class Unit
class GreetError < StandardError; end
def greet; raise GreetError; end
end
class Soldier < Unit
def greet; 'I am a soldier'; end
end
class Doctor < Unit
def greet; 'I am a doctor'; end
end
class UnitFactory
class CreateUnitError < StandardError; end
def create_unit; raise CreateUnitError; end
end
class SoldierFactory < UnitFactory
def create_unit; Soldier.new; end
end
class DoctorFactory < UnitFactory
def create_unit; Doctor.new; end
end
class Army
attr_reader :unit_factory, :count, :units
def initialize(unit_factory, count)
#unit_factory = unit_factory
#count = count
#units = []
gather
end
def gather
count.times { units << unit_factory.create_unit }
end
def greet
units.map { |unit| unit.greet }
end
end

Related

Uninitialized constant Van (NameError)

I am trying to write some functionality which allows me to take a broken bike to a garage to have it fixed, whilst implementing this i have come across this issue. i understand that this usually is because it cannot find the file but have ran out of ideas on how to fix it. If you need any of the other code let me know but i thought this would be all the code needed.
dockingstation.rb:
require_relative 'Bike'
require_relative 'van'
require_relative 'garage'
class DockingStation
attr_reader :dock, :max_dock, :DEFAULT_CAPACITY
DEFAULT_CAPACITY = 20
def initialize(capacity = DEFAULT_CAPACITY)
#max_dock = capacity
#dock = []
end
def release_bike
if !empty?
#dock.each_with_index do |bike, index|
if bike.working?
#dock.delete_at(index)
return bike
else
raise "Bike is broken"
end
end
else
raise "No bikes to release"
end
end
def dock_bike(bike, working = true)
if !full?
#dock << bike
else
raise "Too many bikes"
end
end
def show_dock
#dock.each do |el|
return el
end
end
def van_takes_broken_bikes(van)
puts #dock
#dock.each_with_index do |bike, index|
if bike.working? == true
van.storage.append(bike)
else
van.storage.append(bike)
end
end
end
private def full?
#dock.length == #max_dock
end
private def empty?
#dock.length == 0
end
end
dock = DockingStation.new
bike = Bike.new
van = Van.new
bike.report_broken
dock.dock_bike(bike)
dock.van_takes_broken_bikes(van)
van.rb:
require_relative 'dockingstation'
require_relative 'garage'
class Van
attr_reader :storage
def initialize
#storage = []
end
def take_broken_bikes_to_garage(bikes)
end
end

Ruby Program is not printing on screen

Good day everyone. I am writing a simple ruby code but it doesn't print on the screen I am using ruby 2.2.2 and my IDE is Rubymine 7.Thanks in advance.Here is the code;
class Animal
attr_accessor :name, :colour
def initialize(name,colour)
#name = name
#colour = colour
end
def to_s
"Name#{#name} Colour #{#colour}"
end
end
class Cheetah < Animal
attr_reader :speed
def initialize(name,colour,speed)
#speed = speed
super (name,colour)
end
def to_s
return super + "Speed#{#speed}kph"
end
end
class Zoo < Animal
def initialize
#animals = []
end
def add_animals(animal)
#animals << animal
end
def my_animals
cage = ""
#animal.each do|call|
cage += call.to_s
end
end
end
5.times do|count|
Zoo.add_animals(MyAnimal.new("Cheetah#{count}","yello and black spots"))
end
puts "#{Zoo.my_animals}"
My_cheetah = Cheetah.new("Cheetah","yello and black spots",180)
puts "#{My_cheetah.to_s}"
class Animal
attr_accessor :name, :colour
def initialize(name,colour)
#name = name
#colour = colour
end
def to_s
"Name#{#name} Colour #{#colour}"
end
end
class Cheetah < Animal
attr_reader :speed
def initialize(name,colour,speed)
#speed = speed
super(name,colour)
end
def to_s
return super + "Speed#{#speed}kph"
end
end
class Zoo < Animal
def initialize
#animals = []
end
def add_animal(animal)
#animals << animal
end
def my_animals
cage = ""
#animals.each do |call|
cage += call.to_s
end
cage
end
end
zoo = Zoo.new
5.times do|count|
zoo.add_animal(Animal.new("Cheetah#{count}","yello and black spots"))
end
puts "#{zoo.my_animals}"
my_cheetah = Cheetah.new("Cheetah","yello and black spots",180)
puts "#{my_cheetah.to_s}"

"Namespaced" methods in Ruby

There is a class with "namespaced" methods:
class MyOrder
def add
end
def edit
end
end
class MyCompany
def list
end
end
class MyDriver
def add
end
def edit
end
end
class MyAPI
attr_reader :order, :company, :driver
def initialize
#order = MyOrder.new
#company = MyCompany.new
#driver = MyDriver.new
end
end
The idea is to group methods into sections to call them like:
api = MyApi.new
api.order.add
api.company.list
Is there some way to group methods without creating container classes?
class MyAPI
def initialize
#namespace = []
end
def self.namespace sym
define_method(sym){#namespace.push(sym); self}
end
namespace :order
namespace :company
namespace :driver
def add
case #namespace
when [:order] then ...
when [:driver] then ...
else raise "invalid namespace"
end
#namespace = []
self
end
def edit
case #namespace
when [:order] then ...
when [:driver] then ...
else raise "invalid namespace"
end
#namespace = []
self
end
def list
case #namespace
when [:company] then ...
else raise "invalid namespace"
end
#namespace = []
self
end
end
The self at the end of the methods is to let you be able to do chaining like
MyApi.new.order.add.company.list
If you don't need to do this, then self is unnecessary.
Ok, I see, try the following:
module MyApi
[MyOrder, MyCompany, MyDriver].each do |klass|
names = klass.to_s.scan(/[A-Z][a-z]+/)
funcname = names[1].downcase
define_singleton_method(funcname) do
instance_variable_get("##{funcname}") ||
instance_variable_set("##{funcname}", klass.new)
end
end
end
MyApi.order.add
If you prefer to order_add, then:
module MyApi
[MyOrder, MyCompany, MyDriver].each do |klass|
names = klass.to_s.scan(/[A-Z][a-z]+/)
prefix_name = names[1].downcase
klass.public_instance_methods(false).each do |method|
funcname = "#{prefix_name}_#{method}"
define_singleton_method(funcname) do |*args|
#obj = instance_variable_get("##{prefix_name}") ||
instance_variable_set("##{prefix_name}", klass.new)
#obj.send(method, *args)
end
end
end
end

How do I list all objects created from a class in Ruby? [duplicate]

This question already has answers here:
How to find each instance of a class in Ruby
(4 answers)
Closed 7 years ago.
Is there any way in Ruby for a class to know how many instances of it exist and can it list them?
Here is a sample class:
class Project
attr_accessor :name, :tasks
def initialize(options)
#name = options[:name]
#tasks = options[:tasks]
end
def self.all
# return listing of project objects
end
def self.count
# return a count of existing projects
end
end
Now I create project objects of this class:
options1 = {
name: 'Building house',
priority: 2,
tasks: []
}
options2 = {
name: 'Getting a loan from the Bank',
priority: 3,
tasks: []
}
#project1 = Project.new(options1)
#project2 = Project.new(options2)
What I would like is to have class methods like Project.all and Project.count to return a listing and count of current projects.
How do I do this?
You can use the ObjectSpace module to do this, specifically the each_object method.
ObjectSpace.each_object(Project).count
For completeness, here's how you would use that in your class (hat tip to sawa)
class Project
# ...
def self.all
ObjectSpace.each_object(self).to_a
end
def self.count
all.count
end
end
One way to do is to keep track of it as and when you create new instances.
class Project
##count = 0
##instances = []
def initialize(options)
##count += 1
##instances << self
end
def self.all
##instances.inspect
end
def self.count
##count
end
end
If you want to use ObjectSpace, then its
def self.count
ObjectSpace.each_object(self).count
end
def self.all
ObjectSpace.each_object(self).to_a
end
class Project
def self.all; ObjectSpace.each_object(self).to_a end
def self.count; all.length end
end
Maybe this will work:
class Project
class << self; attr_accessor :instances; end
attr_accessor :name, :tasks
def initialize(options)
#name = options[:name]
#tasks = options[:tasks]
self.class.instances ||= Array.new
self.class.instances << self
end
def self.all
# return listing of project objects
instances ? instances.dup : []
end
def self.count
# return a count of existing projects
instances ? instances.count : 0
end
def destroy
self.class.instances.delete(self)
end
end
But you will have to manually destroy these objects. Maybe other solution can be build based on ObjectSpace module.

How to share methods between ActionMailers

I have two mailers:
class Mailer1 < ActionMailer::Base
def mail
if check_something?
end
end
private
def check_something?
end
end
class Mailer2 < ActionMailer::Base
def another_mail
if check_something?
end
end
private
def check_something?
end
end
(I understand I can pull in view helpers for the actual mail templates, but how can I make it work for controller-type "helper" methods - as ActionMailers derive from Abstract Controller these days.)
So, where can I declare check_something?, and how can I make it accessible to both my mailers?
Just create a base class, like you get by default with ApplicationController for your http controllers:
class AppMailer < ActionMailer::Base
protected
def check_something?
end
end
class Mailer1 < AppMailer
def mail
if check_something?
end
end
end
class Mailer2 < AppMailer
def another_mail
if check_something?
end
end
end

Resources