views:

38

answers:

2

I have a class, Autodrop, that contains several methods , a.o. 'metadata', that call an external API (dropbox). They are slow. However, I already often have that metadata around when initializing the AutodropImage, so I should make the methods smarter.

What I have in mind is this:

class Autodrop
  include Dropbox
  attr_reader :path

  def initialize(path)
    @path = path
  end

  def self.from_entry(drop_entry)
    @drop_entry = drop_entry
    self.initialize(@drop_entry.path)
  end

  def metadata
    if @drop_entry = nil
      return heavy_lifting_and_network_traffic
    else
      return @drop_entry.metadata
    end
  end
  #...
end

Now, I would expect to call

entry = BarEntry.new()
foo = Autodrop.from_entry(entry)
foo.metadata

In order to avoid that heavy lifting and network traffic call.

But this does not work. And somehow, in all my newbieness, I am sure I am goind at this all wrong. Is there a term I should look for and read about first? How would you go for this?

Note, that the examples are simplified: in my code, I inherit AutodropImage < Autodrop for example, which is called from withing AutodropGallery < Autodrop. The latter already knows all metadata for the AutodropImage, so I mostly want to avoid AutodropImage going over the heavy lifting again.

A: 

You would need to cache the metadata in a class variable.

Edit: Or in a class level instance variable. Maybe this read will help: http://railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/

k_b
that is what I though. However, I did not mention that this is used in Sinatra. And I was told class @@variables are shared across all users/threads. But I may be misinformed there.
berkes
but you are not using class variables you are using instance variables
nas
+1  A: 

You are creating an instance variable @drop_entry in your class method from_entry and obviously it wont be available to your object that you are creating in this method. One workaround is to pass it as a parameter when you are initializing the class. It should work if you do the following modifications:

  1. In your from_entry class method change

    self.initialize(@drop_entry) 
    

    to

    new(@drop_entry)
    
  2. Modify initialize method to:

    def initialize(drop_entry)
      @drop_entry = drop_entry
      @path = @drop_entry.path
    end
    

Or if your class is tied up to pass only the path parameter, ie. you dont want to change the other existing code then you can use an optional parameter drop entry like so

    def initialize(path, drop_entry=nil)
nas