riakrest 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/Manifest.txt +41 -0
- data/PostInstall.txt +2 -0
- data/README.rdoc +51 -0
- data/Rakefile +24 -0
- data/examples/auto_update_data.rb +50 -0
- data/examples/auto_update_links.rb +48 -0
- data/examples/basic_client.rb +33 -0
- data/examples/basic_resource.rb +34 -0
- data/examples/json_data_resource.rb +32 -0
- data/examples/linked_resource.rb +113 -0
- data/examples/multiple_resources.rb +43 -0
- data/lib/riakrest/core/exceptions.rb +73 -0
- data/lib/riakrest/core/jiak_bucket.rb +146 -0
- data/lib/riakrest/core/jiak_client.rb +316 -0
- data/lib/riakrest/core/jiak_data.rb +265 -0
- data/lib/riakrest/core/jiak_link.rb +131 -0
- data/lib/riakrest/core/jiak_object.rb +233 -0
- data/lib/riakrest/core/jiak_schema.rb +242 -0
- data/lib/riakrest/core/query_link.rb +156 -0
- data/lib/riakrest/data/jiak_data_hash.rb +182 -0
- data/lib/riakrest/resource/jiak_resource.rb +628 -0
- data/lib/riakrest/version.rb +7 -0
- data/lib/riakrest.rb +164 -0
- data/riakrest.gemspec +38 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/core/exceptions_spec.rb +18 -0
- data/spec/core/jiak_bucket_spec.rb +103 -0
- data/spec/core/jiak_client_spec.rb +358 -0
- data/spec/core/jiak_link_spec.rb +77 -0
- data/spec/core/jiak_object_spec.rb +210 -0
- data/spec/core/jiak_schema_spec.rb +184 -0
- data/spec/core/query_link_spec.rb +128 -0
- data/spec/data/jiak_data_hash_spec.rb +14 -0
- data/spec/resource/jiak_resource_spec.rb +128 -0
- data/spec/riakrest_spec.rb +17 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +12 -0
- data/tasks/rspec.rake +21 -0
- metadata +113 -0
| @@ -0,0 +1,358 @@ | |
| 1 | 
            +
            require File.dirname(__FILE__) + '/../spec_helper.rb'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class FooBarBaz  # :nodoc:
         | 
| 4 | 
            +
              include JiakData
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              allowed  :foo, :bar, :baz
         | 
| 7 | 
            +
              required :foo
         | 
| 8 | 
            +
              readable :foo, :bar
         | 
| 9 | 
            +
              writable :foo, :bar
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              def initialize(hsh)
         | 
| 12 | 
            +
                hsh.each {|key,val| send("#{key}=",val)}
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def self.jiak_create(jiak)
         | 
| 16 | 
            +
                new(jiak)
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              def for_jiak
         | 
| 20 | 
            +
                { :foo => @foo,
         | 
| 21 | 
            +
                  :bar => @bar
         | 
| 22 | 
            +
                }.reject {|k,v| v.nil?}
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              def eql?(other)
         | 
| 26 | 
            +
                other.is_a?(FooBarBaz) && other.foo.eql?(@foo) && other.bar.eql?(@bar)
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            describe "JiakClient" do
         | 
| 31 | 
            +
              before do
         | 
| 32 | 
            +
                @base_uri = 'http://127.0.0.1:8002/jiak/'
         | 
| 33 | 
            +
                @client = JiakClient.new @base_uri
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              it "should respond to" do
         | 
| 37 | 
            +
                @client.should respond_to(:set_schema, :schema, :keys)
         | 
| 38 | 
            +
                @client.should respond_to(:uri)
         | 
| 39 | 
            +
                @client.should respond_to(:==,:eql?)
         | 
| 40 | 
            +
                @client.should respond_to(:get, :store, :delete, :walk)
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              it "should default to base URI" do
         | 
| 44 | 
            +
                @client.uri.should match @base_uri
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              it "should allow specified base URI" do
         | 
| 48 | 
            +
                base_uri = 'http://localhost:1234/tmp/'
         | 
| 49 | 
            +
                client = JiakClient.new base_uri
         | 
| 50 | 
            +
                client.uri.should match base_uri
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              it "should equal another JiakClient with the same URI" do
         | 
| 54 | 
            +
                client = JiakClient.new @base_uri
         | 
| 55 | 
            +
                client.should eql @client
         | 
| 56 | 
            +
                client.should ==  @client
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            describe "JiakClient URI handling" do
         | 
| 62 | 
            +
              before do
         | 
| 63 | 
            +
                @base_uri = 'http://127.0.0.1:8002/jiak/'
         | 
| 64 | 
            +
                @client = JiakClient.new @base_uri
         | 
| 65 | 
            +
                @bucket = JiakBucket.new('uri_bucket',FooBarBaz)
         | 
| 66 | 
            +
                @key = 'uri_key'
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            describe "JiakClient processing" do
         | 
| 71 | 
            +
              before do
         | 
| 72 | 
            +
                @base_uri = 'http://127.0.0.1:8002/jiak/'
         | 
