toystore 0.6.1 → 0.6.2

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.
@@ -1,8 +1,13 @@
1
1
  require 'pp'
2
+ require 'pathname'
2
3
  require 'rubygems'
3
- require 'toystore'
4
4
  require 'adapter/memcached'
5
5
 
6
+ root_path = Pathname(__FILE__).dirname.join('..').expand_path
7
+ lib_path = root_path.join('lib')
8
+ $:.unshift(lib_path)
9
+ require 'toystore'
10
+
6
11
  class GameList
7
12
  include Toy::Store
8
13
  store :memcached, Memcached.new
data/examples/memory.rb CHANGED
@@ -1,8 +1,13 @@
1
1
  require 'pp'
2
+ require 'pathname'
2
3
  require 'rubygems'
3
- require 'toystore'
4
4
  require 'adapter/memory'
5
5
 
6
+ root_path = Pathname(__FILE__).dirname.join('..').expand_path
7
+ lib_path = root_path.join('lib')
8
+ $:.unshift(lib_path)
9
+ require 'toystore'
10
+
6
11
  class User
7
12
  include Toy::Store
8
13
  store :memory, {}
data/examples/mongo.rb CHANGED
@@ -1,11 +1,16 @@
1
1
  require 'pp'
2
+ require 'pathname'
2
3
  require 'rubygems'
3
- require 'toystore'
4
4
  require 'adapter/mongo'
5
5
 
6
+ root_path = Pathname(__FILE__).dirname.join('..').expand_path
7
+ lib_path = root_path.join('lib')
8
+ $:.unshift(lib_path)
9
+ require 'toystore'
6
10
  class User
7
11
  include Toy::Store
8
12
  store :mongo, Mongo::Connection.new.db('adapter')['testing']
13
+ key(:object_id)
9
14
 
10
15
  attribute :name, String
11
16
  end
@@ -9,6 +9,10 @@ $:.unshift(lib_path)
9
9
  require 'toystore'
10
10
 
11
11
  class NamespacedUUIDKeyFactory < Toy::Identity::AbstractKeyFactory
12
+ def key_type
13
+ String
14
+ end
15
+
12
16
  def next_key(object)
13
17
  [object.class.name, SimpleUUID::UUID.new.to_guid].join(':')
14
18
  end
data/examples/redis.rb CHANGED
@@ -1,8 +1,13 @@
1
1
  require 'pp'
2
+ require 'pathname'
2
3
  require 'rubygems'
3
- require 'toystore'
4
4
  require 'adapter/redis'
5
5
 
6
+ root_path = Pathname(__FILE__).dirname.join('..').expand_path
7
+ lib_path = root_path.join('lib')
8
+ $:.unshift(lib_path)
9
+ require 'toystore'
10
+
6
11
  class User
7
12
  include Toy::Store
8
13
  store :redis, Redis.new
data/examples/riak.rb CHANGED
@@ -1,8 +1,13 @@
1
1
  require 'pp'
2
+ require 'pathname'
2
3
  require 'rubygems'
3
- require 'toystore'
4
4
  require 'adapter/riak'
5
5
 
6
+ root_path = Pathname(__FILE__).dirname.join('..').expand_path
7
+ lib_path = root_path.join('lib')
8
+ $:.unshift(lib_path)
9
+ require 'toystore'
10
+
6
11
  class GameList
7
12
  include Toy::Store
8
13
  store :riak, Riak::Client.new['adapter_example']
@@ -5,7 +5,6 @@ module Toy
5
5
 
6
6
  included do
7
7
  attribute_method_suffix('', '=', '?')
8
- attribute :id, String
9
8
  end
10
9
 
11
10
  module ClassMethods
@@ -42,6 +41,7 @@ module Toy
42
41
 
43
42
  def reload
44
43
  if attrs = store.read(store_key)
44
+ attrs['id'] = store_key
45
45
  instance_variables.each { |ivar| instance_variable_set(ivar, nil) }
46
46
  initialize_attributes_with_defaults
47
47
  self.attributes = attrs
@@ -26,4 +26,16 @@ module Toy
26
26
  super("#{adapter.name.to_s.capitalize} adapter does not support locking")
27
27
  end
28
28
  end
29
+
30
+ class InvalidKeyFactory < Error
31
+ def initialize(name_or_factory)
32
+ super("#{name_or_factory.inspect} is not a valid name and did not respond to next_key and key_type")
33
+ end
34
+ end
35
+
36
+ class InvalidKey < Error
37
+ def initialize(*)
38
+ super("Key may not be nil")
39
+ end
40
+ end
29
41
  end
