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
Related
I am trying to get programm started where i cant read in a csv File an it prints the data out on a pdf-File. Now i have a problem.
Heres is my Code:
------------------------------------
require_relative 'friends'
class List
attr_accessor :list_name, :list
def initialize(list_name)
#list_name = list_name
#list = []
end
def list_name
#list_name
end
def liste
#list
end
def wert(place)
#list[place].to_s
end
def list_length
#list.length
end
def print_list
#list.each do |freunde|
"#{freunde.name},#{freunde.age}"
end
end
def add_friend(a_friend)
#list.push(a_friend)
end
def load_friend(from_file)
File.readlines(from_file).each do |line|
add_friend(Freunde.from_csv(line))
end
end
end
-------------------------------------------
require_relative 'list'
class Friends
attr_accessor :name,:age
def initialize(name, age)
#name = name
#age = age
end
def self.from_csv(string)
name, age = string.split(',')
Freunde.new(name,age)
end
def friends
#name
end
end
-------------------------------------------
require 'prawn'
require_relative 'list'
require_relative 'friends'
class Generating
include Prawn::View
def initialize
#document = Prawn::Document.new(:page_size => "A4")
#fontpath = File.expand_path("../data/fonts", __FILE__)
liste1 = Listen.new("Friendslist")
liste1.load_friend("test.csv")
print_list
save
end
def print_friends
font("#{#fontpath}/Arial.ttf") do
font_size 11
text_box("#{liste1.print_list}", :at => [15,405], :height => 50,
:width => 250)
end
end
def save
self.render_file "Hello.pdf"
end
end
---------------------------------------------
When i now create a new generating-Object:
gen = Generating.new
then it fails the whole programm because the error says method unknow (print_list). Am i submitting the wrong object for the method(print_list), or am using the text output methods of prawn wrong?
print_list is an instance method of List class, and you call it on self object, which is there an instance of Generating. It should be:
liste1 = Listen.new("Friendslist")
liste1.load_friend("test.csv")
#⇓⇓⇓⇓⇓⇓
liste1.print_list
So I'm trying to create a basic text adventure in ruby, and I'm roughly following a tutorial (https://jsrn.gitbooks.io/make-your-first-text-adventure-in-ruby/content/creating_the_framework.html)
But when I try and run my code I get this error:
GameBase.rb:10:in `initialize': uninitialized constant Game::World (NameError)
from GameBase.rb:55:in `new'
from GameBase.rb:55:in `<main>'
This is my code:
From GameBase.rb
Dir["GameDir/**.*"].each { |file| require_relative file }
class Game
Actions = [
:forward, :backward, :look, :attack, :loot, :inventory, :use, :cast
]
def initialize
#world = World.new
#player = Player.new
start_game
end
private
def start_game
while #player.alive?
#current_room = #world.get_room_of(#player)
print_player_status
action = take_player_input
next unless ACTIONS.include? action
take_action(action)
end
end
def take_player_input
print "What do you do?"
gets.chomp.to_sym
end
def take_action(action)
case action
when :forward
#world
when :backward
#world
when :look
#world
when :attack
#current_room.interact(#player)
when :loot
#current_room.interact(#player)
when :inventory
when :use
when :cast
end
end
end
Game.new
And from world.rb
class World
def initialize
#past_rooms = 0
#current_room = 0
end
def move_entity_forward(entity)
#current_room += 1
end
def move_entity_backward(entity)
#current_room -= 1
end
def get_room_of(entity)
if #current_room <= #past_rooms then #current_room
else
Room.new
#past_rooms += 1 end
end
end
class Room
attr_accessor :size, :content
def initialize
#content = get_content
#size = get_size
#adjetive = get_adjetive
end
def interact(player)
if #content
#content.interact(player)
#content = nil
else
puts "There isn't anything here..."
end
end
private
def get_content
[Monster, Item.sample.new]
end
def get_size
dimensions = [5, 10, 15, 20, 25, 30, 40, 50, 75, 100, 200]
"#{dimensions.sample}'x#{dimensions.sample}'"
end
def get_adjetive
["well-lit", "dim", "filthy", "suprisingly clean", "round", "muddy", "oppressive"]
end
end
Try adding this line to the top of GameBase.rb:
require_relative 'world'
This tells the Ruby interpreter to look for a file named world.rb in the same folder as GameBase.rb and run the code in that file, which would define the World class. Then the World class would be available when you try to use it.
So, I ran into the same problem because I didn't see instructions in the tutorial that the extra files (world.rb, player.rb, etc.) are expected to be in a subfolder. I had them all in the same folder, game.rb , which was causing this error.
The first line of code in game.rb is telling Ruby where to load all the related game files
Dir["GameDir/**.*"]
So, if your game.rb file is in a directory 'game' for example, then all the related files need to be in a directory game>GameDir since you are telling it to look in the GameDir folder.
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}"
There is the following code:
class MyOpenStruct
def initialize(initial_values = {})
#values = initial_values
end
def _singleton_class
class << self
self
end
end
def method_missing(name, *args, &block)
if name[-1] == "="
base_name = name[0..-2].intern
puts "add_method_to_set"
self.class.add_method_to_set(base_name)
#values[base_name] = args[0]
else
puts "add_method_to_get"
self.class.add_method_to_get(base_name)
#values[name]
end
end
def self.add_method_to_get(name)
define_method(name) do |value|
#values[name]
end
end
def self.add_method_to_set(name)
define_method(name) do |value|
#values[name] = value
end
end
end
obj1 = MyOpenStruct.new(name: "Dave")
obj1.address = "1"
obj2 = MyOpenStruct.new(name: "Dave")
obj2.address = "2"
I want to do the following thing: when I execute some method (obj1.address) and it's missing I want to add this method to my MyOpenStruct class. But when I execute my code I get 'missing' two times instead of one. Why? I don't understand. Please explain it to me. Thanks.
#koffeinfrei identified one problem with you code, but I found a few others. Below I have what I believe to be a corrected version. I have also suggested an alternative way to structure the code. My main advice is to pull out the dynamic creation of instance methods, as that is quite generic. You might even put that in a module with other methods that you could include as needed.
Your code with repairs
class MyOpenStruct
def initialize(initial_values = {})
#values = initial_values
end
def method_missing(name, *args, &block)
puts "in mm, name = #{name}"
if name[-1] == "="
base_name = name[/\w+/]
puts "add_method_to_set: '#{name}'"
self.class.add_method_to_set(base_name)
#values[base_name.to_sym] = args[0]
else
puts "add_method_to_get: '#{name}'"
self.class.add_method_to_get(name)
#values[name.to_sym]
end
end
def self.add_method_to_get(name)
define_method(name.to_sym) do
#values[name.to_sym]
end
end
def self.add_method_to_set(name)
define_method((name+'=').to_sym) do |value|
#values[name.to_sym] = value
end
end
end
Alternative construction
def create_instance_eval(klass, method, &block)
klass.class_eval { define_method(method, &block) }
end
class MyOpenStruct
def initialize(initial_values = {})
#values = initial_values
end
def method_missing(name, *args, &block)
if name[-1] == "="
base_name = name[/\w+/]
method_name = (base_name+'=').to_sym
puts "create method '#{method_name}'"
method = create_instance_eval(self.class, method_name) do |value|
#values[base_name.to_sym] = value
end
send(method, args[0])
else
method_name = name.to_sym
puts "create method '#{method_name}'"
method = create_instance_eval(self.class, method_name) do
#values[method_name]
end
send(method)
end
end
end
Example
MyOpenStruct.instance_methods(false)
#=> [:method_missing]
obj1 = MyOpenStruct.new(name: "Dave")
#=> #<MyOpenStruct:0x00000102805b58 #values={:name=>"Dave"}>
obj1.address = "1"
# create method 'address='
#=> "1"
MyOpenStruct.instance_methods(false)
#=> [:method_missing, :address=]
obj2 = MyOpenStruct.new(name: "Mitzy")
#=> #<MyOpenStruct:0x00000101848878 #values={:name=>"Mitzy"}>
obj2.address = 2
#=> 2
obj2.address
# create method 'address'
# => 2
MyOpenStruct.instance_methods(false)
$#=> [:method_missing, :address=, :address]
obj1.instance_variable_get(:#values)
#=> {:name=>"Dave", :address=>"1"}
obj2.instance_variable_get(:#values)
#=> {:name=>"Mitzy", :address=>2}
The method name for the setter method needs to have the trailing =, so you need to define the method with the name instead of the base_name.
self.class.add_method_to_set(name)
(Big edit, I got part of the way there…)
I've been hacking away and I've come up with this as a way to specify things that need to be done before attributes are read:
class Class
def attr_reader(*params)
if block_given?
params.each do |sym|
define_method(sym) do
yield
self.instance_variable_get("##{sym}")
end
end
else
params.each do |sym|
attr sym
end
end
end
end
class Test
attr_reader :normal
attr_reader(:jp,:nope) { changethings if #nope.nil? }
def initialize
#normal = "Normal"
#jp = "JP"
#done = false
end
def changethings
p "doing"
#jp = "Haha!"
#nope = "poop"
end
end
j = Test.new
p j.normal
p j.jp
But changethings isn't being recognised as a method — anyone got any ideas?
You need to evaluate the block in the context of the instance. yield by default will evaluate it in its native context.
class Class
def attr_reader(*params, &blk)
if block_given?
params.each do |sym|
define_method(sym) do
self.instance_eval(&blk)
self.instance_variable_get("##{sym}")
end
end
else
params.each do |sym|
attr sym
end
end
end
end
Here's another alternative approach you can look at. It's not as elegant as what you're trying to do using define_method but it's maybe worth looking at.
Add a new method lazy_attr_reader to Class
class Class
def lazy_attr_reader(*vars)
options = vars.last.is_a?(::Hash) ? vars.pop : {}
# get the name of the method that will populate the attribute from options
# default to 'get_things'
init_method = options[:via] || 'get_things'
vars.each do |var|
class_eval("def #{var}; #{init_method} if !defined? ##{var}; ##{var}; end")
end
end
end
Then use it like this:
class Test
lazy_attr_reader :name, :via => "name_loader"
def name_loader
#name = "Bob"
end
end
In action:
irb(main):145:0> t = Test.new
=> #<Test:0x2d6291c>
irb(main):146:0> t.name
=> "Bob"
IMHO changing the context of the block is pretty counter-intuitive, from a perspective of someone who would use such attr_reader on steroids.
Perhaps you should consider plain ol' "specify method name using optional arguments" approach:
def lazy_attr_reader(*args, params)
args.each do |e|
define_method(e) do
send(params[:init]) if params[:init] && !instance_variable_get("##{e}")
instance_variable_get("##{e}")
end
end
end
class Foo
lazy_attr_reader :foo, :bar, :init => :load
def load
#foo = 'foo'
#bar = 'bar'
end
end
f = Foo.new
puts f.bar
#=> bar