couchbase-model-relationship 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,197 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'rubygems'
5
+ require 'bundler/setup'
6
+ require 'rspec/core'
7
+
8
+ require 'couchbase'
9
+ require 'couchbase/model'
10
+
11
+ require 'socket'
12
+ require 'open-uri'
13
+
14
+ class CouchbaseServer
15
+ attr_accessor :host, :port, :num_nodes, :buckets_spec
16
+
17
+ def real?
18
+ true
19
+ end
20
+
21
+ def initialize(params = {})
22
+ @host, @port = ENV['COUCHBASE_SERVER'].split(':')
23
+ @port = @port.to_i
24
+
25
+ if @host.nil? || @host.empty? || @port == 0
26
+ raise ArgumentError, "Check COUCHBASE_SERVER variable. It should be hostname:port"
27
+ end
28
+
29
+ @config = Yajl::Parser.parse(open("http://#{@host}:#{@port}/pools/default"))
30
+ @num_nodes = @config["nodes"].size
31
+ @buckets_spec = params[:buckets_spec] || "default:" # "default:,protected:secret,cache::memcache"
32
+ end
33
+
34
+ def start
35
+ # flush all buckets
36
+ @buckets_spec.split(',') do |bucket|
37
+ name, password, _ = bucket.split(':')
38
+ connection = Couchbase.new(:hostname => @host,
39
+ :port => @port,
40
+ :username => name,
41
+ :bucket => name,
42
+ :password => password)
43
+ connection.flush
44
+ end
45
+ end
46
+ def stop; end
47
+ end
48
+
49
+ class CouchbaseMock
50
+ Monitor = Struct.new(:pid, :client, :socket, :port)
51
+
52
+ attr_accessor :host, :port, :buckets_spec, :num_nodes, :num_vbuckets
53
+
54
+ def real?
55
+ false
56
+ end
57
+
58
+ def initialize(params = {})
59
+ @host = "127.0.0.1"
60
+ @port = 0
61
+ @num_nodes = 10
62
+ @num_vbuckets = 4096
63
+ @buckets_spec = "default:" # "default:,protected:secret,cache::memcache"
64
+ params.each do |key, value|
65
+ send("#{key}=", value)
66
+ end
67
+ yield self if block_given?
68
+ if @num_vbuckets < 1 || (@num_vbuckets & (@num_vbuckets - 1) != 0)
69
+ raise ArgumentError, "Number of vbuckets should be a power of two and greater than zero"
70
+ end
71
+ end
72
+
73
+ def start
74
+ @monitor = Monitor.new
75
+ @monitor.socket = TCPServer.new(nil, 0)
76
+ @monitor.socket.listen(10)
77
+ _, @monitor.port, _, _ = @monitor.socket.addr
78
+ trap("CLD") do
79
+ puts "CouchbaseMock.jar died unexpectedly during startup"
80
+ exit(1)
81
+ end
82
+ @monitor.pid = fork
83
+ if @monitor.pid.nil?
84
+ rc = exec(command_line("--harakiri-monitor=:#{@monitor.port}"))
85
+ else
86
+ trap("CLD", "SIG_DFL")
87
+ @monitor.client, _ = @monitor.socket.accept
88
+ @port = @monitor.client.recv(100).to_i
89
+ end
90
+ end
91
+
92
+ def stop
93
+ @monitor.client.close
94
+ @monitor.socket.close
95
+ Process.kill("TERM", @monitor.pid)
96
+ Process.wait(@monitor.pid)
97
+ end
98
+
99
+ def failover_node(index, bucket = "default")
100
+ @monitor.client.send("failover,#{index},#{bucket}", 0)
101
+ end
102
+
103
+ def respawn_node(index, bucket = "default")
104
+ @monitor.client.send("respawn,#{index},#{bucket}", 0)
105
+ end
106
+
107
+ protected
108
+
109
+ def command_line(extra = nil)
110
+ cmd = "java -jar #{File.dirname(__FILE__)}/CouchbaseMock.jar"
111
+ cmd << " --host #{@host}" if @host
112
+ cmd << " --port #{@port}" if @port
113
+ cmd << " --nodes #{@num_nodes}" if @num_nodes
114
+ cmd << " --vbuckets #{@num_vbuckets}" if @num_vbuckets
115
+ cmd << " --buckets #{@buckets_spec}" if @buckets_spec
116
+ cmd << " #{extra}"
117
+ cmd
118
+ end
119
+ end
120
+
121
+ require 'couchbase/model/relationship'
122
+
123
+ module RspecHelpers
124
+ def stub_instance(klass, stubs = {}, mocks = {})
125
+ stub = stub(klass.name)
126
+ stub.responds_like_instance_of(klass)
127
+
128
+ stub.stubs(stubs) if stubs && ! stubs.empty?
129
+ stub.mocks(mocks) if mocks && ! mocks.empty?
130
+
131
+ stub
132
+ end
133
+
134
+ def stub_klass(klass)
135
+ stub = stub(klass.name)
136
+ stub.responds_like(klass)
137
+
138
+ stub
139
+ end
140
+
141
+ def stub_server(*klasses)
142
+ Thread.current['mock'] = start_mock
143
+ bucket = Couchbase.connect(:hostname => @mock.host, :port => @mock.port)
144
+ [Post, ValidPost, Brewery, Beer, Attachment].each do |model|
145
+ model.bucket = bucket
146
+ end
147
+ bucket
148
+ end
149
+
150
+ def start_mock(params = {})
151
+ mock = nil
152
+ if ENV['COUCHBASE_SERVER']
153
+ mock = CouchbaseServer.new(params)
154
+ if (params[:port] && mock.port != params[:port]) ||
155
+ (params[:host] && mock.host != params[:host]) ||
156
+ mock.buckets_spec != "default:"
157
+ skip("Unable to configure real cluster. Requested config is: #{params.inspect}")
158
+ end
159
+ else
160
+ mock = CouchbaseMock.new(params)
161
+ end
162
+ mock.start
163
+ mock
164
+ end
165
+
166
+ def stop_mock(mock = Thread.current['mock'])
167
+ mock.stop if mock
168
+ end
169
+
170
+ def with_mock(params = {})
171
+ mock = nil
172
+ if block_given?
173
+ mock = start_mock(params)
174
+ yield mock
175
+ end
176
+ ensure
177
+ stop_mock(mock) if mock
178
+ end
179
+
180
+ def uniq_id(*suffixes)
181
+ [caller.first[/.*[` ](.*)'/, 1], suffixes].join("_")
182
+ end
183
+ end
184
+
185
+
186
+ RSpec.configure do |config|
187
+ config.mock_framework = :mocha
188
+ config.include RspecHelpers
189
+
190
+ #config.after(:suite) do
191
+ # stop_mock
192
+ #end
193
+ end
194
+
195
+ Mocha::Configuration.prevent :stubbing_non_existent_method
196
+ Mocha::Configuration.prevent :stubbing_method_on_nil
197
+
metadata ADDED
@@ -0,0 +1,246 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: couchbase-model-relationship
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jon Moses
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activemodel
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: activesupport
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '3'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3'
46
+ - !ruby/object:Gem::Dependency
47
+ name: couchbase
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1'
62
+ - !ruby/object:Gem::Dependency
63
+ name: couchbase-model
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.5.3
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.5.3
78
+ - !ruby/object:Gem::Dependency
79
+ name: json
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 1.7.7
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.7.7
94
+ - !ruby/object:Gem::Dependency
95
+ name: multi_json
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - '='
100
+ - !ruby/object:Gem::Version
101
+ version: 1.7.5
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - '='
108
+ - !ruby/object:Gem::Version
109
+ version: 1.7.5
110
+ - !ruby/object:Gem::Dependency
111
+ name: bundler
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '1.3'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '1.3'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rake
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: rspec
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: mocha
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ description: Closely bound relationships for Couchbase::Model
175
+ email:
176
+ - jon@burningbush.us
177
+ executables: []
178
+ extensions: []
179
+ extra_rdoc_files: []
180
+ files:
181
+ - .gitignore
182
+ - Gemfile
183
+ - LICENSE.txt
184
+ - README.md
185
+ - Rakefile
186
+ - couchbase-model-relationship.gemspec
187
+ - lib/couchbase/model/attributes.rb
188
+ - lib/couchbase/model/complex_attributes.rb
189
+ - lib/couchbase/model/deep_copier.rb
190
+ - lib/couchbase/model/dirty.rb
191
+ - lib/couchbase/model/id_prefix.rb
192
+ - lib/couchbase/model/relationship.rb
193
+ - lib/couchbase/model/relationship/association.rb
194
+ - lib/couchbase/model/relationship/child.rb
195
+ - lib/couchbase/model/relationship/parent.rb
196
+ - lib/couchbase/model/relationship/version.rb
197
+ - spec/association_spec.rb
198
+ - spec/attributes_spec.rb
199
+ - spec/child_spec.rb
200
+ - spec/complex_attributes_spec.rb
201
+ - spec/deep_copier_spec.rb
202
+ - spec/dirty_spec.rb
203
+ - spec/id_prefix_spec.rb
204
+ - spec/parent_spec.rb
205
+ - spec/spec_helper.rb
206
+ homepage: https://github.com/jmoses/couchbase-model-relationship
207
+ licenses:
208
+ - MIT
209
+ post_install_message:
210
+ rdoc_options: []
211
+ require_paths:
212
+ - lib
213
+ required_ruby_version: !ruby/object:Gem::Requirement
214
+ none: false
215
+ requirements:
216
+ - - ! '>='
217
+ - !ruby/object:Gem::Version
218
+ version: '0'
219
+ segments:
220
+ - 0
221
+ hash: -2574960161948404974
222
+ required_rubygems_version: !ruby/object:Gem::Requirement
223
+ none: false
224
+ requirements:
225
+ - - ! '>='
226
+ - !ruby/object:Gem::Version
227
+ version: '0'
228
+ segments:
229
+ - 0
230
+ hash: -2574960161948404974
231
+ requirements: []
232
+ rubyforge_project:
233
+ rubygems_version: 1.8.24
234
+ signing_key:
235
+ specification_version: 3
236
+ summary: Supports relationships that are fetched and saved with a root model
237
+ test_files:
238
+ - spec/association_spec.rb
239
+ - spec/attributes_spec.rb
240
+ - spec/child_spec.rb
241
+ - spec/complex_attributes_spec.rb
242
+ - spec/deep_copier_spec.rb
243
+ - spec/dirty_spec.rb
244
+ - spec/id_prefix_spec.rb
245
+ - spec/parent_spec.rb
246
+ - spec/spec_helper.rb