@@ -1,6 +1,10 @@
1
1
  module Toy
2
2
  module Identity
3
3
  class AbstractKeyFactory
4
+ def key_type
5
+ raise NotImplementedError, "#{self.class.name}.store_type isn't implemented."
6
+ end
7
+
4
8
  def next_key(object)
5
9
  raise NotImplementedError, "#{self.class.name}#next_key isn't implemented."
6
10
  end
@@ -3,9 +3,24 @@ require 'bson'
3
3
  module Toy
4
4
  module Identity
5
5
  class ObjectIdKeyFactory < AbstractKeyFactory
6
+ def key_type
7
+ BSON::ObjectId
8
+ end
9
+
6
10
  def next_key(object)
7
11
  BSON::ObjectId.new
8
12
  end
9
13
  end
10
14
  end
15
+ end
16
+
17
+ class BSON::ObjectId
18
+ def self.to_store(value, *)
19
+ return value if value.is_a?(BSON::ObjectId)
20
+ BSON::ObjectId.from_string(value.to_s)
21
+ end
22
+
23
+ def self.from_store(value, *)
24
+ value
25
+ end
11
26
  end
@@ -1,6 +1,10 @@
1
1
  module Toy
2
2
  module Identity
3
3
  class UUIDKeyFactory < AbstractKeyFactory
4
+ def key_type
5
+ String
6
+ end
7
+
4
8
  def next_key(object)
5
9
  SimpleUUID::UUID.new.to_guid
6
10
  end
data/lib/toy/identity.rb CHANGED
@@ -15,13 +15,20 @@ module Toy
15
15
  require 'toy/identity/object_id_key_factory'
16
16
  ObjectIdKeyFactory.new
17
17
  else
18
- name_or_factory
18
+ if name_or_factory.respond_to?(:next_key) &&
19
+ name_or_factory.respond_to?(:key_type)
20
+ name_or_factory
21
+ else
22
+ raise InvalidKeyFactory.new(name_or_factory)
23
+ end
19
24
  end
25
+ attribute :id, @key_factory.key_type
26
+ @key_factory
20
27
  end
21
28
 
22
29
  def next_key(object = nil)
23
30
  @key_factory.next_key(object).tap do |key|
24
- raise "Keys may not be nil" if key.nil?
31
+ raise InvalidKey.new if key.nil?
25
32
  end
26
33
  end
27
34
  end
@@ -49,15 +49,15 @@ module Toy
49
49
  return nil unless identity_map_on?
50
50
  key = store_key(id)
51
51
  if record = identity_map[key]
52
- logger.debug("ToyStore IMG #{key.inspect}")
52
+ logger.debug("ToyStore IMG #{self.name} #{key.inspect}")
53
53
  record
54
54
  end
55
55
  end
56
56
 
57
- def load(attrs)
57
+ def load(key, attrs)
58
58
  return nil if attrs.nil?
59
59
 
60
- if instance = identity_map[store_key(attrs['id'])]
60
+ if instance = identity_map[store_key(key)]
61
61
  instance
62
62
  else
63
63
  super.tap { |doc| doc.add_to_identity_map }
@@ -83,14 +83,14 @@ module Toy
83
83
  return unless self.class.identity_map_on?
84
84
  key = store_key
85
85
  identity_map[key] = self
86
- logger.debug("ToyStore IMS #{key.inspect}")
86
+ logger.debug("ToyStore IMS #{self.class.name} #{key.inspect}")
87
87
  end
88
88
 
89
89
  def remove_from_identity_map
90
90
  return unless self.class.identity_map_on?
91
91
  key = store_key
92
92
  identity_map.delete(key)
93
- logger.debug("ToyStore IMD #{key.inspect}")
93
+ logger.debug("ToyStore IMD #{self.class.name} #{key.inspect}")
94
94
  end
95
95
 
96
96
  private
data/lib/toy/logger.rb CHANGED
@@ -7,8 +7,8 @@ module Toy
7
7
  Toy.logger
8
8
  end
9
9
 
10
- def log_operation(operation, adapter, key, value)
11
- logger.debug("ToyStore #{operation} :#{adapter.name} #{key.inspect}")
10
+ def log_operation(operation, model, adapter, key, value)
11
+ logger.debug("ToyStore #{operation} #{model} :#{adapter.name} #{key.inspect}")
12
12
  logger.debug(" #{value.inspect}")
13
13
  end
14
14
  end
@@ -92,7 +92,7 @@ module Toy
92
92
  def delete
93
93
  key = store_key
94
94
  @_destroyed = true