| 73 | 
            +
                @client = JiakClient.new @base_uri
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              describe "for buckets" do
         | 
| 77 | 
            +
                before do
         | 
| 78 | 
            +
                  @bucket_name = 'bucket_1'
         | 
| 79 | 
            +
                  @bucket = JiakBucket.new(@bucket_name,FooBarBaz)
         | 
| 80 | 
            +
                  @client.set_schema(@bucket)
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                it "should create and fetch a bucket schema" do
         | 
| 84 | 
            +
                  schema = @client.schema(@bucket)
         | 
| 85 | 
            +
                  
         | 
| 86 | 
            +
                  ['allowed_fields',
         | 
| 87 | 
            +
                   'required_fields',
         | 
| 88 | 
            +
                   'read_mask',
         | 
| 89 | 
            +
                   'write_mask'].each do |fields|
         | 
| 90 | 
            +
                    schema_fields = schema.send("#{fields}")
         | 
| 91 | 
            +
                    fbb_fields = FooBarBaz.schema.send("#{fields}")
         | 
| 92 | 
            +
                    schema_fields.same_fields?(fbb_fields).should be true
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                it "should update an existing bucket schema" do
         | 
| 97 | 
            +
                  FooBarBazBuz = JiakDataHash.create(:foo,:bar,:baz,:buz)
         | 
| 98 | 
            +
                  @client.set_schema(JiakBucket.new(@bucket_name,FooBarBazBuz))
         | 
| 99 | 
            +
                  
         | 
| 100 | 
            +
                  resp_schema = @client.schema(@bucket)
         | 
| 101 | 
            +
                  resp_schema.allowed_fields.should include 'buz'
         | 
| 102 | 
            +
                  resp_schema.required_fields.should be_empty
         | 
| 103 | 
            +
                  resp_schema.read_mask.should include 'baz'
         | 
| 104 | 
            +
                  resp_schema.write_mask.should include 'baz'
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                it "should get a list of keys for a bucket" do
         | 
| 109 | 
            +
                  arr = [{:key=>'key1',:dobj=>FooBarBaz.new(:foo=>'v1')},
         | 
| 110 | 
            +
                         {:key=>'key2',:dobj=>FooBarBaz.new(:foo=>'v21',:bar=>'v22')},
         | 
| 111 | 
            +
                         {:key=>'',:dobj=>FooBarBaz.new(:foo=>'v3')}]
         | 
| 112 | 
            +
                  keys = arr.map do |hsh|
         | 
| 113 | 
            +
                    jo = JiakObject.new(:bucket => @bucket,
         | 
| 114 | 
            +
                                        :key => hsh[:key],
         | 
| 115 | 
            +
                                        :data => hsh[:dobj])
         | 
| 116 | 
            +
                    @client.store(jo)
         | 
| 117 | 
            +
                  end
         | 
| 118 | 
            +
                  srv_keys = @client.keys(@bucket)
         | 
| 119 | 
            +
                  keys.each {|key| srv_keys.should include key}
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                it "should encode odd bucket strings" do
         | 
| 123 | 
            +
                  bucket_name = "# <& %"
         | 
| 124 | 
            +
                  bucket = JiakBucket.new(bucket_name,FooBarBaz)
         | 
| 125 | 
            +
                  @client.set_schema(bucket)
         | 
| 126 | 
            +
                  schema = @client.schema(@bucket)
         | 
| 127 | 
            +
                  FooBarBaz.schema.read_mask.same_fields?(schema.read_mask).should be true
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
              end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
              describe "for CRUD" do
         | 
| 132 | 
            +
                before do
         | 
| 133 | 
            +
                  @bucket = JiakBucket.new('bucket_2',FooBarBaz)
         | 
| 134 | 
            +
                  @client.set_schema(@bucket)
         | 
| 135 | 
            +
                  @data = FooBarBaz.new(:foo => 'foo val')
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                describe "storage" do
         | 
| 139 | 
            +
                  it "should store a JiakObject by the specified key" do
         | 
| 140 | 
            +
                    key = 'store_key_1'
         | 
| 141 | 
            +
                    jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
         | 
| 142 | 
            +
                    resp = @client.store(jobj)
         | 
| 143 | 
            +
                    resp.should eql key
         | 
| 144 | 
            +
                  end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                  it "should store a JiakObject w/o a key" do
         | 
| 147 | 
            +
                    jobj = JiakObject.new(:bucket => @bucket, :data => @data)
         | 
| 148 | 
            +
                    resp = @client.store(jobj)
         | 
| 149 | 
            +
                    resp.should_not be_empty
         | 
| 150 | 
            +
                  end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                  it "should return a JiakObject at time of storage" do
         | 
| 153 | 
            +
                    key = 'store_key_2'
         | 
| 154 | 
            +
                    jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
         | 
| 155 | 
            +
                    resp = @client.store(jobj,{:object => true})
         | 
| 156 | 
            +
                    resp.should be_a JiakObject
         | 
