I'm trying to to create my getters and setters using attr_accessor. I want to assign a value to my variables.
Here is my code:
class Person
def initialize(name)
attr_accessor :name
end
def initialize(age)
attr_accessor :age
end
end
person1 = Person.new
person1.name = "Andre"
person1.age = 22
I get some trouble though. My error is:
q5.rb:6:in `initialize': wrong number of arguments (given 0, expected 1) (ArgumentError)
This is what you're trying to do:
class Person
attr_accessor :name, :age
end
person1 = Person.new
person1.name = "Andre"
person1.age = 22
An alternative approach, for example, could be:
class Person
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
end
person1 = Person.new("Andre", 22)
The error you're seeing is because you defined (and then re-defined) an initialize method that is expecting one parameter:
def initialize(name)
and then tried to create an object without supplying a parameter:
person1 = Person.new
Related
I have been working with Ruby for three days. I am trying to set a default in the way shown below, for #happiness. i need #happiness to have a range of 0-10, cannot be less than zero or more than ten. Thanks in advance.
class Person
attr_reader :name
attr_accessor :bank_account, :happiness={value > 11}
def initialize(name)
#name = name
#bank_account = 25
#happiness = 8
end
end
If you need a writer method that performs some validation, then you have to write a writer method which performs that validation. For example, something like this:
class Person
attr_reader :name, :happiness
attr_accessor :bank_account
def initialize(name)
#name = name
#bank_account = 25
#happiness = 8
end
def happiness=(value)
raise ArgumentError, "`happiness` needs to be between 0 and 10, but you supplied `#{value}`" unless 0..10 === value
#happiness = value
end
end
I am trying to convert any class into a hash using ruby. The initial implementation I have done:
class Object
def to_hash
instance_variables.map{ |v|
Hash[v.to_s.delete("#").to_sym, instance_variable_get(v)] }.inject(:merge)
end
end
Everything seemed to work ok. But when I tried the following code:
class Person
attr_accessor :name, :pet
def initialize(name, pet)
#name = name
#pet = pet
end
end
class Pet
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
end
tom = Person.new("Tom", Pet.new("Tobby", 5))
puts tom.to_hash
I have got the following output
{:name=>"Tom", :pet=>#<Pet:0x0055ff94072378 #name="Tobby", #age=5>}
I am unable to hash the attribute pet of type Pet (or any other custom class)
Any ideas?
Edit
That's what I would expect to be returned:
{:name=>"Tom", :pet=>{ :name=>"Tobby", :age=>5}}
When you want to have associated objects to be returned as a hash too hen you have to call to_hash recursively:
class Object
def to_hash
return self if instance_variables.empty?
instance_variables
.map { |v| [v.to_s.delete("#").to_sym, instance_variable_get(v).to_hash] }
.to_h
end
end
tom = Person.new("Tom", Pet.new("Tobby", 5))
puts tom.to_hash
#=> { :name=>"Tom", :pet => { :name=>"Tobby", :age=>5 } }
Here's code that works but I'm looking to make it as clean as possible, to get the output without having to build a hash.
class Person
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
def create
Report.create({name: #name, age: #age})
end
end
class Report < Person
def self.create(attributes)
puts "Hello, this is my report. I am #{attributes[:name]} and my age is #{attributes[:age]}."
end
end
me = Person.new("Andy", 34)
me.create # Hello, this is my report. I am Andy and my age is 34.
Here are my changes that didn't work, but is there a method that would?
def create
Report.create
end
and
def self.create(attributes)
puts "Hello, this is my report. I am #{:name} and my age is #{:age}."
end
but the output was "I am name and my age is age."
You could just pass the person, something like this:
class Person
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
def report
Report.new(self)
end
end
class Report
attr_accessor :person
def initialize(person)
#person = person
end
def to_s
"Hello, this is my report. I am #{person.name} and my age is #{person.age}."
end
end
me = Person.new("Andy", 34)
puts me.report
# Hello, this is my report. I am Andy and my age is 34.
Note that I've changed some details:
Report doesn't inherit from Person
Report instances are created via new
Person#create is now Person#report
Report uses to_s for the output (which is called by puts)
Im a bit confused on the initialize method. I understand that it is automatically called when you do Person.new and you add the arguments to it like Person.new("james"). What I dont understand is, why would you have instance variables in your initialize method that are not an used as an argument also. Is it so you can use them later on after the instance has been created?
See below. What reason is there to have #age in the initialize method but not as an argument. thanks.
class Person
attr_accessor :name, :age
def initialize(name)
#name = name
#age = age
end
You can set an instance variable in any method in your class.
initialize is a method that is executed immediately after calling Person.new.
All external data for new object is passed through the arguments of .new(args).
Your line #age = age - it's the same that #age = nil.
This is due to the fact that age is absent in the arguments of initialize.
Also you have attr_accessor :age.
It's equal, that you have methods:
def age
#age
end
def age=(age)
#age = age
end
So you can set instance variable like this:
john = Person.new('John')
p john.age #=> nil
john.age = 5
p john.age #=> 5
The instance variables declared inside your initialize method only need to be those which you want to set during initialization. In your Person class example, you wouldn't need to set #age in initialization (it actually would throw an error as you currently have it).
class Person
attr_accessor :name, :age
def initialize(name)
#name = name
end
def birthday
if #age.nil?
#age = 1
else
#age += 1
end
end
end
Hopefully, this helps. If the initialize method doesn't have an age set, you can still use/set age in other methods. In this case, the first time the Person.birthday method is called, it would set their #age to 1, and then increment it from there.
For example if you need to call a method to assign a value to the instance variable while instantiating the object.
This is silly, but gives an idea:
class Person
attr_accessor :name, :age
def initialize(name)
#name = name
#age = random_age
end
def random_age
rand(1..100)
end
end
jack = Person.new('jack')
p jack.age #=> 29
Im struggling on understanding (after googling) on how to implement this: I have a class:
class Student
# constructor method
def initialize(name,age)
#name, #age = name, age
end
# accessor methods
def getName
#name
end
def getAge
#age
end
# setter methods
def setName=(value)
#name = value
end
def setAge=(value)
#age = value
end
end
And lets say I have another class which inherits from Student
class Grade < Student
#constructor method
def initialize(grade)
super
#grade = grade
end
# accessor methods
def getGrade
#grade
end
# setter methods
def setGrade=(value)
#grade = value
end
end
I understand how to build an abject:
student = Student.new(name, age)
How can I build this Student (that I have just created) a Grade object associated with the student and how would I call the inherited object, for example i wanted to:
puts 'student name and associated grade'
I know I can place the grade variable within the Student class, but for the purpose of learning im doing it this way.
This code would do what you wanted:
class Grade
attr_accessor :value
def initialize value
#value = value
end
end
class Student
attr_accessor :name, :age, :grade
def initialize name, age, grade
#name, #age, #grade = name, age, Grade.new(grade)
end
end
st = Student.new 'John', 18, 5
puts "student #{st.name} and associated grade #{st.grade.value}"
First off, no need to define accessors in Ruby like that, it's far from idiomatic. Let's clean that up first:
class Student
attr_accessor :name, :age
def initialize(name, age)
#name =name
#age = age
end
end
class Grade
attr_accessor :value
def initialize(grade)
#value = grade
end
end
Secondly it doesn't seem like Grade should inherit from Student at all, just adjust the latter to also store a Grade instance variable:
class Student
attr_accessor :name, :age, :grade
def initialize(name, age, grade = nil)
#name =name
#age = age
#grade = grade
end
end
You can then instantiate a student like this:
student = Student.new("Test", 18, Grade.new(1))
Or because of the default value you leave off the grade and assign it later:
student = Student.new("Test", 18)
# later
student.grade = Grade.new(1)