95
- logger.debug("ToyStore DEL #{key.inspect}")
95
+ logger.debug("ToyStore DEL #{self.class.name} #{key.inspect}")
96
96
  store.delete(key)
97
97
  end
98
98
 
@@ -111,14 +111,13 @@ module Toy
111
111
 
112
112
  def persist!
113
113
  key, attrs = store_key, persisted_attributes
114
-
114
+ attrs.delete('id') # no need to persist id as that is key
115
115
  if self.class.has_cache?
116
116
  cache.write(key, attrs)
117
- log_operation('WTS', cache, key, attrs)
117
+ log_operation('WTS', self, cache, key, attrs)
118
118
  end
119
-
120
119
  store.write(key, attrs)
121
- log_operation('SET', store, key, attrs)
120
+ log_operation('SET', self, store, key, attrs)
122
121
  persist
123
122
  each_embedded_object { |doc| doc.send(:persist) }
124
123
  true
@@ -34,7 +34,12 @@ module Toy
34
34
 
35
35
  def replace(instances)
36
36
  @target = instances.map do |instance|
37
- instance = instance.is_a?(proxy_class) ? instance : proxy_class.load(instance)
37
+ instance = if instance.is_a?(proxy_class)
38
+ instance
39
+ else
40
+ key = instance.delete('id')
41
+ proxy_class.load(key, instance)
42
+ end
38
43
  assign_reference(instance)
39
44
  end
40
45
  end
data/lib/toy/querying.rb CHANGED
@@ -8,20 +8,20 @@ module Toy
8
8
 
9
9
  if has_cache?
10
10
  value = cache.read(key)
11
- log_operation('RTG', cache, key, value)
11
+ log_operation('RTG', self, cache, key, value)
12
12
  end
13
13
 
14
14
  if value.nil?
15
15
  value = store.read(key)
16
- log_operation('GET', store, key, value)
16
+ log_operation('GET', self, store, key, value)
17
17
 
18
18
  if has_cache?
19
19
  cache.write(key, value)
20
- log_operation('RTS', cache, key, value)
20
+ log_operation('RTS', self, cache, key, value)
21
21
  end
22
22
  end
23
23
 
24
- load(value)
24
+ load(key, value)
25
25
  end
26
26
 
27
27
  def get!(id)
@@ -43,13 +43,14 @@ module Toy
43
43
  def key?(id)
44
44
  key = store_key(id)
45
45
  value = store.key?(key)
46
- log_operation('KEY', store, key, value)
46
+ log_operation('KEY', self, store, key, value)
47
47
  value
48
48
  end
49
49
  alias :has_key? :key?
50
50
 
51
- def load(attrs)
51
+ def load(key, attrs)
52
52
  return nil if attrs.nil?
53
+ attrs['id'] = key
53
54
  allocate.initialize_from_database(attrs)
54
55
  end
55
56
  end
@@ -14,7 +14,8 @@ module Toy
14
14
  options[:only] = Array.wrap(options[:only]).map(&:to_sym)
15
15
  options[:except] = Array.wrap(options[:except]).map(&:to_sym)
16
16
 
17
- serializable_stuff = serializable_attributes.map(&:to_sym) + self.class.embedded_lists.keys.map(&:to_sym)
17
+ serializable_stuff = serializable_attributes.map(&:to_sym) +
18
+ self.class.embedded_lists.keys.map(&:to_sym)
18
19
 
19
20
  if options[:only].any?
20
21
  serializable_stuff &= options[:only]
@@ -14,7 +14,7 @@ module Toy
14
14
  invalid = value.compact.select { |o| !o.valid? }
15
15
  if invalid.any?
16
16
  record.errors.add(name, 'is invalid')
17
- logger.debug("ToyStore IEM")
17
+ logger.debug("ToyStore #{self.name} IEM")
18
18
  invalid.each do |o|
19
19
  logger.debug(" #{o.attributes.inspect} - #{o.errors.full_messages.inspect}")
20
20
  end
data/lib/toy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Toy
2
- VERSION = "0.6.1"
2
+ VERSION = "0.6.2"
3
3
  end
data/spec/helper.rb CHANGED
@@ -31,5 +31,6 @@ Rspec.configure do |c|
31
31
  c.before(:each) do
32
32
  Toy.clear
33
33
  Toy.reset
34
+ Toy.key_factory = nil
34
35
  end
35
36
  end
@@ -1,4 +1,8 @@
1
1
  class NameAndNumberKeyFactory < Toy::Identity::AbstractKeyFactory
2
+ def key_type
3
+ String
4
+ end
5
+
2
6
  def next_key(object)
3
7
  "#{object.name}-#{object.number}" unless object.name.nil? || object.number.nil?
