Home > Software design >  How to use Method param as variable in ruby
How to use Method param as variable in ruby

Time:05-24

Hello i have a problem in ruby mine it says that my param isn't initialized can you help me? I need to sum all the subjects

class Student
  attr_accessor :name, :english, :math, :science, :french, :pe

  def initialize(name, english, math, science, french, pe)
    @name = name
    @english = english
    @math = math
    @science = science
    @french = french
    @pe = pe
  end

  def avg_sum_grades(param)
    sum_of_subjcet_grades = students.map { |student| student.param }
  end

students = [
  student.new('brian', 3, 4, 5, 5, 6),
  student.new('eric', 1, 3, 4, 5, 2),
  student.new('jessica', 2, 1, 4, 5, 3),
  student.new('agatha', 4, 4, 5, 3, 5),
  student.new('alex', 2, 4, 5, 2, 5)
]

avg_sum_grades("english")

CodePudding user response:

You're trying to access a method based on a name passed into a method.

class Student
  attr_accessor :name, :english, :math, :science, :french, :pe

  def initialize(name, english, math, science, french, pe)
    @name = name
    @english = english
    @math = math
    @science = science
    @french = french
    @pe = pe
  end
end

This is definitely possible by using a symbol with the #send method.

bob = Student.new("Bob", 1, 2, 3, 4, 5)
bob.send(:pe)
# => 5

You're trying to do this on a group of Student objects.

students = [
  student.new('brian', 3, 4, 5, 5, 6),
  student.new('eric', 1, 3, 4, 5, 2),
  student.new('jessica', 2, 1, 4, 5, 3),
  student.new('agatha', 4, 4, 5, 3, 5),
  student.new('alex', 2, 4, 5, 2, 5)
]

So you could write:

def get_avg_grade(students, subject)
  grades = students.map { |s| s.send(subject) }
  grades.sum / grades.length
end

Which can be called: get_avg_grade(students, :math).

One more thing...

Given that you are just creating accessors for everything, you can really just write:

Student = Struct.new(:name, :english, :math, :science, :french, :pe)

CodePudding user response:

You will need the instance_variable_get to get the instance variable as string.

class Student
    attr_accessor :name, :english, :math, :science, :french, :pe

    def initialize(name, english, math, science, french, pe)
      @name = name
      @english = english
      @math = math
      @science = science
      @french = french
      @pe = pe
    end 
 end

@students = [
  Student.new('brian', 3, 4, 5, 5, 6),
  Student.new('eric', 1, 3, 4, 5, 2),
  Student.new('jessica', 2, 1, 4, 5, 3),
  Student.new('agatha', 4, 4, 5, 3, 5),
  Student.new('alex', 2, 4, 5, 2, 5)
]

  def avg_sum_grades(param)
       sum_of_subjcet_grades = @students.sum{ |student| student.instance_variable_get("@#{param}") }
  end

avg_sum_grades("english")

CodePudding user response:

class Student
  attr_accessor :name, :english, :math, :science, :french, :pe

  def initialize(name, english, math, science, french, pe)
    @name = name
    @english = english
    @math = math
    @science = science
    @french = french
    @pe = pe
  end

  # NOTE: make it a class method so we can call it on `Student` class;
  #       we have to have two arguments:
  #       an array of students and subject
  def self.avg_sum_grades(students, subject)
    students.map{|student| student.send(subject) }.sum / students.length
    # or the short version
    # students.sum(&subject.to_sym) / students.length
  end

  # NOTE: if you want to get some decimal points in the result
  def self.avg_sum_grades_float(students, subject)
    students.sum(&subject.to_sym) / students.length.to_f
  end
end
students = [
  Student.new('brian', 3, 4, 5, 5, 6),
  Student.new('eric', 1, 3, 4, 5, 2),
  Student.new('jessica', 2, 1, 4, 5, 3),
  Student.new('agatha', 4, 4, 5, 3, 5),
  Student.new('alex', 2, 4, 5, 2, 5)
]

Student.avg_sum_grades(students, "english")       # => 2
Student.avg_sum_grades_float(students, "english") # => 2.4

https://ruby-doc.org/core-3.1.2/Object.html#method-i-send

  •  Tags:  
  • ruby
  • Related