Practicing defining Classes and Methods in Ruby [closed] - ruby

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm having the following error "Line 46: undefined local variable or method `app1' for main:Object (NameError)" when I run the following Ruby code about Methods and Classes on the compiler.Thanks in advance :D!!
class Apps
def initialize(name)
#name = name
end
def add_app
"#{name} has been added to the App Center.Approval is pending!!"
end
def app_approved
"#{name} has been approved by the App Center"
end
def app_posted
"Congratulations!!!!#{name} has been posted to the App Store."
end
end
class Fbapps
def initialize(name)
#name = name
#apps = []
end
def add_new(a_app)
#apps << a_app
"#{#app} has been added to the #{#apps} store!!"
end
def weekly_release
#apps.each do |app|
puts #app
end
#apps.each do |app|
app.add_app
app.app_approved
app.app_posted
end
end
end
apps = ["Bitstrip", "Candy Crush" , "Instapaper"]
apps = Fbapps.new("Apps")
apps.add_new(app1)
apps.add_new(app2)
apps.add_new(app3)
puts apps.weekly_release
app1 = Apps.new("Bitstrip")
app2 = Apps.new("Candy Crush")
app3 = Apps.new("Instapaper")

You need to create app1, app2, and app3 before adding them to apps:
apps = ["Bitstrip", "Candy Crush" , "Instapaper"]
app1 = Apps.new("Bitstrip")
app2 = Apps.new("Candy Crush")
app3 = Apps.new("Instapaper")
apps = Fbapps.new("Apps")
apps.add_new(app1)
apps.add_new(app2)
apps.add_new(app3)
puts apps.weekly_release
As noted there are other bugs in your classes, but they should be relatively trivial to fix given changing the order of execution as above.
Update: Here's your code updated to fix most of the bugs:
class Apps
attr_accessor :name
def initialize(name)
#name = name
end
def add_app
"#{name} has been added to the App Center.Approval is pending!!"
end
def app_approved
"#{name} has been approved by the App Center"
end
def app_posted
"Congratulations!!!! #{name} has been posted to the App Store."
end
end
class Fbapps
attr_accessor :name
def initialize(name)
#name = name
#apps = []
end
def add_new(a_app)
#apps << a_app
"#{a_app.name} has been added to the #{self.name} store!!"
end
def weekly_release
#apps.each do |app|
puts app.name
end
#apps.each do |app|
puts app.add_app
puts app.app_approved
puts app.app_posted
end
end
end

You're trying to do apps.add_new(app1) before you define app1. That line needs to go after app1 = Apps.new("Bitstrap") .

Related

Can someone point to me to the right direction but leading me with questions to ask myself to solve this error for my hw