| 157 | 
            +
                    resp.bucket.should eql @bucket
         | 
| 158 | 
            +
                    resp.key.should eql key
         | 
| 159 | 
            +
                    resp.data.should be_a FooBarBaz
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                    jobj = JiakObject.new(:bucket => @bucket, :data => @data)
         | 
| 162 | 
            +
                    resp = @client.store(jobj,{:object => true})
         | 
| 163 | 
            +
                    resp.should be_a JiakObject
         | 
| 164 | 
            +
                    resp.key.should_not be_nil
         | 
| 165 | 
            +
                    resp.data.should be_a FooBarBaz
         | 
| 166 | 
            +
                  end
         | 
| 167 | 
            +
                  
         | 
| 168 | 
            +
                  it "should handle odd key values" do
         | 
| 169 | 
            +
                    key = '$ p @ c #'
         | 
| 170 | 
            +
                    jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
         | 
| 171 | 
            +
                    resp_key = @client.store(jobj)
         | 
| 172 | 
            +
                    resp_key.should eql key
         | 
| 173 | 
            +
                  end
         | 
| 174 | 
            +
                end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                describe "fetching" do
         | 
| 177 | 
            +
                  it "should get a previously stored JiakObject" do
         | 
| 178 | 
            +
                    key = 'fetch_key_1'
         | 
| 179 | 
            +
                    jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
         | 
| 180 | 
            +
                    @client.store(jobj)
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                    fetched = @client.get(@bucket,key)
         | 
| 183 | 
            +
                    fetched.should be_a JiakObject
         | 
| 184 | 
            +
                    fetched.bucket.should eql @bucket
         | 
| 185 | 
            +
                    fetched.key.should eql key
         | 
| 186 | 
            +
                    fetched.data.should eql jobj.data
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                    jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
         | 
| 189 | 
            +
                    key = @client.store(jobj)
         | 
| 190 | 
            +
                    fetched = @client.get(@bucket,key)
         | 
| 191 | 
            +
                    fetched.should be_a JiakObject
         | 
| 192 | 
            +
                  end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                  it "should raise JiakResourceNotFound for a non-existent key" do
         | 
| 195 | 
            +
                    get_nope = lambda {@client.get(@bucket,'nope')}
         | 
| 196 | 
            +
                    get_nope.should raise_error(JiakResourceNotFound)
         | 
| 197 | 
            +
                  end
         | 
| 198 | 
            +
                end
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                describe "updating" do
         | 
| 201 | 
            +
                  it "should update a previously stored JiakObject" do
         | 
| 202 | 
            +
                    jobj =
         | 
| 203 | 
            +
                      @client.store(JiakObject.new(:bucket => @bucket, :data => @data),
         | 
| 204 | 
            +
                                    {:object => true})
         | 
| 205 | 
            +
                    
         | 
| 206 | 
            +
                    jobj.data.should eql @data
         | 
| 207 | 
            +
                    [:vclock,:vtag,:lastmod].each do |field|
         | 
| 208 | 
            +
                      jobj.riak.should include field
         | 
| 209 | 
            +
                      jobj.riak[field].should be_a String
         | 
| 210 | 
            +
                      jobj.riak[field].should_not be_empty
         | 
| 211 | 
            +
                    end
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                    updated_data = FooBarBaz.new(:foo => 'new val')
         | 
| 214 | 
            +
                    jobj.data = updated_data
         | 
| 215 | 
            +
                    updated_object = 
         | 
| 216 | 
            +
                      @client.store(jobj,{:object => true})
         | 
| 217 | 
            +
                    updated_data = updated_object.data
         | 
| 218 | 
            +
                    updated_data.should_not eql @data
         | 
| 219 | 
            +
                    updated_data.foo.should eql 'new val'
         | 
| 220 | 
            +
                    updated_object.riak[:vclock].should_not eql jobj.riak[:vclock]
         | 
| 221 | 
            +
                    updated_object.riak[:vtag].should_not eql jobj.riak[:vtag]
         | 
| 222 | 
            +
                  end
         | 
| 223 | 
            +
                end
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                describe "deleting" do
         | 
| 226 | 
            +
                  it "should remove a previously stored JiakObject" do
         | 
| 227 | 
            +
                    key = 'delete_key_1'
         | 
| 228 | 
            +
                    jobj = JiakObject.new(:bucket => @bucket, :key => key, :data => @data)
         | 
| 229 | 
            +
                    @client.store(jobj)
         | 
| 230 | 
            +
             | 
| 231 | 
            +
                    @client.delete(@bucket,key).should be true
         | 
| 232 | 
            +
                    get_deleted = lambda {@client.get(@bucket,key)}
         | 
| 233 | 
            +
                    get_deleted.should raise_error(JiakResourceNotFound)
         | 
| 234 | 
            +
                  end
         | 
| 235 | 
            +
                end
         | 
| 236 | 
            +
              end
         | 
| 237 | 
            +
             | 
| 238 | 
            +
            end
         | 
| 239 | 
            +
             | 
| 240 | 
            +
            Parent = JiakDataHash.create(:name)
         | 
