kvom 6.8.0.beta.200.869.9609b39 → 6.8.0.beta.200.883.f5f063b

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,12 +1,9 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gem "activesupport" # adapter (core), storage (core), file_system_storage
4
- gem "couchrest" # couchdb_adapter
4
+ gem "rack" # file_system_storage (active_support/cache/file_store requires rack/utils)
5
5
  gem "aws-sdk" # dynamodb_adapter, s3_storage
6
- gem "rack" # file_system_storage
7
- # active_support/cache/file_store requires rack/utils
8
6
 
9
- # not that if any kvom source depends on it ;-)
10
7
  gem "pry" # the debugging shell
11
8
 
12
9
  gemspec
@@ -42,10 +42,13 @@ class DynamodbDocument < KeyAttributesDocument
42
42
  case value
43
43
  when nil
44
44
  # skip
45
+ when ""
46
+ # will not raise an error when persisted, but will be returned as nil
47
+ raise unsupported_value(value)
45
48
  when String, Fixnum, BigDecimal
46
49
  memo[name] = value
47
50
  else
48
- raise "Unsupported value type #{value.class.to_s}"
51
+ raise unsupported_value(value)
49
52
  end
50
53
  memo
51
54
  end
@@ -4,7 +4,17 @@ module Kvom; module Adapter
4
4
 
5
5
  class FilesystemDocument < KeyAttributesDocument
6
6
  def to_json
7
- Lib::Json.dump(attributes || {})
7
+ # supported values restricted to the ones of dynamo_document
8
+ attributes.each do |key, value|
9
+ case value
10
+ when ""
11
+ raise unsupported_value(value)
12
+ when nil, String, Fixnum # BigDecimal is not standard ruby
13
+ else
14
+ raise unsupported_value(value)
15
+ end
16
+ end
17
+ Lib::Json.dump(attributes)
8
18
  end
9
19
  end
10
20
 
@@ -1,5 +1,6 @@
1
- require 'kvom'
1
+ require 'kvom/adapter'
2
2
 
3
+ # :enddoc:
3
4
  module Kvom; module Adapter;
4
5
 
5
6
  class KeyAttributesDocument < Document
@@ -12,15 +13,24 @@ class KeyAttributesDocument < Document
12
13
  end
13
14
 
14
15
  def [](name)
15
- @attributes ||= load_attributes
16
16
  @attributes[name]
17
17
  end
18
18
 
19
19
  def []=(name, value)
20
- @attributes ||= load_attributes
21
20
  @attributes[name] = value
22
21
  end
23
22
 
23
+ private
24
+
25
+ def unsupported_value(value)
26
+ case value
27
+ when ""
28
+ "Unsupported value: empty string"
29
+ else
30
+ "Unsupported value type: #{value.class.to_s}"
31
+ end
32
+ end
33
+
24
34
  end
25
35
 
26
36
  end; end # module Kvom::Adapter
@@ -12,6 +12,7 @@ class Base
12
12
  include ModelIdentity
13
13
  extend ActiveModel::Naming
14
14
 
15
+
15
16
  class_attribute :key_prefix
16
17
 
17
18
  class << self
@@ -63,17 +64,16 @@ class Base
63
64
  end
64
65
 
65
66
  def initialize(doc_or_attrs = {})
66
- if doc_or_attrs.is_a?(Document)
67
- @document = doc_or_attrs
68
- else
69
- attrs = doc_or_attrs.stringify_keys
70
-
71
- attrs["id"] ||= SecureRandom.hex(8)
72
-
73
- id = attrs["id"]
74
- @document = self.class.adapter.new_document(self.class.key_for(id), attrs)
75
- @new = true
76
- end
67
+ @document =
68
+ case doc_or_attrs
69
+ when Document
70
+ doc_or_attrs
71
+ else
72
+ @new = true
73
+ attrs = doc_or_attrs.stringify_keys
74
+ key = self.class.key_for(attrs["id"] ||= SecureRandom.hex(8))
75
+ self.class.adapter.new_document(key, attrs)
76
+ end
77
77
  end
78
78
 
79
79
  def document
@@ -89,14 +89,6 @@ class Base
89
89
  @document["id"]
90
90
  end
91
91
 
92
- def read_attribute(name)
93
- @document[name]
94
- end
95
-
96
- def write_attribute(name, value)
97
- @document[name] = value
98
- end
99
-
100
92
  def new?
101
93
  @new
102
94
  end
@@ -105,6 +97,16 @@ class Base
105
97
  self.class.adapter.destroy(@document)
106
98
  end
107
99
 
100
+ private
101
+
102
+ def read_attribute(name)
103
+ @document[name]
104
+ end
105
+
106
+ def write_attribute(name, value)
107
+ @document[name] = value
108
+ end
109
+
108
110
  end
