On Wed, Apr 27, 2011 at 8:08 AM, Reginald Tan <redge.tan / gmail.com> wrote:
> Christopher Dicely wrote in post #995252:
>> On Tue, Apr 26, 2011 at 6:34 PM, Reginald Tan <redge.tan / gmail.com>
>> wrote:
>>> I want pstore to be able to do same thing. I've included Enumerable but
>>> I do have to implement the each method which I dont know how to go
>>> about. Any suggestions? Thanks

Regarding your original code

h =3D {0 =3D> "sword", 5 =3D> "hammer", 3 =3D> "arrow"}
puts h.map{ |x| x[0]}.max   # gives the highest key which is 5

With a Hash I'd rather

irb(main):002:0> h.keys.max
=3D> 5
irb(main):003:0> h.max_by {|k,v| k}.first
=3D> 5

>> It looks like, during a transaction, the content of a PStore is
>> represent by a Hash in the instance variable @table, so you if you
>> want the PStore to act like a Hash, something like this should work:
>>
>> class PStore
>> =A0 def each &blk
>> =A0 =A0 in_transaction
>> =A0 =A0 @table.each &blk
>> =A0 end
>> end
>>
>> (If you call this without a block, it looks like you get an enumerator
>> over the state of the store as of the transaction it was captured in,
>> which can be used outside of that transaction, and that could be
>> useful for some things.)
>>
>> Obviously, this is exploiting details of the implementation rather
>> than the public interface, so it's at more risk of getting broken in a
>> new version of the library than would be an approach that relies only
>> on the public interface.
>
> Thanks. I didnt realized before that opening up a class would give you
> access to instance variables as well. I tried to access the table
> variable before using self.table but there was no getter method defined
> for it so I had a bit of trouble.
>
> Good catch on - being able to get enum and use it outside transaction.
>
> Btw, I find having to do everything in transaction quite annoying and
> tedious. Do you see any better way of implementing it instead of always
> passing a block to transaction()?

If you do not want to use transactions you can as well just write a
Hash with Marshal and not use PStore at all.  Transaction safety and
persistent consistency is the main feature to use PStore.

A proper implementation of Hash like access that would not depend on
the internals could roughly work like this:

# untested!
class PStoreHash
  attr_accessor :read_only

  def initialize(ps, read_only =3D false)
    @ps =3D ps
    @read_only =3D read_only
  end

  def method_missing(*a,&b)
    @ps.transaction read_only do |ps|
      PSWrap.new(ps).send(*a,&b)
    end
  end

  class PSWrap < SimpleDelegator
    include Enumerable

    def keys; roots; end
    def values; roots.map {|r| self[r]}; end

    def each
      if block_given?
        roots.each {|r| yield r, self[r]}
        self
      else
        to_a
      end
    end
  end
end

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/