| 241 | 
            +
            Child = JiakDataHash.create(:name)
         | 
| 242 | 
            +
             | 
| 243 | 
            +
            describe "JiakClient links" do
         | 
| 244 | 
            +
              before do
         | 
| 245 | 
            +
                @base_uri = 'http://127.0.0.1:8002/jiak/'
         | 
| 246 | 
            +
                @client = JiakClient.new @base_uri
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                @p_bucket = JiakBucket.new('parent',Parent)
         | 
| 249 | 
            +
                @c_bucket = JiakBucket.new('child',Child)
         | 
| 250 | 
            +
                @client.set_schema(@p_bucket)
         | 
| 251 | 
            +
                @client.set_schema(@c_bucket)
         | 
| 252 | 
            +
              end
         | 
| 253 | 
            +
             | 
| 254 | 
            +
              it "should add links and walk the resulting structure" do
         | 
| 255 | 
            +
                parent_children = {
         | 
| 256 | 
            +
                  'p1' => ['c1','c2'],
         | 
| 257 | 
            +
                  'p2' => ['c2','c3','c4'],
         | 
| 258 | 
            +
                  'p3' => ['c4','c5','c6'],
         | 
| 259 | 
            +
                  'p4' => ['c5','c6'],
         | 
| 260 | 
            +
                  'p5' => ['c7']
         | 
| 261 | 
            +
                }
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                # invert the p/c relationships
         | 
| 264 | 
            +
                child_parents = parent_children.inject({}) do |build, (p,cs)|
         | 
| 265 | 
            +
                  cs.each do |c|
         | 
| 266 | 
            +
                    build[c] ? build[c] << p : build[c] = [p]
         | 
| 267 | 
            +
                  end
         | 
| 268 | 
            +
                  build
         | 
| 269 | 
            +
                end
         | 
| 270 | 
            +
             | 
| 271 | 
            +
                # for each p/c relation
         | 
| 272 | 
            +
                #  - create p and c (when necessary)
         | 
| 273 | 
            +
                #  - add links for p -> c and c -> p
         | 
| 274 | 
            +
                parent_children.each do |p_name,c_names|
         | 
| 275 | 
            +
                  p_data = Parent.new(:name => p_name)
         | 
| 276 | 
            +
                  p_obj = JiakObject.new(:bucket => @p_bucket,
         | 
| 277 | 
            +
                                         :key => p_name,
         | 
| 278 | 
            +
                                         :data => p_data)
         | 
| 279 | 
            +
                  parent = @client.store(p_obj,:object => true)
         | 
| 280 | 
            +
                  p_link = JiakLink.new(@p_bucket,parent.key,'parent')
         | 
| 281 | 
            +
                  c_names.each do |c_name|
         | 
| 282 | 
            +
                    begin
         | 
| 283 | 
            +
                      child = @client.get(@c_bucket,c_name)
         | 
| 284 | 
            +
                    rescue JiakResourceNotFound
         | 
| 285 | 
            +
                      c_data = Child.new(:name => c_name)
         | 
| 286 | 
            +
                      c_obj = JiakObject.new(:bucket => @c_bucket,
         | 
| 287 | 
            +
                                             :key => c_name,
         | 
| 288 | 
            +
                                             :data => c_data)
         | 
| 289 | 
            +
                      child = @client.store(c_obj, :object => true)
         | 
| 290 | 
            +
                    end
         | 
| 291 | 
            +
                    c_link = JiakLink.new(@c_bucket,child.key,'child')
         | 
| 292 | 
            +
                    child << p_link
         | 
| 293 | 
            +
                    @client.store(child)
         | 
| 294 | 
            +
                    parent << c_link
         | 
| 295 | 
            +
                  end
         | 
| 296 | 
            +
                  @client.store(parent)
         | 
| 297 | 
            +
                end
         | 
| 298 | 
            +
             | 
| 299 | 
            +
                # get the number of links in the p's
         | 
| 300 | 
            +
                p1,p2,p3,p4,p5 = parent_children.keys.map {|p| @client.get(@p_bucket,p)}
         | 
| 301 | 
            +
                [p1,p4].each {|p| p.links.should have_exactly(2).items}
         | 
| 302 | 
            +
                [p2,p3].each {|p| p.links.should have_exactly(3).items}
         | 
| 303 | 
            +
                p5.links.should have_exactly(1).item
         | 
| 304 | 
            +
             | 
| 305 | 
            +
                # get the number of links in the c's
         | 
| 306 | 
            +
                c1,c2,c3,c4,c5,c6,c7 = child_parents.keys.map {|c| @client.get(@c_bucket,c)}
         | 
| 307 | 
            +
                [c1,c3,c7].each {|c| c.links.should have_exactly(1).items}
         | 
| 308 | 
            +
                [c2,c4,c5,c6].each {|c| c.links.should have_exactly(2).items}
         | 
| 309 | 
            +
             | 
| 310 | 
            +
                # check the links in each p and c
         | 
