MagicArray

MagicArray is class that performs lazy loading of data. The only thing that you have to do is to define data source methods inside the MagicArray descendant. And then you can simply load data by accessing array elements.

Installation

Add this line to your application's Gemfile:

gem 'magic_array'

And then execute:

$ bundle

Or install it yourself as:

$ gem install magic_array

Usage

Say you want to load some posts from vk.com. You can simply create the MagicArray descendant in order to load them.
You should always remember that you have to define element_source(index) and elements_source(range_start, count) using MagicArray.

MagicArray descendant example:

class PostArray < MagicArray

  load_limit 100

  def initialize group_id
    @group_id = "-#{group_id}"
    self.count = vk.wall.get(owner_id: @group_id, offset: 0, count: 1).first
    super
  end

  def element_source index
    vk.wall.get(owner_id: @group_id, offset: index, count: 1).last
  end

  def elements_source range_start, range_count
    result = vk.wall.get(owner_id: @group_id, offset: range_start, count: range_count)
    result.shift
    result
  end

  def vk
    vk_source = -> {VK::Client.new}
    @vk ||= vk_source.call
  end

  def search from, till
    from_index = (bsearch{ |post| post.date <= from }) - 1
    till_index = bsearch{ |post| post.date <= till }
    self[till_index..from_index]
  end

  private

      def bsearch &block
        first = 0
        last = count-1
        mid = first + (last - first) / 2
        while first<last
          if yield(self[mid])
            last = mid
          else
            first = mid + 1
          end
          mid = first + (last - first) / 2
        end
        if yield(self[last])
          last
        else
          nil
        end
      end

end

Initializing object

post_array = PostArray.new 1234567 
=> #<PostArray:0x000000028d3568 @group_id="-17076618", @vk=#<VkontakteApi::Client:0x000000028d2d48 ...

this code prints:

POST https://api.vk.com/method/wall.get
body: "owner_id=-17076618&offset=0&count=1"

it means that PostArray loaded first element in order to find out total count of elements. So:

post_array.count
 => 901

Loading elements with index number

The code

post_array[0] => #<Hashie::Mash comments=#<Hashie::Mash count=0> date=1385007153 from_id=79826777 id...

prints

POST https://api.vk.com/method/wall.get
body: "owner_id=-17076618&offset=0&count=1"

and returns one post object.

Loading elements with range

The code

post_array[10..20]  => [#<Hashie::Mash comments=#<Hashie::Mash count=7> date=1384009402 from_id=6355...

prints

POST https://api.vk.com/method/wall.get
body: "owner_id=-17076618&offset=10&count=11"

and returns an array that contains 11 post objects.

Accessing elements

Once you loaded element or elements they are saved within PostArray. So you can simply access them without loading. Another words the are cached within your MagicArray descendant instance. If you want to see original Array of loaded elements:

post_array.elements => [#<Hashie::Mash comments=#<Hashie::Mash count=0> date=1385007153 from_id=7982...

And now you have got the Array. Lets check it:

post_array[0] => #<Hashie::Mash comments=#<Hashie::Mash count=0> date=1385007153 from_id=79826777 id...
post_array[1] => nil

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request