From: tamouse mailing lists Date: 2012-11-23T01:26:42+09:00 Subject: Re: Arrays with records as objects On Thu, Nov 22, 2012 at 8:37 AM, Steve Tucknott wrote: > Robert > > The TodoItem class is as attached. > > > I'm a complete novice, so I'm not sure how structures are used in Ruby - > I had tried a simple case of '..build record...put in array' in another > example where I built a local record and appended that to a local array, > and then I accessed the array fields by a simple array[n].field1. So I > stupidly assumed that the similar '@list << item_rec' would append the > structure of item_rec in the list array. > > Attachments: > http://www.ruby-forum.com/attachment/7888/TodoItem.rb Steve, I'm probably not understanding what you're trying to do here, but why do you use the OpenStruct class here? I think the question of how to access an anonymous object in an array is still an interesting one. I think you have to give @item_rec accessors (maybe just attr_reader? not sure). The attr_accessor's you have set for :done, :action, and :name define instance variables directly in TodoItem, but then you create a new object @item_rec and assign instance variables to it. This results is your class really having 4 instance variables, not 3, only 3 of which aren't being used: TodoItem instance vars: @done - not used by class @action - not used by class @name - not used by class @item_rec - this is used The object @item_rec points to has 3 instance variables: @done @action @name So, if you replace the attr_accessor line with: attr_accessor :item_rec Then, in your outer code, you can refer to it with the list as: @list[0].item_rec.name Still, unless this is an exercise in using OpenStruct, it's quite unnecessary. Instead, you can simply do this: class TodoItem attr_accessor :done, :action, :name alias_method :done?, :done def initialize(line) # Create a record of state, action and name with state (done) set to false # set state to undone @done = false @action, @name = line.split("<<>>") # Generally not a good idea to have object print out internal state like this # It can be useful for debugging, but better to define a # to_s method that will format it how you like it # STDOUT.puts "New TodoItem - #{@item_rec}" # if this really is debugging info, consider using a # logger instead of tossing it to STDOUT end # maybe this is personal, but I'd call this state? # also, look at the ternary operator. the following could be written # @done ? "Done" : "Active" def state_getter if @done "Done" else "Active" end end # You might consider a more descriptive set of methods # that say what is happening, such as "complete" and "undo" # rather than the single method to flip the value. # flipping rather depends on the current state, obviously, # but it thus requires proper knowlege of the current # state to determine what to do. methods like "complete" and # "undo" state more clearly their intentions. def state_setter STDOUT.puts "Setter Status Was ("+@item_rec.done+") for ("+@item_rec.name+')' @item_rec.done = !@item_rec.done STDOUT.puts "Setter Status Now ("+@item_rec.done+") for ("+@item_rec.name+')' end end