wyc
wyc

Reputation: 55263

How to use Class_name.method instead of Class_name.new.method?

I have the following code creates a Parser class which has many parse_something methods. Then finally they are merged in the parse method:

class Parser
  def parse(html)
    @data = Nokogiri.HTML(open(html))
    merged_hashes = {}

    array_of_hashes = [
      parse_department,
      parse_super_saver,
      parse_new_arrivals,
      parse_out_of_stock,
      parse_categories,
      parse_results
    ]
    array_of_hashes.inject(merged_hashes,:update)

    return merged_hashes
  end

  def parse_department  
    department = @data.css('#ref_2619534011')

    @department_hash = {}
    department.css('li').drop(1).each do | department |
      department_title = department.css('.refinementLink').text
      department_count = department.css('.narrowValue').text[/[\d,]+/].delete(",").to_i
      @department_hash[:department] ||= {}
      @department_hash[:department]["Pet Supplies"] ||= {}
      @department_hash[:department]["Pet Supplies"][department_title] = department_count
    end 

    return @department_hash
  end 

  def parse_super_saver  

(etc...)

So right now, I'm using it like this:

def html_pet_supplies
  File.open("amazon_pet_supplies.html")
end

Parser.new.parse html_pet_supplies

But I would like to use it like this instead: Parser.parse html_pet_supplies

I tried removing new but I got this error:

NoMethodError: undefined method `parse' for Parser:Class

What's the simplest way of changing the code so that I just do Parser.parse?

Upvotes: 0

Views: 109

Answers (2)

Stefan
Stefan

Reputation: 114138

Instead of rewriting all your methods to class methods, you could create a Parser instance and call Parser#parse from Parser.parse:

class Parser
  def self.parse(html)
    self.class.new.parse(html)
  end

  def parse(html)
    @data = Nokogiri.HTML(open(html))
    # ...
  end
  #...
end

Now Parser.parse(html) is equivalent to Parser.new.parse(html).

Upvotes: 1

ch4nd4n
ch4nd4n

Reputation: 4197

Use static method declaration

class Parser
  def self.parse(html)
    #Parsing logic
  end
end

You could then invoke it by Parser.parse filename

Update You have instance variable declared in your parsing logic @data so you cannot get it working with current logic. You would have to create instance to be able to call parse_department.

** Further Update **

Short answer Your current logic is just fine.

Long answer It's more about OOP. In Parser#parse method you have @data instance variable declaration. @data can exist only for an object not for class, which in turn means that you can have it only in an instance method and not in static method. When you call Parser.new it create an object and that is when @data can exist. While static methods can be invoked on a class directly without creating an object. Read more Understanding Ruby class vs instance methods

Upvotes: 1

Related Questions