| 311 | 
            +
                p_link = JiakLink.new(@p_bucket,'k','parent')
         | 
| 312 | 
            +
                c_link = JiakLink.new(@c_bucket,'k','child')
         | 
| 313 | 
            +
                parent_children.each do |p_name,children|
         | 
| 314 | 
            +
                  parent = @client.get(@p_bucket,p_name)
         | 
| 315 | 
            +
                  links = parent.links
         | 
| 316 | 
            +
                  children.each do |c_name|
         | 
| 317 | 
            +
                    c_link.key = c_name
         | 
| 318 | 
            +
                    parent.links.should include c_link
         | 
| 319 | 
            +
             | 
| 320 | 
            +
                    child = @client.get(@c_bucket,c_name)
         | 
| 321 | 
            +
                    p_link.key = p_name
         | 
| 322 | 
            +
                    child.links.should include p_link
         | 
| 323 | 
            +
                  end
         | 
| 324 | 
            +
                end
         | 
| 325 | 
            +
                
         | 
| 326 | 
            +
                # p's should include links to their c's
         | 
| 327 | 
            +
                c_link = QueryLink.new(@c_bucket,'child',nil)
         | 
| 328 | 
            +
                parent_children.each do |p_name,children|
         | 
| 329 | 
            +
                  @client.walk(@p_bucket,p_name,c_link,Child).each do |c_obj|
         | 
| 330 | 
            +
                    children.should include c_obj.data.name
         | 
| 331 | 
            +
                  end
         | 
| 332 | 
            +
                end
         | 
| 333 | 
            +
             | 
| 334 | 
            +
                # c's should include links to their p's
         | 
| 335 | 
            +
                p_link = QueryLink.new(@p_bucket,'parent',nil)
         | 
| 336 | 
            +
                child_parents.each do |c_name,parents|
         | 
| 337 | 
            +
                  @client.walk(@c_bucket,c_name,p_link,Parent).each do |p_obj|
         | 
| 338 | 
            +
                    parents.should include p_obj.data.name
         | 
| 339 | 
            +
                  end
         | 
| 340 | 
            +
                end
         | 
| 341 | 
            +
             | 
| 342 | 
            +
                # c siblings requires a second step
         | 
| 343 | 
            +
                c1s,c2s,c3s,c4s,c5s,c6s,c7s = child_parents.keys.map do |c|
         | 
| 344 | 
            +
                  siblings = @client.walk(@c_bucket,c,[p_link,c_link],Child)
         | 
| 345 | 
            +
                  me = @client.get(@c_bucket,c)
         | 
| 346 | 
            +
                  siblings.reject! {|s| s.eql?(me)}
         | 
| 347 | 
            +
                  siblings
         | 
| 348 | 
            +
                end
         | 
| 349 | 
            +
                c1s.should have_exactly(1).item
         | 
| 350 | 
            +
                c2s.should have_exactly(3).items
         | 
| 351 | 
            +
                c3s.should have_exactly(2).items
         | 
| 352 | 
            +
                c4s.should have_exactly(4).items
         | 
| 353 | 
            +
                c5s.should have_exactly(2).items
         | 
| 354 | 
            +
                c6s.should have_exactly(2).items
         | 
| 355 | 
            +
                c7s.should have_exactly(0).items
         | 
| 356 | 
            +
              end
         | 
| 357 | 
            +
             | 
| 358 | 
            +
            end
         | 
| @@ -0,0 +1,77 @@ | |
| 1 | 
            +
            require File.dirname(__FILE__) + '/../spec_helper.rb'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe "JiakLink" do
         | 
| 4 | 
            +
              before do
         | 
| 5 | 
            +
                @bucket = 'b'
         | 
| 6 | 
            +
                @key = 'k'
         | 
| 7 | 
            +
                @tag = 't'
         | 
| 8 | 
            +
                @jiak_link = JiakLink.new(@bucket,@key,@tag)
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              it "should respond to" do
         | 
| 12 | 
            +
                @jiak_link.should respond_to(:bucket,:key,:tag)
         | 
| 13 | 
            +
                @jiak_link.should respond_to(:bucket=,:key=,:tag=)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                @jiak_link.should respond_to(:for_jiak)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                @jiak_link.should respond_to(:eql?,:==)
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              it "should init from specified values" do
         | 
| 21 | 
            +
                @jiak_link.bucket.should eql @bucket
         | 
| 22 | 
            +
                @jiak_link.key.should eql @key
         | 
| 23 | 
            +
                @jiak_link.tag.should eql @tag
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                jiak_link = JiakLink.new(@jiak_link)
         | 
| 26 | 
            +
                jiak_link.bucket.should eql @bucket
         | 
| 27 | 
            +
                jiak_link.key.should eql @key
         | 
| 28 | 
            +
                jiak_link.tag.should eql @tag
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                jiak_link = JiakLink.new(['b','k','t'])
         | 
| 31 | 
            +
                jiak_link.bucket.should eql 'b'
         | 
| 32 | 
            +
                jiak_link.key.should eql 'k'
         | 
