0

Can you tell me why this isn't working?

The code below outputs student1 & student2 properly, but I cannot get the class method to work on student3.

All I am trying to do is assign a class method .create_with_species , with the species attribute = to "Human".

However, when I run the program, I get an error that "local variable or method sex is undefined". I'm a newbie and I can't figure out what I've done wrong!

It was my understanding that since I had identified "sex" in the Initialize method I should be able to use it within a class method such as create_with_species. I tried explicitly defining sex in the class method, as student.sex = sex, but still got the same error.

class Students

  attr_accessor :sex, :age, :species

  def self.create_with_species(species)
    student = Students.new(sex,age)
    student.species = species
    return student
  end

  def initialize(sex, age)
    @sex = sex
    @age = age
    puts "----A new student has been added----"
  end

end

student1 = Students.new("Male", "21")
puts student1.sex
puts student1.age
puts

student2 = Students.new("Female", "19")
puts student2.sex
puts student2.age

student3 = Students.create_with_species("human")
kikuchiyo
  • 3,391
  • 3
  • 23
  • 29
Jeff H.
  • 923
  • 1
  • 7
  • 9

3 Answers3

1

As far as the syntax goes, you have to use @sex and @age instead of sex and age. Otherwise they won't be interpreted as instance attributes.

But you do realize that the logic of the code is broken? I understand you want to use the static factory method pattern but this is not how you should do it since @sexand @age are nil when you call that method and those variables are instance attributes not class attributes.

Amokrane Chentir
  • 29,907
  • 37
  • 114
  • 158
1

sex and age are not defined. Do you mean to use a class variable? Using @age or @sex will result in nils, as no class attributes are set and the instance is not yet created, hence no instance variables set either. You don't need to state Students.new in create_with_species. new will suffice because you are scoped in Students. I think you would be better off passing a hash object to initialize, and just set the species variable there. It will be nil if not assigned explicitly, or you can have a default value.

Try this:

class Students

  attr_accessor :sex, :age, :species

  def initialize(options)
    @sex = options[:sex]
    @age = options[:age]
    @species = options[:species]
    puts "----A new student has been added----"
  end

end

student1 = Students.new(:sex => "Male", :age => "21")
puts student1.sex
puts student1.age
puts student1.species
puts

student2 = Students.new(:sex => "Female", :age => "19")
puts student2.sex
puts student2.age

student3 = Students.new(
    :sex => "Hermi", :age => "2", :species => "alien"
)
kikuchiyo
  • 3,391
  • 3
  • 23
  • 29
1

@sex and @age are instance attributes. You can't use them (what would they mean?) inside a class method. You've written just sex and age inside create_with_species, but again: what are these supposed to refer to? (In an instance method they'd be calls to the accessors, but at this point there's no instance to call the accessors on.)

Consider: when you say

student3 = Students.create_with_species("human")

what sex and age should this new student object get? You haven't specified any.

Gareth McCaughan
  • 19,888
  • 1
  • 41
  • 62
  • Thank You, I got it to work. However, now I have a problem. Look at the answer I accepted to the question below. That guy made a class method which (based on your explanation), shouldn't work...http://stackoverflow.com/questions/10366572/class-methods-ruby – Jeff H. Apr 28 '12 at 22:05
  • I don't understand why you think it shouldn't work. That class method gets the things it needs as arguments, and then sets them on a particular instance. – Gareth McCaughan Apr 28 '12 at 22:08