109
111
 
110
112
  end # module Kvom
@@ -16,12 +16,6 @@ describe Kvom::Base do
16
16
  expect { ModelWithoutAdapter.find("spam") }.to raise_error(/overwritten/)
17
17
  end
18
18
 
19
- it "should provide access to the underlying document" do
20
- example = ExampleModel.create(:spam => "foo")
21
- example.document["spam"].should == "foo"
22
- example.document.should be_a(Kvom::Document)
23
- end
24
-
25
19
  describe "getters and setters" do
26
20
  it "work for freshly created models" do
27
21
  example = ExampleModel.create(:spam => "foo")
@@ -44,6 +38,68 @@ describe Kvom::Base do
44
38
  loaded = ExampleModel.find(example.id)
45
39
  loaded.spam.should == "foo"
46
40
  end
41
+
42
+ context "when setting an empty string as property value" do
43
+
44
+ context "when created" do
45
+ it "raises an error" do
46
+ expect {ExampleModel.create(:spam => "")}.to raise_error "Unsupported value: empty string"
47
+ end
48
+ end
49
+
50
+ context "when saved" do
51
+ let(:example) {ExampleModel.create(:property => "not empty")}
52
+
53
+ it "raises an error" do
54
+ expect {
55
+ example.spam = ""
56
+ example.save
57
+ }.to raise_error "Unsupported value: empty string"
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ context "when setting a value of an unsupported value class" do
65
+ context "when saved" do
66
+ let(:example) {ExampleModel.create(:property => "valid type")}
67
+
68
+ it "raises an error" do
69
+ expect {
70
+ example.spam = %w[invalid type array]
71
+ example.save
72
+ }.to raise_error "Unsupported value type: Array"
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+
81
+ describe "#save" do
82
+
83
+ context "when loaded from database" do
84
+
85
+ let(:example_id) {ExampleModel.create(:spam => "ham").id}
86
+ let(:example_from_db) {ExampleModel.find(example_id)}
87
+
88
+ context "when modified" do
89
+ before do
90
+ example_from_db.spam = "and eggs"
91
+ end
92
+
93
+ it "persists the new value to the database" do
94
+ expect {
95
+ example_from_db.save
96
+ }.to change {
97
+ ExampleModel.find(example_id).spam
98
+ }.to("and eggs")
99
+ end
100
+
101
+ end
102
+ end
47
103
  end
48
104
 
49
105
  it "should accept an id as string or symbol" do
@@ -53,13 +109,13 @@ describe Kvom::Base do
53
109
  ExampleModel.find(second_id)
54
110
  end
55
111
 
56
- describe "model id's" do
112
+ describe "model's id" do
57
113
  it "should use a custom prefix when given" do
58
- CustomKeyPrefixModel.new.document.key.should =~ /^spam_prefix\/id\/.+/
114
+ CustomKeyPrefixModel.new.__send__(:document).key.should =~ /^spam_prefix\/id\/.+/
59
115
  end
60
116
 
61
117
  it "should use a default prefix" do
62
- ExampleModel.new.document.key.should =~ /^ExampleModel\/id\/.+/
118
+ ExampleModel.new.__send__(:document).key.should =~ /^ExampleModel\/id\/.+/
63
119
  end
64
120
  end
65
121
 
@@ -5,16 +5,7 @@ require File.expand_path("../../lib/kvom", __FILE__)
5
5
  class TestModel < Kvom::Base
6
6
  def self.adapter
7
7
  @adapter ||=
8
- case (type = ENV['KVOM_ADAPTER_TYPE'] || "couch")
9
- when "couch"
10
- require 'multi_json'
11
- MultiJson.engine = :yajl
12
- database_name = "kvom-unit_tests"
13
- adapter = Kvom::Adapter::CouchdbAdapter.new({
14
- :url => database_name,
15
- })
16
- CouchRest.database!(database_name)
17
- adapter
8
+ case (type = ENV['KVOM_ADAPTER_TYPE'] || "file")
18
9
  when /dynamo/
19
10
  require File.expand_path("../../../tasks/support/local_config", __FILE__)
20
11
  options = {
@@ -24,7 +15,7 @@ class TestModel < Kvom::Base
24
15
  }
25
16
  options[:partition] = "korb" if type == "partitioned_dynamo"
26
17
  Kvom::Adapter::DynamodbAdapter.new(options)
27
- when /filesystem/
18
+ when /file/
28
19
  Kvom::Adapter::FilesystemAdapter.new(:path => File.expand_path("../../tmp/fsa", __FILE__))
29
20
  end
30
21
  end