| 33 | 
            +
                jiak_link.tag.should eql 't'
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              it "should ignore leading/trailing spaces for opts on init" do
         | 
| 37 | 
            +
                bucket = " "+@bucket+" "
         | 
| 38 | 
            +
                key = " "+@key+" "
         | 
| 39 | 
            +
                tag = " "+@tag+" "
         | 
| 40 | 
            +
                jiak_link = JiakLink.new(bucket,key,tag)
         | 
| 41 | 
            +
                jiak_link.bucket.should eql @bucket
         | 
| 42 | 
            +
                jiak_link.key.should eql @key
         | 
| 43 | 
            +
                jiak_link.tag.should eql @tag
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
              
         | 
| 46 | 
            +
              it "should reject blank, empty strings, or nil values on init" do
         | 
| 47 | 
            +
                ["","  ",nil].each do |bucket|
         | 
| 48 | 
            +
                  bad_bucket = lambda { JiakLink.new(bucket,'k','t') }
         | 
| 49 | 
            +
                  bad_bucket.should raise_error(JiakLinkException)
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              it "should allow field updates" do
         | 
| 54 | 
            +
                @jiak_link.bucket = 'new_bucket'
         | 
| 55 | 
            +
                @jiak_link.bucket.should eql 'new_bucket'
         | 
| 56 | 
            +
                @jiak_link.key = 'new_key'
         | 
| 57 | 
            +
                @jiak_link.key.should eql 'new_key'
         | 
| 58 | 
            +
                @jiak_link.tag = 'new_tag'
         | 
| 59 | 
            +
                @jiak_link.tag.should eql 'new_tag'
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              it "should convert for Jiak" do
         | 
| 63 | 
            +
                @jiak_link.for_jiak.should eql [@bucket,@key,@tag]
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
              
         | 
| 66 | 
            +
              it "should compare to another JiakLink via eql?" do
         | 
| 67 | 
            +
                jiak_link_1 = JiakLink.new('a','b','c')
         | 
| 68 | 
            +
                jiak_link_2 = JiakLink.new('a','b','c')
         | 
| 69 | 
            +
                jiak_link_3 = JiakLink.new('a','~b','c')
         | 
| 70 | 
            +
                
         | 
| 71 | 
            +
                jiak_link_1.should eql jiak_link_2
         | 
| 72 | 
            +
                jiak_link_1.should_not eql jiak_link_3
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                jiak_link_1.should == jiak_link_2
         | 
| 75 | 
            +
                jiak_link_1.should_not == jiak_link_3
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
            end
         | 
| @@ -0,0 +1,210 @@ | |
| 1 | 
            +
            require File.dirname(__FILE__) + '/../spec_helper.rb'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            DataObject = JiakDataHash.create(:f1,:f2,:f3)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            describe "JiakObject" do
         | 
| 6 | 
            +
              before do
         | 
| 7 | 
            +
                @data = 
         | 
| 8 | 
            +
                  DataObject.new(:f1 => 'f1',:f2 => ['a','b'], :f3 => {:f3_1 => 'f3_1'})
         | 
| 9 | 
            +
                @bucket_name = 'bucket'
         | 
| 10 | 
            +
                @bucket = JiakBucket.new(@bucket_name,DataObject)
         | 
| 11 | 
            +
                @key = 'hey'
         | 
| 12 | 
            +
                @l1 = JiakLink.new('l1b','l1k','l1t')
         | 
| 13 | 
            +
                @l2 = JiakLink.new('l2b','l2k','l2t')
         | 
| 14 | 
            +
                @links = [@l1,@l2]
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                object = @data.for_jiak
         | 
| 17 | 
            +
                links = @links.map {|link| link.for_jiak}
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                core = {
         | 
| 20 | 
            +
                  :bucket => @bucket_name, :key => @key,
         | 
| 21 | 
            +
                  :object => object, :links => links
         | 
| 22 | 
            +
                }
         | 
| 23 | 
            +
                full = core.merge(:vclock=>'vclock',:vtag=>'vtag',:lastmod=>'last mod')
         | 
| 24 | 
            +
                @core_json = core.to_json
         | 
| 25 | 
            +
                @full_json = full.to_json
         | 
| 26 | 
            +
                @object = JiakObject.new(:bucket => @bucket,
         | 
| 27 | 
            +
                                         :key => @key,
         | 
| 28 | 
            +
                                         :data => @data,
         | 
| 29 | 
            +
                                         :links => @links)
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              it "should respond to" do
         | 
| 33 | 
            +
                JiakObject.should respond_to(:new,:from_jiak)
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                @object.should respond_to(:bucket,:bucket=)
         | 
| 36 | 
            +
                @object.should respond_to(:key,:key=)
         | 
| 37 | 
            +
                @object.should respond_to(:data,:data=)
         | 
| 38 | 
            +
                @object.should respond_to(:links,:links=)
         | 
| 39 | 
            +
                @object.should respond_to(:riak,:riak=)
         | 
| 40 | 
            +
                @object.should respond_to(:<<)
         | 