4
8
  end
@@ -52,6 +52,10 @@ describe Toy::Attributes do
52
52
  @game.persisted_attributes.should have_key('moves')
53
53
  end
54
54
 
55
+ it "includes ids of embedded" do
56
+ @game.persisted_attributes['moves'][0].should have_key('id')
57
+ end
58
+
55
59
  it "does not include virtual attributes" do
56
60
  @game.persisted_attributes.should_not have_key(:creator_score)
57
61
  end
@@ -328,6 +332,12 @@ describe Toy::Attributes do
328
332
  end
329
333
  let(:user) { @user }
330
334
 
335
+ it "reloads id from database" do
336
+ id = user.id
337
+ user.reload
338
+ user.id.should == id
339
+ end
340
+
331
341
  it "reloads record from the database" do
332
342
  user.name = 'Steve'
333
343
  user.reload
@@ -1,6 +1,12 @@
1
1
  require 'helper'
2
2
 
3
3
  describe Toy::Identity::AbstractKeyFactory do
4
+ it "should raise not implemented for #key_type" do
5
+ lambda {
6
+ Toy::Identity::AbstractKeyFactory.new.key_type
7
+ }.should raise_error(NotImplementedError)
8
+ end
9
+
4
10
  it "should raise not implemented error for #next_key" do
5
11
  lambda { Toy::Identity::AbstractKeyFactory.new.next_key("any object") }.should raise_error(NotImplementedError)
6
12
  end
@@ -2,8 +2,35 @@ require 'helper'
2
2
  require 'toy/identity/object_id_key_factory'
3
3
 
4
4
  describe Toy::Identity::ObjectIdKeyFactory do
5
+ uses_constants('User')
6
+
7
+ it "should use String as store_type" do
8
+ Toy::Identity::ObjectIdKeyFactory.new.key_type.should be(BSON::ObjectId)
9
+ end
10
+
5
11
  it "should use object id for next key" do
6
12
  key = Toy::Identity::ObjectIdKeyFactory.new.next_key(nil)
7
13
  key.should be_instance_of(BSON::ObjectId)
8
14
  end
15
+
16
+ describe "Declaring key to be object_id" do
17
+ before(:each) do
18
+ User.key(:object_id)
19
+ User.attribute(:name, String)
20
+ end
21
+
22
+ it "sets id attribute to BSON::ObjectId type" do
23
+ User.attributes['id'].type.should be(BSON::ObjectId)
24
+ end
25
+
26
+ it "correctly stores id in database" do
27
+ user = User.create(:name => 'John')
28
+ user.id.should be_instance_of(BSON::ObjectId)
29
+ # key_for in memory adapter marshals non symbol/string keys
30
+ # so we have to unmarshal to get the key type
31
+ key = Marshal.load(user.store.client.keys.first)
32
+ key.should be_instance_of(BSON::ObjectId)
33
+ user.id.should == key
34
+ end
35
+ end
9
36
  end
@@ -1,7 +1,23 @@
1
1
  require 'helper'
2
2
 
3
3
  describe Toy::Identity::UUIDKeyFactory do
4
+ uses_constants('User')
5
+
6
+ it "should use String as store_type" do
7
+ Toy::Identity::UUIDKeyFactory.new.key_type.should be(String)
8
+ end
9
+
4
10
  it "should use uuid for next key" do
5
11
  Toy::Identity::UUIDKeyFactory.new.next_key(nil).length.should == 36
6
12
  end
13
+
14
+ describe "Declaring key to be object_id" do
15
+ before(:each) do
16
+ User.key(:uuid)
17
+ end
18
+
19
+ it "sets id attribute to String type" do
20
+ User.attributes['id'].type.should be(String)
21
+ end
22
+ end
7
23
  end
@@ -24,7 +24,7 @@ describe Toy::IdentityMap do
24
24
  end
25
25
 
26
26
  it "adds to map on load" do
27
- user = User.load({'id' => '1'})
27
+ user = User.load('1', 'id' => '1')
28
28
  user.should be_in_identity_map
29
29
  end
30
30
 
@@ -84,7 +84,7 @@ describe Toy::IdentityMap do
84
84
 
85
85
  it "does not add to map on load" do
86
86
  User.identity_map_off
87
- user = User.load('id' => '1')
87
+ user = User.load('1', 'name' => 'John')
88
88
  user.should_not be_in_identity_map
89
89
  end
90
90
 
@@ -13,12 +13,12 @@ describe Toy::Identity do
13
13
  end
14
14
 
15
15
  it "should set key factory passed in factory" do
