rrod 0.0.1 → 1.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +33 -18
- data/lib/rrod/all.rb +24 -1
- data/lib/rrod/caster/nested_model.rb +16 -0
- data/lib/rrod/caster.rb +34 -0
- data/lib/rrod/cli.rb +9 -2
- data/lib/rrod/configuration.rb +40 -0
- data/lib/rrod/model/attribute.rb +80 -0
- data/lib/rrod/model/attribute_methods.rb +85 -0
- data/lib/rrod/model/collection.rb +37 -0
- data/lib/rrod/model/finders.rb +59 -0
- data/lib/rrod/model/persistence.rb +35 -0
- data/lib/rrod/model/schema.rb +30 -0
- data/lib/rrod/model/serialization.rb +12 -0
- data/lib/rrod/model.rb +38 -0
- data/lib/rrod/query.rb +30 -0
- data/lib/rrod/test_server/rspec.rb +50 -0
- data/lib/rrod/test_server/runner.rb +56 -0
- data/lib/rrod/test_server.rb +77 -0
- data/lib/rrod/version.rb +2 -3
- data/rrod.gemspec +7 -1
- data/spec/rrod/caster_spec.rb +117 -0
- data/spec/rrod/configuration_spec.rb +55 -0
- data/spec/rrod/model/attribute_methods_spec.rb +64 -0
- data/spec/rrod/model/attribute_spec.rb +102 -0
- data/spec/rrod/model/collection_spec.rb +39 -0
- data/spec/rrod/model/finders_spec.rb +78 -0
- data/spec/rrod/model/persistence_spec.rb +43 -0
- data/spec/rrod/model/schema_spec.rb +59 -0
- data/spec/rrod/model/serialization_spec.rb +17 -0
- data/spec/rrod/model/validations_spec.rb +50 -0
- data/spec/rrod/model_spec.rb +50 -0
- data/spec/rrod/query_spec.rb +34 -0
- data/spec/rrod_spec.rb +4 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/models/car.rb +3 -0
- data/spec/support/models/person.rb +41 -0
- data/spec/support/test_server.yml.example +17 -0
- metadata +106 -5
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rrod/test_server'
|
2
|
+
|
3
|
+
module Rrod
|
4
|
+
class TestServer
|
5
|
+
module RSpec
|
6
|
+
|
7
|
+
def self.enable!
|
8
|
+
Rrod.configure do |config|
|
9
|
+
# We have to use http to set bucket props (to enable search index)
|
10
|
+
# https://github.com/basho/riak-ruby-client/blob/v1.4.2/lib/riak/client.rb#L500
|
11
|
+
config.http_port = Rrod::TestServer.http_port
|
12
|
+
config.pb_port = Rrod::TestServer.pb_port
|
13
|
+
end
|
14
|
+
|
15
|
+
::RSpec.configure do |config|
|
16
|
+
config.before(:each, :integration => true) do
|
17
|
+
if Rrod::TestServer.fatal
|
18
|
+
fail "Test server not working: #{Rrod::TestServer.fatal}"
|
19
|
+
end
|
20
|
+
|
21
|
+
if example.metadata[:test_server] == false
|
22
|
+
Rrod::TestServer.stop
|
23
|
+
else
|
24
|
+
Rrod::TestServer.create unless Rrod::TestServer.exist?
|
25
|
+
unless Rrod::TestServer.started?
|
26
|
+
@rspec_started = true
|
27
|
+
Rrod::TestServer.start
|
28
|
+
Rrod::TestServer.wait_for_search
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
config.after(:each, :integration => true) do
|
34
|
+
# i really don't understand this...
|
35
|
+
if !Rrod::TestServer.fatal &&
|
36
|
+
Rrod::TestServer.started? &&
|
37
|
+
example.metadata[:test_server] != false
|
38
|
+
Rrod::TestServer.drop
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
config.after(:suite) do
|
43
|
+
Rrod::TestServer.stop if @rspec_started && Rrod::TestServer.started?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rrod/test_server'
|
2
|
+
|
3
|
+
module Rrod
|
4
|
+
class TestServer
|
5
|
+
class Runner
|
6
|
+
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
def self.run
|
10
|
+
instance.run
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.signal_queue
|
14
|
+
@signal_queue ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
define_signal_traps
|
19
|
+
|
20
|
+
Rrod::TestServer.tap { |server|
|
21
|
+
puts "starting rrod test server"
|
22
|
+
server.config[:root].tap { |root| FileUtils.rm_rf root if Dir.exists? root }
|
23
|
+
server.create unless server.exist?
|
24
|
+
server.start unless server.started?
|
25
|
+
begin puts "waiting for search..." end until server.search_started?
|
26
|
+
puts "started."
|
27
|
+
}
|
28
|
+
|
29
|
+
setup_run_loop
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def setup_run_loop
|
35
|
+
loop do
|
36
|
+
case self.class.signal_queue.shift
|
37
|
+
when nil
|
38
|
+
sleep 1 # not really sure what to do here
|
39
|
+
when :INT, :TERM, :QUIT
|
40
|
+
puts
|
41
|
+
puts "shutting down rrod test server"
|
42
|
+
Rrod::TestServer.stop
|
43
|
+
break
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def define_signal_traps
|
49
|
+
[:INT, :TERM, :QUIT].each do |signal|
|
50
|
+
Signal.trap(signal) { self.class.signal_queue << signal }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# The test server was copied directly out of
|
2
|
+
# riak-ruby-client/spec/support/test_server.rb
|
3
|
+
# and refactored into a class that can be used
|
4
|
+
# to control the server's lifecycle
|
5
|
+
|
6
|
+
require 'yaml'
|
7
|
+
require 'riak/test_server'
|
8
|
+
|
9
|
+
module Rrod
|
10
|
+
class TestServer
|
11
|
+
attr_reader :fatal
|
12
|
+
|
13
|
+
extend Forwardable
|
14
|
+
include Singleton
|
15
|
+
|
16
|
+
DELEGATES = %w[wait_for_search start stop create drop http_port pb_port config started? search_started? exist?]
|
17
|
+
|
18
|
+
class << self
|
19
|
+
extend Forwardable
|
20
|
+
def_delegators(:instance, * [:fatal] + DELEGATES)
|
21
|
+
end
|
22
|
+
|
23
|
+
def_delegators(:server, *DELEGATES)
|
24
|
+
|
25
|
+
def config
|
26
|
+
loaded = YAML.load_file(Rrod.configuration.test_server_yml)
|
27
|
+
{ min_port: 15_000 }.merge loaded.symbolize_keys
|
28
|
+
rescue Errno::ENOENT => e
|
29
|
+
message = "Cannot find Rrod::TestServer configuration. #{e.message}"
|
30
|
+
raise MissingConfigurationError.new(message)
|
31
|
+
end
|
32
|
+
|
33
|
+
def server
|
34
|
+
@server ||= try_creating_riak_test_server!
|
35
|
+
end
|
36
|
+
|
37
|
+
def search_started?
|
38
|
+
wait_for_search.chomp.eql? "riak_search is up"
|
39
|
+
end
|
40
|
+
|
41
|
+
def wait_for_search
|
42
|
+
Timeout.timeout(Rrod.configuration.test_server_search_startup_timeout) do
|
43
|
+
server.send :riak_admin, 'wait-for-service', 'riak_search', server.name
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def warn_crash_log
|
48
|
+
if @server && crash_log = @server.log + 'crash.log'
|
49
|
+
warn crash_log.read if crash_log.exist?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
attr_writer :fatal
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# TODO refactor warnings
|
60
|
+
def try_creating_riak_test_server!
|
61
|
+
Riak::TestServer.create(config)
|
62
|
+
rescue SocketError => e
|
63
|
+
warn "Couldn't connect to Riak TestServer!"
|
64
|
+
warn "Skipping remaining integration tests."
|
65
|
+
warn_crash_log
|
66
|
+
self.fatal = e
|
67
|
+
rescue => e
|
68
|
+
warn "Can't run integration specs without the test server. Please create/verify spec/support/test_server.yml."
|
69
|
+
warn "Skipping remaining integration tests."
|
70
|
+
warn e.inspect
|
71
|
+
warn_crash_log
|
72
|
+
self.fatal = e
|
73
|
+
end
|
74
|
+
|
75
|
+
MissingConfigurationError = Class.new(StandardError)
|
76
|
+
end
|
77
|
+
end
|
data/lib/rrod/version.rb
CHANGED
@@ -1,3 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
end
|
1
|
+
Rrod = Module.new unless defined? Rrod
|
2
|
+
Rrod::VERSION = '1.0.0.alpha.1'
|
data/rrod.gemspec
CHANGED
@@ -18,11 +18,17 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_dependency "riak-client", "~> 1.4.2"
|
22
|
+
spec.add_dependency "activemodel", ">= 3.2"
|
23
|
+
spec.add_dependency "activesupport", ">= 3.2"
|
24
|
+
spec.add_dependency "american_date", ">= 1.1.0"
|
25
|
+
|
26
|
+
# cli deps
|
21
27
|
spec.add_dependency "thor", "~> 0.18"
|
22
28
|
spec.add_dependency "pry", "~> 0.9"
|
23
29
|
|
24
30
|
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
-
spec.add_development_dependency "rspec",
|
31
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
26
32
|
|
27
33
|
spec.add_development_dependency "rake"
|
28
34
|
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rrod::Caster do
|
4
|
+
let(:type) { nil }
|
5
|
+
let(:caster) { "#{described_class}::#{type}".constantize }
|
6
|
+
|
7
|
+
describe "BigDecimal" do
|
8
|
+
let(:type) { 'BigDecimal' }
|
9
|
+
it "converts to big decimal" do
|
10
|
+
expect(caster.rrod_cast("42")).to eq 42
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "Boolean" do
|
15
|
+
let(:type) { 'Boolean' }
|
16
|
+
it "converts to true" do
|
17
|
+
expect(caster.rrod_cast(true)).to be true
|
18
|
+
end
|
19
|
+
it "converts 'true' to true" do
|
20
|
+
expect(caster.rrod_cast("true")).to be true
|
21
|
+
end
|
22
|
+
it "converts 1 to true" do
|
23
|
+
expect(caster.rrod_cast(1)).to be true
|
24
|
+
end
|
25
|
+
it "converts '1' to true" do
|
26
|
+
expect(caster.rrod_cast("1")).to be true
|
27
|
+
end
|
28
|
+
it "converts to false" do
|
29
|
+
expect(caster.rrod_cast(false)).to be false
|
30
|
+
end
|
31
|
+
it "converts 'false' to false" do
|
32
|
+
expect(caster.rrod_cast("false")).to be false
|
33
|
+
end
|
34
|
+
it "converts 0 to false" do
|
35
|
+
expect(caster.rrod_cast(0)).to be false
|
36
|
+
end
|
37
|
+
it "converts '0' to false" do
|
38
|
+
expect(caster.rrod_cast("0")).to be false
|
39
|
+
end
|
40
|
+
it "converts nil to false" do
|
41
|
+
expect(caster.rrod_cast(nil)).to be false
|
42
|
+
end
|
43
|
+
it "converts everything else to true" do
|
44
|
+
expect(caster.rrod_cast(Object.new)).to be true
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "Date" do
|
50
|
+
let(:type) { 'Date' }
|
51
|
+
let(:date) { Date.parse("2013-10-31") }
|
52
|
+
it "converts db format to date" do
|
53
|
+
expect(caster.rrod_cast("2013-10-31")).to eq date
|
54
|
+
end
|
55
|
+
it "converts standard format to date" do
|
56
|
+
expect(caster.rrod_cast("31-10-2013")).to eq date
|
57
|
+
end
|
58
|
+
it "converts american format to date" do
|
59
|
+
expect(caster.rrod_cast("10/31/2013")).to eq date
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "DateTime" do
|
64
|
+
let(:type) { 'DateTime' }
|
65
|
+
let(:datetime) { "12:13:14".to_datetime }
|
66
|
+
it "converts time to datetime" do
|
67
|
+
expect(caster.rrod_cast("12:13:14")).to eq datetime
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "Float" do
|
72
|
+
let(:type) { 'Float' }
|
73
|
+
let(:floater) { 3.142 }
|
74
|
+
it "converts to floating point" do
|
75
|
+
expect(caster.rrod_cast("3.142")).to eq floater
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "Integer" do
|
80
|
+
let(:type) { 'Integer' }
|
81
|
+
it "converts to integer" do
|
82
|
+
expect(caster.rrod_cast('4')).to eq 4
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "Numeric" do
|
87
|
+
let(:type) { 'Numeric' }
|
88
|
+
it "converts to floating point" do
|
89
|
+
expect(caster.rrod_cast("3.142")).to eq 3.142
|
90
|
+
end
|
91
|
+
it "converts to integer" do
|
92
|
+
expect(caster.rrod_cast("3")).to eq 3
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "String" do
|
97
|
+
let(:type) { 'String' }
|
98
|
+
it "converts to string" do
|
99
|
+
expect(caster.rrod_cast(:string)).to eq 'string'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "Symbol" do
|
104
|
+
let(:type) { 'Symbol' }
|
105
|
+
it "converts to symbol" do
|
106
|
+
expect(caster.rrod_cast('symbol')).to eq :symbol
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "Time" do
|
111
|
+
let(:type) { 'Time' }
|
112
|
+
let(:time) { "12:13:14".to_time }
|
113
|
+
it "converts to time" do
|
114
|
+
expect(caster.rrod_cast("12:13:14")).to eq time
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rrod do
|
4
|
+
|
5
|
+
it "adds a configure method to the Rrod module" do
|
6
|
+
expect(Rrod).to respond_to(:configure)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "yields the configuration to the block given to config" do
|
10
|
+
Rrod.configure do |config|
|
11
|
+
config.pb_port = 123456
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "adds a configuration object to the Rrod module" do
|
16
|
+
expect(Rrod.configuration).to be_a Rrod::Configuration
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Rrod::Configuration do
|
22
|
+
|
23
|
+
let(:config) { described_class.new }
|
24
|
+
|
25
|
+
describe "defaults" do
|
26
|
+
it "will use spec/support/test_server.yml for the test_server_yml" do
|
27
|
+
expect(config.test_server_yml).to match('spec/support/test_server.yml')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "client" do
|
32
|
+
it "creates a client based on its options" do
|
33
|
+
config.pb_port = 123456
|
34
|
+
expect(Riak::Client).to receive(:new).with(pb_port: 123456, protocol: 'pbc')
|
35
|
+
config.client
|
36
|
+
end
|
37
|
+
|
38
|
+
it "will not create a client if one exists" do
|
39
|
+
config.client = Riak::Client.new
|
40
|
+
expect(Riak::Client).not_to receive(:new)
|
41
|
+
config.client
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "attributes" do
|
46
|
+
%w[http_port pb_port protocol client test_server_yml
|
47
|
+
test_server_search_startup_timeout nodes].each do |attribute|
|
48
|
+
it "allows configuration of #{attribute}" do
|
49
|
+
expect(config).to respond_to attribute
|
50
|
+
expect(config).to respond_to "#{attribute}="
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/models/car'
|
3
|
+
|
4
|
+
describe Rrod::Model do
|
5
|
+
|
6
|
+
let(:model) { Car }
|
7
|
+
let(:hash) { {wheels: 4, color: :black, make: 'Jeep'} }
|
8
|
+
let(:instance) { model.new(hash) }
|
9
|
+
|
10
|
+
describe "instantiation" do
|
11
|
+
it "can create an object with an arbitrary hash" do
|
12
|
+
expect(instance.wheels).to eq 4
|
13
|
+
expect(instance.color).to eq :black
|
14
|
+
expect(instance.make).to eq 'Jeep'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "always has an id property" do
|
18
|
+
expect(instance).to respond_to :id
|
19
|
+
expect(instance.id).to be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it "manages attribute keys as strings" do
|
23
|
+
expect(instance.attributes).to eq hash.stringify_keys
|
24
|
+
end
|
25
|
+
|
26
|
+
it "ignores modifications to the attribute hash" do
|
27
|
+
instance.attributes[:model] = 'Wrangler'
|
28
|
+
expect(instance.attributes[:model]).to be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "will return nil for an attribute that exists in the hash but does not have a corresponding method" do
|
32
|
+
instance.instance_variable_get(:@attributes)['foo'] = 'bar'
|
33
|
+
expect(instance).not_to respond_to(:foo)
|
34
|
+
expect(instance.attributes).to include('foo' => nil)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "mass assignment" do
|
38
|
+
it "will merge attributes when mass assigning" do
|
39
|
+
instance.attributes = {wheels: 5}
|
40
|
+
expect(instance.wheels).to eq 5
|
41
|
+
end
|
42
|
+
|
43
|
+
it "will not add additional attribute methods after instantiation" do
|
44
|
+
expect { instance.attributes = {model: 'Wrangler'} }.to raise_error
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "with schema" do
|
49
|
+
let(:model) { Class.new(Car) { attribute :wheels, Integer } }
|
50
|
+
|
51
|
+
it "does not allow creating with arbitrary attributes" do
|
52
|
+
expect { model.new(model: 'Jeep') }.to raise_error(NoMethodError, /model=/)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "can be created with the specified attributes" do
|
56
|
+
expect(model.new(wheels: 5).wheels).to be 5
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "query generation" do
|
61
|
+
it "lets you use strings with apostrophes in them"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rrod::Model::Attribute do
|
4
|
+
let(:options) { {presence: true} }
|
5
|
+
let(:model) { Class.new { include Rrod::Model } }
|
6
|
+
let(:instance) { model.new }
|
7
|
+
let(:name) { :name }
|
8
|
+
let(:type) { String }
|
9
|
+
let(:attribute) { described_class.new(model, name, type, options) }
|
10
|
+
|
11
|
+
it "has a model" do
|
12
|
+
expect(attribute.model).to be model
|
13
|
+
end
|
14
|
+
|
15
|
+
it "has a name" do
|
16
|
+
expect(attribute.name).to be name
|
17
|
+
end
|
18
|
+
|
19
|
+
it "typecasts name to a symbol when initializing" do
|
20
|
+
attribute = described_class.new(model, "unicorn_tears", Integer)
|
21
|
+
expect(attribute.name).to be :unicorn_tears
|
22
|
+
end
|
23
|
+
|
24
|
+
it "has a type" do
|
25
|
+
expect(attribute.type).to be type
|
26
|
+
end
|
27
|
+
|
28
|
+
it "has options" do
|
29
|
+
expect(attribute.options).to eq(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "defaults" do
|
33
|
+
context "when a value" do
|
34
|
+
let(:options) { {default: 'SOO fluffy!'} }
|
35
|
+
it "can provide a default value" do
|
36
|
+
expect(attribute.default).to eq 'SOO fluffy!'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when a proc" do
|
41
|
+
let(:options) { {default: -> { 'alligator' }} }
|
42
|
+
|
43
|
+
it "can provide a default value if a proc" do
|
44
|
+
expect(attribute.default).to eq 'alligator'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "defining attribute methods" do
|
50
|
+
before(:each) { attribute.define }
|
51
|
+
|
52
|
+
describe "getters" do
|
53
|
+
it "is defined on the declaring class" do
|
54
|
+
expect(instance).to respond_to(name)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "setters" do
|
59
|
+
it "is defined on the declaring class" do
|
60
|
+
expect(instance).to respond_to("#{name}=")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "casting" do
|
66
|
+
it "will use the types rrod_cast method if available" do
|
67
|
+
type = Class.new {
|
68
|
+
def self.rrod_cast(value)
|
69
|
+
value.to_s.upcase
|
70
|
+
end
|
71
|
+
}
|
72
|
+
model.attribute :example, type
|
73
|
+
instance.example = 'shorty'
|
74
|
+
expect(instance.example).to eq 'SHORTY'
|
75
|
+
end
|
76
|
+
|
77
|
+
it "will look for a register Rrod caster if the type cannot cast itself" do
|
78
|
+
model.attribute :example, String
|
79
|
+
instance.example = :whazzup
|
80
|
+
expect(instance.example).to eq('whazzup')
|
81
|
+
end
|
82
|
+
|
83
|
+
it "will simply return the value if all else fails" do
|
84
|
+
model.attribute :example, Class.new
|
85
|
+
instance.example = self
|
86
|
+
expect(instance.example).to be self
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "nested rrod models" do
|
90
|
+
let(:type) { [Class.new { include Rrod::Model }] }
|
91
|
+
|
92
|
+
it "can detect if the type is a nested rrod model" do
|
93
|
+
expect(attribute.send :nested_model?).to be true
|
94
|
+
end
|
95
|
+
|
96
|
+
it "adds a rrod_cast method to the nested rrod model reference object" do
|
97
|
+
attribute
|
98
|
+
expect(type).to respond_to(:rrod_cast)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/models/person'
|
3
|
+
|
4
|
+
describe Rrod::Model::Collection do
|
5
|
+
let(:array) { [Pet.new] }
|
6
|
+
let(:collection) { described_class.new(array) }
|
7
|
+
|
8
|
+
describe "initialization" do
|
9
|
+
it "takes a collection" do
|
10
|
+
expect(collection.collection).to eq(array)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "defaults to an empty collection" do
|
14
|
+
expect(described_class.new.collection).to be_an Array
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "errors" do
|
18
|
+
describe "non enumerable" do
|
19
|
+
let(:array) { Object.new }
|
20
|
+
it "raises" do
|
21
|
+
expect { collection }.to raise_error(Rrod::Model::Collection::InvalidCollectionTypeError)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "not all Rrod::Model" do
|
26
|
+
let(:array) { [Pet.new, Object.new] }
|
27
|
+
it "raises if not all `Rrod::Model`s" do
|
28
|
+
expect { collection }.to raise_error(Rrod::Model::Collection::InvalidMemberTypeError)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "clears the collection" do
|
32
|
+
collection = described_class.new
|
33
|
+
begin; collection.collection = array; rescue; end
|
34
|
+
expect(collection.collection).to be_empty
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/models/car'
|
3
|
+
|
4
|
+
describe Rrod::Model::Finders, integration: true do
|
5
|
+
|
6
|
+
let(:model) { Car }
|
7
|
+
let(:hash) { {wheels: 4, color: :black, make: 'Jeep'} }
|
8
|
+
let(:instance) { model.new(hash) }
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
instance.save
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can be found by id" do
|
15
|
+
found = model.find(instance.id)
|
16
|
+
expect(found).to be_a model
|
17
|
+
end
|
18
|
+
|
19
|
+
it "will raise an error if it can't be found" do
|
20
|
+
expect { model.find("id that is not there") }.to raise_error(Rrod::Model::NotFound)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "is persisted" do
|
24
|
+
found = model.find(instance.id)
|
25
|
+
expect(found).to be_persisted
|
26
|
+
end
|
27
|
+
|
28
|
+
it "sets the robject on the found instance" do
|
29
|
+
found = model.find(instance.id)
|
30
|
+
expect(found.robject).to be_a Riak::RObject
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "finding by attributes in the hash" do
|
34
|
+
describe "find_first_by" do
|
35
|
+
it "can find one" do
|
36
|
+
found = model.find_first_by(make: 'Jeep')
|
37
|
+
expect(found).to be_a model
|
38
|
+
expect(found.make).to eq "Jeep"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "will work properly when finding by id" do
|
42
|
+
found = model.find_first_by(id: instance.id)
|
43
|
+
expect(found).to be_a model
|
44
|
+
end
|
45
|
+
|
46
|
+
it "will return nil if one can't be found" do
|
47
|
+
found = model.find_first_by(id: "id that is not there")
|
48
|
+
expect(found).to be nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it "will raise an exception if one can't be found with a !" do
|
52
|
+
expect { model.find_first_by! zombies: true }.to raise_error(Rrod::Model::NotFound)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "find_all_by" do
|
57
|
+
it "can find all" do
|
58
|
+
founds = model.find_all_by(make: 'Jeep', wheels: 4)
|
59
|
+
found = founds.first
|
60
|
+
expect(founds).to be_an Array
|
61
|
+
expect(found).to be_a model
|
62
|
+
expect(found.make).to eq "Jeep"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "will raise an exception if finding all by id" do
|
66
|
+
expect {model.find_all_by(id: instance.id)}.to raise_error(ArgumentError)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "will return [] if none can be found" do
|
70
|
+
expect(model.find_all_by zombies: 'yes plz').to eq []
|
71
|
+
end
|
72
|
+
|
73
|
+
it "will raise an exception if none can be found with a !" do
|
74
|
+
expect { model.find_all_by! brains: :none }.to raise_error(Rrod::Model::NotFound)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|