| 41 | 
            +
                @object.should respond_to(:==,:eql?)
         | 
| 42 | 
            +
                @object.should respond_to(:to_jiak)
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              it "should initialize with bucket, key and data" do
         | 
| 46 | 
            +
                @object.bucket.should eql @bucket
         | 
| 47 | 
            +
                @object.key.should eql @key
         | 
| 48 | 
            +
                @object.data.should be_a JiakData
         | 
| 49 | 
            +
                @object.data.should eql @data
         | 
| 50 | 
            +
                @object.links.should be_an Array
         | 
| 51 | 
            +
                @object.links.should eql @links
         | 
| 52 | 
            +
                
         | 
| 53 | 
            +
                jobj = JiakObject.new(:bucket => @bucket, :key => @key, :data => @data)
         | 
| 54 | 
            +
                jobj.bucket.should eql @bucket
         | 
| 55 | 
            +
                jobj.links.should be_empty
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              it "should allow nil, missing, blank or empty key" do
         | 
| 59 | 
            +
                [nil,'','  '].each do |key|
         | 
| 60 | 
            +
                  JiakObject.new(:bucket => @bucket, :data => @data,
         | 
| 61 | 
            +
                                 :key => key ).key.should be_empty
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
                JiakObject.new(:bucket => @bucket, :data => @data).key.should be_empty
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
             | 
| 67 | 
            +
              it "should initialize with specified links" do
         | 
| 68 | 
            +
                @object.links.should equal @links
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              it "should initialize from JSON" do
         | 
| 72 | 
            +
                [@core_json,@full_json].each do |json|
         | 
| 73 | 
            +
                  jiak = JSON.parse(json)
         | 
| 74 | 
            +
                  jobj = JiakObject.from_jiak(jiak,@bucket.data_class)
         | 
| 75 | 
            +
                  jobj.bucket.should eql @object.bucket
         | 
| 76 | 
            +
                  jobj.key.should eql @object.key
         | 
| 77 | 
            +
                  jobj.data.f1.should eql @data.f1
         | 
| 78 | 
            +
                  jobj.data.f2.should eql @data.f2
         | 
| 79 | 
            +
                  jobj.data.f3['f3_1'].should eql @data.f3[:f3_1]
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  jobj.links.size.should == @object.links.size
         | 
| 82 | 
            +
                  jlinks = jobj.links
         | 
| 83 | 
            +
                  olinks = @object.links
         | 
| 84 | 
            +
                  same = jlinks.reduce(true) {|same,value| same && olinks.include?(value)}
         | 
| 85 | 
            +
                  same.should be true
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                jiak = JSON.parse(@full_json)
         | 
| 89 | 
            +
                jobj = JiakObject.from_jiak(jiak,@bucket.data_class)
         | 
| 90 | 
            +
                jobj.riak[:vclock].should eql 'vclock'
         | 
| 91 | 
            +
                jobj.riak[:vtag].should eql 'vtag'
         | 
| 92 | 
            +
                jobj.riak[:lastmod].should eql 'last mod'
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
              it "should raise JiakObjectException for nil bucket" do
         | 
| 96 | 
            +
                nil_bucket = lambda {JiakObject.new(:bucket => nil,:data_obect => @data)}
         | 
| 97 | 
            +
                nil_bucket.should raise_error(JiakObjectException)
         | 
| 98 | 
            +
                no_bucket = lambda {JiakObject.new(:data_obect => @data)}
         | 
| 99 | 
            +
                no_bucket.should raise_error(JiakObjectException)
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
              it "should raise JiakObjectException if object not a JiakData" do
         | 
| 103 | 
            +
                bad_data = lambda {JiakObject.new(:bucket=>@bucket,:data=>'a')}
         | 
| 104 | 
            +
                bad_data.should raise_error(JiakObjectException,/JiakData/)
         | 
| 105 | 
            +
                no_data = lambda {JiakObject.new(:bucket=>@bucket)}
         | 
| 106 | 
            +
                no_data.should raise_error(JiakObjectException,/JiakData/)
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
              it "should raise JiakObjectException if link not an Array" do
         | 
| 110 | 
            +
                link_not_array = lambda {JiakObject.new(:bucket => @bucket,
         | 
| 111 | 
            +
                                                        :data => @data,
         | 
| 112 | 
            +
                                                        :links =>"l")}
         | 
| 113 | 
            +
                link_not_array.should raise_error(JiakObjectException,/array/)
         | 
| 114 | 
            +
              end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
              it "should raise JiakObjectException if each link is not a JiakLink" do
         | 
| 117 | 
            +
                links = [@l1,'l',@l2]
         | 
| 118 | 
            +
                bad_link = lambda {JiakObject.new(:bucket => @bucket,
         | 
| 119 | 
            +
                                                  :data => @data,
         | 
| 120 | 
            +
                                                  :links => [@l1,'l',@l2])}
         | 
| 121 | 
            +
                bad_link.should raise_error(JiakObjectException,/JiakLink/)
         | 