16
- factory = Toy::Identity::UUIDKeyFactory
16
+ factory = Toy::Identity::UUIDKeyFactory.new
17
17
  User.key(factory).should == factory
18
18
  end
19
19
 
20
20
  it "should use Toy.key_factory by default" do
21
- key_factory = mock
21
+ key_factory = Toy::Identity::UUIDKeyFactory.new
22
22
  Toy.key_factory = key_factory
23
23
  klass = Class.new { include Toy::Store }
24
24
 
@@ -31,14 +31,14 @@ describe Toy::Identity do
31
31
 
32
32
  describe ".next_key" do
33
33
  it "should call the next key on the key factory" do
34
- factory = Toy::Identity::UUIDKeyFactory
34
+ factory = Toy::Identity::UUIDKeyFactory.new
35
35
  factory.should_receive(:next_key).and_return('some_key')
36
36
  User.key(factory)
37
37
  User.next_key.should == 'some_key'
38
38
  end
39
39
 
40
40
  it "should raise an exception for nil key" do
41
- factory = Toy::Identity::UUIDKeyFactory
41
+ factory = Toy::Identity::UUIDKeyFactory.new
42
42
  factory.should_receive(:next_key).and_return(nil)
43
43
  User.key(factory)
44
44
  lambda { User.next_key }.should raise_error
@@ -315,7 +315,6 @@ describe Toy::List do
315
315
  end
316
316
 
317
317
  it "sets the inverse association" do
318
- # @game.chats.should include(@chat)
319
318
  @chat.game.should == @game
320
319
  end
321
320
  end
@@ -15,9 +15,9 @@ describe Toy::Logger do
15
15
  let(:adapter) { Adapter[:memory].new({}) }
16
16
 
17
17
  it "logs operation" do
18
- User.logger.should_receive(:debug).with('ToyStore GET :memory "foo"')
18
+ User.logger.should_receive(:debug).with('ToyStore GET User :memory "foo"')
19
19
  User.logger.should_receive(:debug).with(' "bar"')
20
- User.log_operation('GET', adapter, 'foo', 'bar')
20
+ User.log_operation('GET', User, adapter, 'foo', 'bar')
21
21
  end
22
22
  end
23
23
 
@@ -25,9 +25,9 @@ describe Toy::Logger do
25
25
  let(:adapter) { Adapter[:memory].new({}) }
26
26
 
27
27
  it "logs operation" do
28
- User.logger.should_receive(:debug).with('ToyStore GET :memory "foo"')
28
+ User.logger.should_receive(:debug).with('ToyStore GET User :memory "foo"')
29
29
  User.logger.should_receive(:debug).with(' "bar"')
30
- User.log_operation('GET', adapter, 'foo', 'bar')
30
+ User.log_operation('GET', User, adapter, 'foo', 'bar')
31
31
  end
32
32
  end
33
33
  end
@@ -95,7 +95,6 @@ describe Toy::Persistence do
95
95
  it "creates key in database with attributes" do
96
96
  User.store.read(doc.store_key).should == {
97
97
  'name' => 'John',
98
- 'id' => doc.id,
99
98
  'age' => 50,
100
99
  }
101
100
  end
@@ -286,9 +285,10 @@ describe Toy::Persistence do
286
285
 
287
286
  describe "with cache store" do
288
287
  before do
288
+ User.attribute(:name, String)
289
289
  @cache = User.cache(:memory, {})
290
290
  @memory = User.store(:memory, {})
291
- @user = User.create
291
+ @user = User.create(:name => 'John')
292
292
  end
293
293
 
294
294
  let(:cache) { @cache }
@@ -296,8 +296,8 @@ describe Toy::Persistence do
296
296
  let(:user) { @user }
297
297
 
298
298
  it "writes to cache and store" do
299
- cache[user.store_key].should == user.persisted_attributes
300
- memory[user.store_key].should == user.persisted_attributes
299
+ cache[user.store_key].should == {'name' => 'John'}
300
+ memory[user.store_key].should == {'name' => 'John'}
301
301
  end
302
302
  end
303
303
  end
@@ -88,7 +88,7 @@ describe Toy::Querying do
88
88
  end
89
89
 
90
90
  describe ".load (with hash)" do
91
- before { @doc = User.load(:id => '1', :name => 'John') }
91
+ before { @doc = User.load('1', :name => 'John') }
92
92
  let(:doc) { @doc }
93
93
 
94
94
  it "returns instance" do
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 6
8
- - 1
9
- version: 0.6.1
8
+ - 2
9
+ version: 0.6.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Geoffrey Dagley
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-03 00:00:00 -05:00
18
+ date: 2011-02-04 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency