SitePoint Sponsor |
|
User Tag List
Results 1 to 7 of 7
-
Nov 14, 2005, 21:20 #1
- Join Date
- Jan 2003
- Posts
- 15
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Dynamically Naming a Class Variable with a Param
I swear this is like throwing a football or baseball left handed! I'm stumped on something that I think should be easy - but since I'm still new to Ruby, I'm not sure how to pull it off.
Basically, I want to be able to create a class var based on the value I pass in the constructor. Something like this:
# BEGIN CODE
class Foodef initialize(var)@#{var} = []endend
b = new.Foo("baz")
p b
# END CODE
I was hoping that I would get a new 'Foo' that has a class array called 'baz' - instead I get a syntax error. I just need a short way of constructing empty arrays when I instantiate an object. Otherwise, I guess I could statically name all of the arrays I want, but that doesn't seem really elegant.
And apologies about the code block - I couldn't get the Ruby to format correctly.
-
Nov 15, 2005, 00:54 #2
- Join Date
- Jun 2004
- Location
- Stockholm, Sweden
- Posts
- 148
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
What are you even trying to do?
Correct Ruby syntax for instantiating an object is: bar = Foo.new.
Why do you want to name the variable yourself from the outside of the object, an object's internal data is just that: An object's internal data.
Could you please elaborate on what you are trying to achieve, and maybe we could tell you how you're supposed to be doing it.If there is a way to overcome the suffering, there is no need to worry; if there is no way to overcome the suffering, there is no point to worry.
- Shantideva
-
Nov 15, 2005, 07:39 #3
- Join Date
- Jan 2003
- Posts
- 15
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Sorry about the syntax gaffe.
I'm trying to create a class called 'Address.' And this class should have two public attributes - 'location' and 'type.' It will have one public method called 'getAddress.' Based on the 'provider' and 'type' attributes, 'getAddress' will return a 'street' and a 'zip code.' The mechanics of the 'getAddress' method are to:
1. Load a CSV file that has the following elements ('location', 'street', 'zip')
2. Parse the file and load 'street' and 'zip' into a 'array' that should be named 'location.'
So let's say the CSV file has the following data:
Code:Home,123 Foo,90210 Home,345 Wombat,00921 Work,456 Baz,11210 Work,991 Bazbat,92128
Code:class Address def initialize(location, type="default") @location = location @type = type # i want to initialize an empty array here that's named # whatever the value that is given for the 'location' parameter # lets just call it @array but ideally these would be class # vars that could be called '@home' or '@work' based on # 'location' parameter when the object is instantiated end def getAddress() CSV.open('csv_filename_here.csv', 'r') do | row | # push the contents of the row into the initialized array end case @type when "random" # return a random element from the array when "default" # return the first element from the array end end end
Maybe not.
-
Nov 15, 2005, 09:21 #4
It sounds to me like you've got candidates for two child classes, HomeAddress and WorkAddress. Perhaps some sort of factory class, AddressFactory that parses a CSV file and returns an array of Address objects. Your Address classes shouldn't know anything about a CSV file (what if you wanted to use a different source?).
Of course, you only need the sub-classes if there is a need for different behaviour depending on whether its a home or work address, otherwise, a single Address class will do. It still shouldn't know anything about where the data comes from though.
What I am confused about is why the array needs to be named according to the location. What difference does it make?
So, as an example:
Code:class Address attr_reader :city, :zip, :type def initialize(type, city, zip) @city = city @zip = zip @type = type end end class AddressCsvReader attr_reader :addresses def initialize(path) @addresses = Array.new CSV.open(path, 'r') do |row| address = Address.new( row[0], row[1], row[2] ) @addresses << address end end end reader = AddressCsvReader.new("my_csv_file.csv") reader.addresses.each do |addr| puts "This is a #{addr.type} address in the city #{addr.city}" end
-
Nov 15, 2005, 19:40 #5
- Join Date
- Nov 2001
- Location
- Bath, UK
- Posts
- 2,498
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by bivouac
Code:class Fred def initialize(p1, p2) @a, @b = p1, p2 end end fred = Fred.new('cat', 99) fred.instance_variable_set(:@a, 'dog') #=> "dog" fred.instance_variable_set(:@c, 'cat') #=> "cat" fred.inspect #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"
Code:class Foo def initialize(var) instance_variable_set(var, []) end end
What you are doing is setting the [b]name[b] of a variable dynamically. That's quite unusual. Normally you change the values of variables, not what the variables are themselves. If you want to set a key (a name) and a value at the same time, a hash is much more common. For example:
Code:def add_a_key_and_a_value(key, value) @params[key] = value end
As an aside, getAddress is a bit foreign in Ruby. CamelCase is only really used in class and module names, where the case of the first letter is important. So if you wanted to use two words, it would be get_address.
Using "get" at the start of a method name is a little unusual too. Ruby supports this syntax for getters and setters, so an explicit "get" or "set" isn't needed:
Code:class Fred def foo=(val) @foo = val end def foo @foo end end
DouglasHello World
-
Nov 15, 2005, 20:04 #6
- Join Date
- Jan 2003
- Posts
- 15
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
You know the more I think about it - the more I think you guys are right. And I apologize for the real lack of clarity with my request, this is a work problem and of course I'm translating the problem space from work to example poorly.
I think I'm going about this the totally wrong way - never have I ever wanted to dynamically set the name of a var inside of function, let along a class method. The factory class that Luke mentions is definitely worth investigating and Douglas' mention of the hash also has some merit (too bad data structures scare me).
In any case, everything that you guys have posted has been immeasurably helpful. I really appreciate you guys putting the time and effort forward to helping me out. Going to try and re-attack this problem tonight with some of the tips given here and some of the tips I got @ work and see if I can't come up with something. I'll repost if anyone's interesting.
Thanks again.
-
Nov 16, 2005, 07:23 #7
- Join Date
- Apr 2004
- Location
- germany
- Posts
- 4,324
- Mentioned
- 0 Post(s)
- Tagged
- 0 Thread(s)
Originally Posted by DougBTX
Code:class A def initialize(params) @params = params end def [](key) @params[key] end def []=(key, value) @params[key] = value end end a = A.new('name' => 'Fred', 'age' => 20) puts a['name'] a['age'] += 10 puts a['age']
Code:require "delegate" class B < SimpleDelegator def initialize(params) super(params) end end b = B.new('name' => 'Sally', 'age' => 17) puts b['name'] puts b['age']
Bookmarks