Ctrl_Alt_Defeat
Ctrl_Alt_Defeat

Reputation: 4009

Creating new class to put into an Array in Ruby

I am coming from a C# background and trying to learn Ruby and Ruby on Rails. I have the following Car class - note the build_xml method I need in order to build XML in that syntax and then pass to a WebService

class Car

  @@array = Array.new
  #this will allow us to get list of all instances of cars created if needed
  def self.all_instances
    @@array
  end

  def initialize(id, model_number, engine_size, no_doors)
    # Instance variables
    @id = id
    @model_number = model_number
    @engine_size = engine_size
    @no_doors = no_doors
    @@array << self
  end

  def build_car_xml
    car = { 'abc:Id'=> @id, 'abc:ModelNo' => @model_number, 'abc:ES' => @engine_size, 'abc:ND' => @no_doors}
   cars = {'abc:Car' => [car] }   
  end

end

In another class then I was using this as below:

car1 = Car.new('1', 18, 3.0, 4)
request = car1.build_car_xml

This works as expected and the request is formatted how I need and the webservice returns the results. I now want to expand this however so I can pass in an array of cars and produce the request XML - however I am struggling to get this part working.

So far I have been trying the following (for now I am ok with just the Id changing as it is the only parameter required to be unique):

  car_array = []
  (1..10).each do |i|
    car_array << Car.new(i.to_s, 18, 3.0, 4)
  end

Am I correct in saying that I would need to define a new build_car_xml method on my Car class that can take an array of cars and then build the xml so my request call would be something like:

request = Car.build_car_xml(car_array)

What i am unsure of is 1) - is this the correct way of doing things in Ruby and 2) how to construct the method so that it is Building the XML in the correct format in the way it was when I call it on the single object - i.e - I need the namespaces added before the actual value.

def build_car_xml(car_array)
 #here is where I am unsure how to contruct this method   
end

Upvotes: 1

Views: 856

Answers (1)

Victor Moroz
Victor Moroz

Reputation: 9225

Possible solution ('abc:Car' is a wrong name, should be Cars if you want it to hold an array):

class Car

...

  def self.build_cars_xml(cars)
    { 'abc:Car' => cars.map(&:build_car_xml) }   
  end

  def build_car_xml
    { 'abc:Id'=> @id, 'abc:ModelNo' => @model_number, 'abc:ES' => @engine_size, 'abc:ND' => @no_doors }
  end
end

cars =
  (1..10).map do |i|
    Car.new(i.to_s, 18, 3.0, 4)
  end
Car.build_cars_xml(cars)

It doesn't meet your requirements as instance build_car_xml doesn't generate Car namespace, but for me it's some inconsistency. Your XML is actually a collection, even if it has just one element, instance method should not be responsible for collection. Car.build_cars_xml([Car.new(...)] looks more logical to me.

Upvotes: 1

Related Questions