@@ -35,28 +26,17 @@ class ExampleModel < TestModel
35
26
  end
36
27
 
37
28
  RSpec.configure do |config|
38
- output = config.output_stream || $stdout
39
-
40
- adapter_specified_and_different = lambda {|adapter_name|
41
- if adapter_name # no adapter_name => do not exclude
42
- application_adapter = TestModel.adapter.class.to_s.demodulize
43
- name = application_adapter.sub("Adapter", "").sub("db", "").downcase
44
- if name != adapter_name.to_s # same adapter name => do not exclude
45
- output.print "a"
46
- true # yes, exclude
47
- end
48
- end
29
+ adapter = TestModel.adapter.class.to_s.demodulize.sub("Adapter", "").sub("db", "").downcase
30
+ adapter_specified_and_different = lambda {|required_adapter|
31
+ required_adapter && required_adapter.to_s != adapter
49
32
  }
50
33
 
34
+ multi_json_version = Gem.loaded_specs["multi_json"].version
51
35
  multi_json_version_and_insufficient = lambda {|multi_json_version_restriction|
52
- if multi_json_version_restriction
53
- multi_json_version = Gem.loaded_specs["multi_json"].version
54
- requirement = Gem::Requirement.create(multi_json_version_restriction)
55
- !requirement.satisfied_by?(multi_json_version)
56
- end
36
+ multi_json_version_restriction && !Gem::Requirement.create(multi_json_version_restriction).
37
+ satisfied_by?(multi_json_version)
57
38
  }
58
39
 
59
- output.puts "Run filtered using adapter metadata (a - when skipped)"
60
40
  config.filter_run_excluding :adapter => adapter_specified_and_different
61
41
  config.filter_run_excluding :multi_json_version => multi_json_version_and_insufficient
62
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kvom
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11187448661
4
+ hash: 988956767
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 6
@@ -9,11 +9,13 @@ version: !ruby/object:Gem::Version
9
9
  - 0
10
10
  - beta
11
11
  - 200
12
- - 869
13
- - 9609
12
+ - 883
13
+ - f
14
+ - 5
15
+ - f
16
+ - 63
14
17
  - b
15
- - 39
16
- version: 6.8.0.beta.200.869.9609b39
18
+ version: 6.8.0.beta.200.883.f5f063b
17
19
  platform: ruby
18
20
  authors:
19
21
  - Kristian Hanekamp, Infopark AG
@@ -21,11 +23,10 @@ autorequire:
21
23
  bindir: bin
22
24
  cert_chain: []
23
25
 
24
- date: 2012-07-26 00:00:00 +02:00
26
+ date: 2012-08-10 00:00:00 +02:00
25
27
  default_executable:
26
28
  dependencies:
27
29
  - !ruby/object:Gem::Dependency
28
- type: :runtime
29
30
  requirement: &id001 !ruby/object:Gem::Requirement
30
31
  none: false
31
32
  requirements:
@@ -35,11 +36,11 @@ dependencies:
35
36
  segments:
36
37
  - 1
37
38
  version: "1"
38
- prerelease: false
39
- name: multi_json
40
39
  version_requirements: *id001
41
- - !ruby/object:Gem::Dependency
40
+ name: multi_json
41
+ prerelease: false
42
42
  type: :runtime
43
+ - !ruby/object:Gem::Dependency
43
44
  requirement: &id002 !ruby/object:Gem::Requirement
44
45
  none: false
45
46
  requirements:
@@ -49,11 +50,11 @@ dependencies:
49
50
  segments:
50
51
  - 3
51
52
  version: "3"
52
- prerelease: false
53
- name: activesupport
54
53
  version_requirements: *id002
55
- - !ruby/object:Gem::Dependency
54
+ name: activesupport
55
+ prerelease: false
56
56
  type: :runtime
57
+ - !ruby/object:Gem::Dependency
57
58
  requirement: &id003 !ruby/object:Gem::Requirement
58
59
  none: false
59
60
  requirements:
@@ -63,11 +64,11 @@ dependencies:
63
64
  segments:
64
65
  - 3
65
66
  version: "3"
66
- prerelease: false
67
- name: activemodel
68
67
  version_requirements: *id003
68
+ name: activemodel
69
+ prerelease: false
70
+ type: :runtime
69
71
  - !ruby/object:Gem::Dependency
70
- type: :development
71
72
  requirement: &id004 !ruby/object:Gem::Requirement
72
73
  none: false
73
74
  requirements:
@@ -78,11 +79,11 @@ dependencies:
78
79
  - 2
79
80
  - 8
80
81
  version: "2.8"
81
- prerelease: false
82
- name: rspec
83
82
  version_requirements: *id004
84
- - !ruby/object:Gem::Dependency
83
+ name: rspec
84
+ prerelease: false
85
85
  type: :development
86
+ - !ruby/object:Gem::Dependency
86
87
  requirement: &id005 !ruby/object:Gem::Requirement
87
88
  none: false
88
89
  requirements:
@@ -92,11 +93,11 @@ dependencies:
92
93
  segments:
93
94
  - 0
94
95
  version: "0"
95
- prerelease: false
96
- name: helpful_configuration
97
96
  version_requirements: *id005
98
- - !ruby/object:Gem::Dependency
97
+ name: helpful_configuration
98
+ prerelease: false
99
99
  type: :development
100
+ - !ruby/object:Gem::Dependency
100
101
  requirement: &id006 !ruby/object:Gem::Requirement
101
102
  none: false
102
103
  requirements:
@@ -106,9 +107,10 @@ dependencies:
106
107
  segments:
107
108
  - 0
108
109
  version: "0"
109
- prerelease: false
110
- name: yajl-ruby
111
110
  version_requirements: *id006
111
+ name: yajl-ruby
112
+ prerelease: false
113
+ type: :development
112
114
  description: Use it to build object models in ruby on top of a key value store.
113
115
  email:
114
116
  - kristian.hanekamp@infopark.de
@@ -126,8 +128,6 @@ files:
126
128
  - lib/kvom.rb
127
129
  - lib/kvom/adapter.rb
128
130
  - lib/kvom/adapter/base.rb
129
- - lib/kvom/adapter/couchdb_adapter.rb
130
- - lib/kvom/adapter/couchdb_document.rb
131
131
  - lib/kvom/adapter/dynamodb_adapter.rb
132
132
  - lib/kvom/adapter/dynamodb_document.rb
133
133
  - lib/kvom/adapter/filesystem_adapter.rb
@@ -1,83 +0,0 @@
1
- require 'kvom/adapter'
2
- require 'couchrest'
3
-
4
- module Kvom; module Adapter
5
-
6
- class CouchdbAdapter < Base
7
-
8
- def new_document(key, attributes)
9
- new_document_from_attributes(attributes.merge("_id" => key))
10
- end
11
-
12
- def save(doc)
13
- doc.couchrest_document.save
14
- end
15
-
16
- def get(key)
17
- doc =
18
- begin
19
- count_request {database.get(key) }
20
- rescue RestClient::ResourceNotFound
21
- raise NotFound.for_key(key)
22
- end
23
- CouchdbDocument.new(doc)
24
- end
25
-
26
- def query(hash_value, range_value)
27
- params =
28
- case range_value
29
- when Range
30
- {
31
- :startkey => "#{hash_value}|#{range_value.begin}",
32
- :endkey => "#{hash_value}|#{range_value.end}",
33
- }
34
- else
35
- {
36
- :key => "#{hash_value}|#{range_value}",
37
- }
38
- end
39
-
40
- params[:include_docs] = true
41
- count_request {database.all_docs(params)["rows"]}.map do |entry|
42
- new_document_from_attributes(entry["doc"])
43
- end
44
- end
45
-
46
- def destroy(doc)
47
- doc.couchrest_document.destroy
48
- end
49
-
50
- private
51
-
52
- def database_url
53
- connection_spec[:url]
54
- end
55
-
56
- def new_document_from_attributes(attributes)
57
- couch_doc = CouchRest::Document.new(attributes)
58
- couch_doc.database = database
59
- CouchdbDocument.new(couch_doc)
60
- end
61
-
62
- def database
63
- @database ||= CouchRest.database(database_url)
64
- end
65
-
66
- module BlobSupport
67
-
68
- def blob_url(id)
69
- "#{ database_url }/#{ id }/blob"
70
- end
71
-
72
- def blob_attachment(id)
73
- document = count_request {database.get(id)}
74
- document["_attachments"]["blob"]
75
- end
76
-
77
- end
78
-
79
- include BlobSupport
80
-
81
- end
82
-
83
- end; end # module Kvom::Adapter
@@ -1,27 +0,0 @@
1
- require 'kvom/adapter'
2
-
3
- module Kvom; module Adapter
4
-
5
- class CouchdbDocument < Document
6
-
7
- attr_accessor :couchrest_document
8
-
9
- def initialize(couchrest_document)
10
- self.couchrest_document = couchrest_document
11
- end
12
-
13
- def [](name)
14
- couchrest_document[name]
15
- end
16
-
17
- def []=(name, value)
18
- couchrest_document[name] = value
19
- end
20
-
21
- def key
22
- couchrest_document.id
23
- end
24
-
25
- end
26
-
27
- end; end # module Kvom::Adapter