| 122 | 
            +
              end
         | 
| 123 | 
            +
              
         | 
| 124 | 
            +
              it "should convert to JSON" do
         | 
| 125 | 
            +
                json = @object.to_jiak
         | 
| 126 | 
            +
                json.should eql @core_json
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                parsed = JSON.parse(json)
         | 
| 129 | 
            +
                parsed['bucket'].should eql @bucket_name
         | 
| 130 | 
            +
                parsed['key'].should eql @key
         | 
| 131 | 
            +
                parsed['object']['f1'].should eql @data.f1
         | 
| 132 | 
            +
                parsed['object']['f2'].should eql @data.f2
         | 
| 133 | 
            +
                parsed['object']['f3']['f3_1'].should eql @data.f3[:f3_1]
         | 
| 134 | 
            +
                @links.each_with_index do |link,ndx|
         | 
| 135 | 
            +
                  parsed['links'][ndx].should eql link.for_jiak
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
              end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
              it "should allow attribute updates" do
         | 
| 140 | 
            +
                bucket_name = 'new bucket'
         | 
| 141 | 
            +
                bucket = JiakBucket.new(bucket_name,DataObject)
         | 
| 142 | 
            +
                @object.bucket = bucket
         | 
| 143 | 
            +
                @object.bucket.should eql bucket
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                key = 'new key'
         | 
| 146 | 
            +
                @object.key = key
         | 
| 147 | 
            +
                @object.key.should eql key
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                object = DataObject.new(:f1 => 'new f1',:f2 => [], :f3 => 6)
         | 
| 150 | 
            +
                @object.data.should_not eql object
         | 
| 151 | 
            +
                @object.data = object
         | 
| 152 | 
            +
                @object.data.should eql object
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                links = [JiakLink.new('c','b','a')]
         | 
| 155 | 
            +
                @object.links = links
         | 
| 156 | 
            +
                @object.links.should eql links
         | 
| 157 | 
            +
                
         | 
| 158 | 
            +
                riak = {:vclock => 'VCLOCK', :vtag => 'VTAG', :lastmod => 'LASTMOD'}
         | 
| 159 | 
            +
                @object.riak = riak
         | 
| 160 | 
            +
                @object.riak.should eql riak
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                bad_bucket = lambda {@object.bucket = 'bucket'}
         | 
| 163 | 
            +
                bad_bucket.should raise_error(JiakObjectException,/Bucket/)
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                bad_key = lambda {@object.key = @bucket}
         | 
| 166 | 
            +
                bad_key.should raise_error(JiakObjectException,/Key/)
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                bad_object = lambda {@object.data = @bucket}
         | 
| 169 | 
            +
                bad_object.should raise_error(JiakObjectException,/Data/)
         | 
| 170 | 
            +
                
         | 
| 171 | 
            +
                bad_links = lambda {@object.links = @bucket}
         | 
| 172 | 
            +
                bad_links.should raise_error(JiakObjectException,/Links/)
         | 
| 173 | 
            +
              end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
              it "should add a link" do
         | 
| 176 | 
            +
                jiak_link = JiakLink.new('a','b','c')
         | 
| 177 | 
            +
                @object.links.should_not include jiak_link
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                size = @links.size
         | 
| 180 | 
            +
                @object << jiak_link
         | 
| 181 | 
            +
                @object.links.should have_exactly(size+1).items
         | 
| 182 | 
            +
                @object.links.should include jiak_link
         | 
| 183 | 
            +
              end
         | 
| 184 | 
            +
              
         | 
| 185 | 
            +
              it "should ignore a duplicate link" do
         | 
| 186 | 
            +
                size = @object.links.size
         | 
| 187 | 
            +
                @object << @l1
         | 
| 188 | 
            +
                @object.links.should have_exactly(size).items
         | 
| 189 | 
            +
              end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
              it "should chain link adds" do
         | 
| 192 | 
            +
                size = @object.links.size
         | 
| 193 | 
            +
                jiak_link = JiakLink.new('a','b','c')
         | 
| 194 | 
            +
                @object << @l2 << jiak_link
         | 
| 195 | 
            +
                @object.links.should have_exactly(size+1).items
         | 
| 196 | 
            +
              end
         | 
| 197 | 
            +
             | 
| 198 | 
            +
              it "should raise exception if adding a non-JiakLink" do
         | 
| 199 | 
            +
                bad_link = lambda {@object << ['l']}
         | 
| 200 | 
            +
                bad_link.should raise_error(JiakObjectException,/JiakLink/)
         | 
| 201 | 
            +
              end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
              it "should eql an equal JiakObject" do
         | 
| 204 | 
            +
                jobj = JiakObject.new(:bucket => @bucket, :key => @key,
         | 
| 205 | 
            +
                                      :data => @data, :links => @links)
         | 
| 206 | 
            +
                @object.should eql jobj
         | 
| 207 | 
            +
                @object.should ==  jobj
         | 
| 208 | 
            +
              end
         | 
| 209 | 
            +
             | 
| 210 | 
            +
            end
         |