So when I run my lab i am getting the following error:
Associations — Song and Artist: Artist #add_song adds the song to the current artist's 'songs' collection
Failure/Error: expect(artist.songs).to include(song)
expected ["In the Aeroplane Over the Sea"] to include #<Song:0x0000000001496e88 #name="In the Aeroplane Over the Sea", #artist=#<Artist:0x0000000001496f50 #name="Neutral Milk Hotel", #songs=["In the Aeroplane Over the Sea"]>>
Diff:
## -1,2 +1,2 ##
-[#<Song:0x0000000001496e88 #name="In the Aeroplane Over the Sea", #artist=#<Artist:0x0000000001496f50 #name="Neutral Milk Hotel", #songs=["In the Aeroplane Over the Sea"]>>]
+["In the Aeroplane Over the Sea"]
But when I run my code through pry, I can see the song added into the array of the instance variable, #songs. I am working with two classes, a song class and artist class.
class Artist
attr_accessor :name
attr_reader :songs
##all = []
def initialize(name)
#name = name
save
#songs = []
end
def self.all
##all
end
def save
##all << self
end
def self.destroy_all
##all.clear
end
def self.create(name)
self.new(name)
end
def add_song(song)
if song.artist == nil
song.artist = self
end
#checks if the same song has already been added, otherwise adds new song
if #songs.include?(song.name) == false
#songs << song.name
end
binding.pry
end
end
class Song
attr_accessor :name, :artist
##all =[]
def initialize(name, artist = nil)
#name = name
#artist = artist
save
end
def self. all
##all
end
def save
##all << self
end
def self.destroy_all
##all.clear
end
def self.create(name)
self.new(name)
end
end
Your tests are expecting an aray of Song instances. But what they find is an array of strings.
To fix it you'd just need to change #songs << song.name to #songs << song.
I am sorry if I just gave you the answer instead of hinting you along to solve it yourself, but this isn't really the right platform for that kind of thing. Every question on StackOverflow can be searched by users and we want to keep things helpful to them by getting straight to the point.
However, I can give some advice. Practice reading errors. Try and understand what the error is telling you.

Adapter Pattern in ruby: Accessing Your Instance Variables

I am studying the adapter pattern implementation in ruby. I want to access an instance variable within the adapter module definition. Take a look at the following code:
module Adapter
module Dog
def self.speak
# I want to access the #name instance variable from my Animal instance
puts "#{name} says: woof!"
end
end
module Cat
def self.speak
# I want to access the #name instance variable from my Animal instance
puts "#{name} says: meow!"
end
end
end
class Animal
attr_accessor :name
def initialize(name)
#name = name
end
def speak
self.adapter.speak
end
def adapter
return #adapter if #adapter
self.adapter = :dog
#adapter
end
def adapter=(adapter)
#adapter = Adapter.const_get(adapter.to_s.capitalize)
end
end
To test it out I did the following:
animal = Animal.new("catdog")
animal.adapter = :cat
animal.speak
I want it to return the following:
catdog says: meow!
Instead it says:
Adapter::Cat says: meow!
Any tips on how I can get access to the Animal#name instance method from the adapter module? I think the issue is that my adapter methods are class-level methods.
Thanks!
You need to use your Module as a mixin and provide a way to keep track of which module is active, the methods don't seem to be overwritten by reincluding or reextending so I took the extend and remove methods I found here.
module Adapter
module Dog
def speak
puts "#{name} says: woof!"
end
end
module Cat
def speak
puts "#{name} says: meow!"
end
end
def extend mod
#ancestors ||= {}
return if #ancestors[mod]
mod_clone = mod.clone
#ancestors[mod] = mod_clone
super mod_clone
end
def remove mod
mod_clone = #ancestors[mod]
mod_clone.instance_methods.each {|m| mod_clone.module_eval {remove_method m } }
#ancestors[mod] = nil
end
end
class Animal
include Adapter
attr_accessor :name, :adapter
def initialize(name)
#name = name
#adapter = Adapter::Dog
extend Adapter::Dog
end
def adapter=(adapter)
remove #adapter
extend Adapter::const_get(adapter.capitalize)
#adapter = Adapter.const_get(adapter.capitalize)
end
end
animal = Animal.new("catdog")
animal.speak # catdog says: woof!
animal.adapter = :cat
animal.speak # catdog says: meow!
animal.adapter = :dog
animal.speak # catdog says: woof!
This is because name inside of the module context refers to something entirely different than the name you're expecting. The Animal class and the Cat module do not share data, they have no relationship. Coincidentally you're calling Module#name which happens to return Adapter::Cat as that's the name of the module.
In order to get around this you need to do one of two things. Either make your module a mix-in (remove self, then include it as necessary) or share the necessary data by passing it in as an argument to speak.
The first method looks like this:
module Adapter
module Dog
def self.speak(name)
puts "#{name} says: woof!"
end
end
end
class Animal
attr_accessor :name
attr_reader :adapter
def initialize(name)
#name = name
self.adapter = :dog
end
def speak
self.adapter.speak(#name)
end
def adapter=(adapter)
#adapter = Adapter.const_get(adapter.to_s.capitalize)
end
end
That doesn't seem as simple as it could be as they basically live in two different worlds. A more Ruby-esque way is this:
module Adapter
module Dog
def speak
puts "#{name} says: woof!"
end
end
end
class Animal
attr_accessor :name
attr_reader :adapter
def initialize(name)
#name = name
self.adapter = :dog
end
def adapter=(adapter)
#adapter = Adapter.const_get(adapter.to_s.capitalize)
extend(#adapter)
end
end

Console printing backwards

I'm trying to get the code to print the name of a class and then greetings on the same line. For example:
(DriveThru): Hi, welcome to Starbucks! What can I get started for you?
Here's my code:
module Order
def order_drink
"(#{self.class.name}): #{self.greeting}"
end
end
class Lobby
include Order
attr_reader :name
def initialize(name)
#name = name
end
def greeting
puts "Hi, welcome to Starbucks! How are you doing today #{self.name}?"
end
end
class DriveThru
include Order
attr_reader :name
def initialize(name)
#name = name
end
def greeting
puts "Hi, welcome to Starbucks! What can I get started for you #{self.name}?"
end
end
dt = DriveThru.new("Tom")
lb = Lobby.new("Jessica")
puts dt.order_drink
puts lb.order_drink
When I run the code, it prints the greeting first, line breaks, then prints the class name like this:
"Hi, welcome to Starbucks! What can I get started for you?"
(DriveThru):
What am I'm doing wrong?
Your greeting function is executing the puts statement. Due to the way Ruby (and most other programming languages) works, the order_drink method will evaluate the contents of the greeting method (calling a puts statement) first before returning its own value.
Dropping the puts at the beginning of each greeting function, for example:
class Lobby
include Order
attr_reader :name
def initialize(name)
#name = name
end
def greeting
"Hi, welcome to Starbucks! How are you doing today #{self.name}?"
end
end
This will cause your script to output the following:
(DriveThru): Hi, welcome to Starbucks! What can I get started for you Tom?
(Lobby): Hi, welcome to Starbucks! How are you doing today Jessica?
That said, it'd be preferable to add an attr_reader for the greeting attribute, and set its value in the initialize method (also known as the constructor), like so:
class Lobby
include Order
attr_reader :name, :greeting
def initialize(name)
#name = name
#greeting = "Hi, welcome to Starbucks! How are you doing today #{name}?"
end
end

Is it possible to get rid of class variable?

I started with that question
My goal is to try an unusual, but interesting way of calling a block. I came to that code:
class Chips
def self.configure player_class, player_id_method, player_api_method
player_class.send :define_method, player_api_method do
Chips::Player.new(self.send player_id_method)
end
end
def self.fix_game game_id
##game_results = {game_id: game_id, players: []}
yield
puts ##game_results.inspect
end
class Player
def initialize player_id
#player_id= player_id
end
def gain chips
Chips.send :fix_player, #player_id, chips.abs
end
def lose chips
Chips.send :fix_player, #player_id, -chips.abs
end
end
def self.fix_player player_id, chips
##game_results[:players]<< {player_id: player_id, chips: chips}
end
private_class_method :fix_player
end
class User
attr_reader :email
def initialize email
#email = email
end
end
Chips.configure User, :email, :chips
p1= User.new 'david#gmail.com'
p2= User.new 'simon#gmail.com'
# p1.chips and p2.chips should have access to the value
# currently accessible by ##game_results reference
Chips.fix_game 3333 do
p1.chips.gain 300
p2.chips.lose 300
end
... which outputs {:game_id=>3333, :players=>[{:player_id=>"david#gmail.com", :chips=>300}, {:player_id=>"simon#gmail.com", :chips=>-300}]}
I would like to avoid class variable using.
ps
Question creation form hadn't allow me to submit this question until I added more words, which are in fact a pray to The Mighty Doorkeeper. I've brought you more bytes, TMD. I obey.

What is wrong with this Ruby code 2? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
What is wrong with this code?
class Person
def initialize(name)
#name = name
end
def greet(other_name)
"Hi #{other_name}, my name is #{name}"
end
end
Write the code as
class Person
def initialize(name)
#name = name
end
def greet(other_name)
"Hi #{other_name}, my name is #{#name}" # <~~ you missed `#` before name.
end
end
If you write only name(instead of #name), Ruby will try to look for a local var named as name, but you didn't define any. Then it will try to check if any method you have defined as name or not, that also not present. So finally you will get
undefined local variable or method `name'
Here is an example after the fix :
#!/usr/bin/env ruby
class Person
def initialize(name)
#name = name
end
def greet(other_name)
"Hi #{other_name}, my name is #{#name}"
end
end
Person.new("Raju").greet('Welcome!') # => "Hi Welcome!, my name is Raju"

Resources