Carlos Troncoso
Carlos Troncoso

Reputation: 683

Defining a Struct during initialize

I have a class that reads a dynamic CSV file, and would like to create a struct based on the headers of the CSV.

It goes like this in pseudo-code:

class SomeClass
  def initialize(csvfile)
    @csv = CSV.open(csvfile, options.....)
    .....
    headers = @csv.headers  # => [:line, :error, :user, ........]   <==this is dynamic
    RECORD = Struct.new(headers)
    load_data
  end

  def load_data
    @records = []
    @csv.each do |r|
      @records << RECORD.new(r.fields)
    end
  end
end

The issue is that a constant can not (should not) be dynamically defined. So, what should be the proper way to address this?

Upvotes: 1

Views: 328

Answers (2)

Arup Rakshit
Arup Rakshit

Reputation: 118271

@sawa's answer is correct. I will add something more here.

Constants are used to store values which DO NOT change. If you change a constant in your program it is probably a bug. Ruby is trying to be helpful and say "Hold on! I think something strange is going on here. You said you wanted this to be a constant but now it's being changed!"

In Ruby, you are never allowed to put a constant assignment, inside a method definitions due to the reason as I just said above. If you try to do constant assignment inside a method, you will get Syntax Error. As per your need, you can use any variables, but not constant variables, inside a method.

If you do

Y = 1
#then
Y = 2
# warning: already initialized constant Y
# warning: previous definition of Y was here

But if you try,

def meth arg
  C = arg
end
# then 
# SyntaxError: dynamic constant assignment
# C = arg
#   ^

Upvotes: 0

sawa
sawa

Reputation: 168101

You don't have to use a constant. Use an instance variable.

class SomeClass
  def initialize(csvfile)
    @csv = CSV.open(csvfile, options...)
    ...
    headers = @csv.headers
    @record = Struct.new(headers)
    load_data
  end
  def load_data
    @records = []
    @csv.each do |r|
      @records << @record.new(r.fields)
    end
  end
end

Upvotes: 3

Related Questions