couchbase-jruby-model 0.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,124 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011, 2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require File.join(File.dirname(__FILE__), 'setup')
19
+
20
+ class ActiveUser < Couchbase::Model
21
+ attribute :name
22
+ attribute :email
23
+ attribute :role
24
+ attribute :created_at, :updated_at, :default => lambda { Time.now.utc }
25
+
26
+ validates_presence_of :email
27
+ validates :role, :presence => true, :inclusion => { :in => %w(admin editor) }
28
+
29
+ before_create :upcase_name
30
+
31
+ private
32
+
33
+ def upcase_name
34
+ self.name = self.name.upcase unless self.name.nil?
35
+ end
36
+ end
37
+
38
+ class ActiveObj < Couchbase::Model
39
+ end
40
+
41
+ class TestActiveModelIntegration < MiniTest::Unit::TestCase
42
+
43
+ include ActiveModel::Lint::Tests
44
+
45
+ def setup
46
+ @model = ActiveUser.new # used by ActiveModel::Lint::Tests
47
+ @mock = start_mock
48
+ bucket = Couchbase.connect(:hostname => @mock.host, :port => @mock.port)
49
+ ActiveObj.bucket = ActiveUser.bucket = bucket
50
+ end
51
+
52
+ def teardown
53
+ stop_mock(@mock)
54
+ end
55
+
56
+ def test_active_model_includes
57
+ [
58
+ ActiveModel::Conversion,
59
+ ActiveModel::Validations,
60
+ ActiveModel::Validations::Callbacks,
61
+ ActiveModel::Validations::HelperMethods
62
+ ].each do |mod|
63
+ assert ActiveUser.ancestors.include?(mod), "Model not including #{mod}"
64
+ end
65
+ end
66
+
67
+ def test_callbacks
68
+ [
69
+ :before_validation, :after_validation,
70
+ :after_initialize, :before_create, :around_create,
71
+ :after_create, :before_delete, :around_delete,
72
+ :after_delete, :before_save, :around_save, :after_save,
73
+ :before_update, :around_update, :after_update
74
+ ].each do |callback|
75
+ assert ActiveObj.respond_to?(callback), "Model doesn't support callback: #{callback}"
76
+ end
77
+ end
78
+
79
+ def test_active_model_validations
80
+ no_role = ActiveUser.new(:email => 'joe@example.com', :role => nil)
81
+ bad_role = ActiveUser.new(:email => 'joe@example.com', :role => 'bad')
82
+ good_role = ActiveUser.new(:email => 'joe@example.com', :role => 'admin')
83
+
84
+ refute no_role.valid?
85
+ refute bad_role.valid?
86
+ assert good_role.valid?
87
+ end
88
+
89
+ def test_active_model_validation_helpers
90
+ valid = ActiveUser.new(:email => 'joe@example.com', :role => 'editor')
91
+ invalid = ActiveUser.new(:name => 'Joe', :role => 'editor')
92
+
93
+ assert valid.valid?
94
+ refute invalid.valid?
95
+ end
96
+
97
+ def test_before_save_callback
98
+ assert user = ActiveUser.create(:name => 'joe', :role => 'admin', :email => 'joe@example.com')
99
+ assert_equal 'JOE', user.name
100
+ end
101
+
102
+ def test_model_name_exposes_singular_and_human_name
103
+ assert_equal 'active_user', @model.class.model_name.singular
104
+ assert_equal 'Active user', @model.class.model_name.human
105
+ end
106
+
107
+ def test_model_equality
108
+ obj1 = ActiveObj.create
109
+ obj2 = ActiveObj.find(obj1.id)
110
+
111
+ assert_equal obj1, obj2
112
+ end
113
+
114
+ def test_to_key
115
+ assert_equal ['the-id'], ActiveObj.new(:id => 'the-id').to_key
116
+ assert_equal ['the-key'], ActiveObj.new(:key => 'the-key').to_key
117
+ end
118
+
119
+ def test_to_param
120
+ assert_equal 'the-id', ActiveObj.new(:id => 'the-id').to_param
121
+ assert_equal 'the-key', ActiveObj.new(:key => ['the', 'key']).to_param
122
+ end
123
+
124
+ end
@@ -0,0 +1,311 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011, 2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require File.join(File.dirname(__FILE__), 'setup')
19
+
20
+ class Post < Couchbase::Model
21
+ attribute :title
22
+ attribute :body
23
+ attribute :author, :default => 'Anonymous'
24
+ attribute :created_at, :default => lambda { Time.utc('2010-01-01') }
25
+ end
26
+
27
+ class ValidPost < Couchbase::Model
28
+ attribute :title
29
+
30
+ def valid?
31
+ title && !title.empty?
32
+ end
33
+ end
34
+
35
+ class Brewery < Couchbase::Model
36
+ attribute :name
37
+ end
38
+
39
+ class Beer < Couchbase::Model
40
+ attribute :name
41
+ belongs_to :brewery
42
+ end
43
+
44
+ class Attachment < Couchbase::Model
45
+ defaults :format => :plain
46
+ end
47
+
48
+ class Comments < Couchbase::Model
49
+ include Enumerable
50
+ attribute :comments, :default => []
51
+ end
52
+
53
+ class User < Couchbase::Model
54
+ design_document :people
55
+ end
56
+
57
+ class TestModel < MiniTest::Unit::TestCase
58
+
59
+ def setup
60
+ @mock = start_mock
61
+ bucket = Couchbase.connect(:hostname => @mock.host, :port => @mock.port)
62
+ [Post, ValidPost, Brewery, Beer, Attachment].each do |model|
63
+ model.bucket = bucket
64
+ end
65
+ end
66
+
67
+ def teardown
68
+ stop_mock(@mock)
69
+ end
70
+
71
+ def test_design_document
72
+ assert_equal 'people', User.design_document
73
+ assert_equal 'new_people', User.design_document('new_people')
74
+ assert_equal 'post', Post.design_document
75
+ end
76
+
77
+ def test_it_supports_value_property
78
+ doc = {
79
+ 'id' => 'x',
80
+ 'key' => 'x',
81
+ 'value' => 'x',
82
+ 'doc' => {
83
+ 'value' => {'title' => 'foo'}
84
+ }
85
+ }
86
+ post = Post.wrap(Post.bucket, doc)
87
+ assert_equal 'foo', post.title
88
+ end
89
+
90
+ def test_it_supports_json_property
91
+ doc = {
92
+ 'id' => 'x',
93
+ 'key' => 'x',
94
+ 'value' => 'x',
95
+ 'doc' => {
96
+ 'json' => {'title' => 'foo'}
97
+ }
98
+ }
99
+ post = Post.wrap(Post.bucket, doc)
100
+ assert_equal 'foo', post.title
101
+ end
102
+
103
+ def test_assigns_attributes_from_the_hash
104
+ post = Post.new(:title => 'Hello, world')
105
+ assert_equal 'Hello, world', post.title
106
+ refute post.body
107
+ refute post.id
108
+ end
109
+
110
+ def test_uses_default_value_or_nil
111
+ post = Post.new(:title => 'Hello, world')
112
+ refute post.body
113
+ assert_equal 'Anonymous', post.author
114
+ assert_equal 'Anonymous', post.attributes[:author]
115
+ end
116
+
117
+ def test_allows_lambda_as_default_value
118
+ post = Post.new(:title => 'Hello, world')
119
+ expected = Time.utc('2010-01-01')
120
+ assert_equal expected, post.created_at
121
+ assert_equal expected, post.attributes[:created_at]
122
+ end
123
+
124
+ def test_assings_id_and_saves_the_object
125
+ post = Post.create(:title => 'Hello, world')
126
+ assert post.id
127
+ end
128
+
129
+ def test_updates_attributes
130
+ post = Post.create(:title => 'Hello, world')
131
+ post.update(:body => 'This is my first example')
132
+ assert_equal 'This is my first example', post.body
133
+ end
134
+
135
+ def test_refreshes_the_attributes_with_reload_method
136
+ orig = Post.create(:title => 'Hello, world')
137
+ double = Post.find(orig.id)
138
+ double.update(:title => 'Good bye, world')
139
+ orig.reload
140
+ assert_equal 'Good bye, world', orig.title
141
+ end
142
+
143
+ def test_reloads_cas_value_with_reload_method
144
+ orig = Post.create(:title => "Hello, world")
145
+ double = Post.find(orig.id)
146
+ orig.update(:title => "Good bye, world")
147
+ double.reload
148
+
149
+ assert_equal orig.meta[:cas], double.meta[:cas]
150
+ end
151
+
152
+ def test_it_raises_not_found_exception
153
+ assert_raises Couchbase::Error::NotFound do
154
+ Post.find('missing_key')
155
+ end
156
+ end
157
+
158
+ def test_it_returns_nil_when_key_not_found
159
+ refute Post.find_by_id('missing_key')
160
+ end
161
+
162
+ def test_doesnt_raise_if_the_attribute_redefined
163
+ eval <<-EOC
164
+ class RefinedPost < Couchbase::Model
165
+ attribute :title
166
+ attribute :title
167
+ end
168
+ EOC
169
+ end
170
+
171
+ def test_allows_to_define_several_attributes_at_once
172
+ eval <<-EOC
173
+ class Comment < Couchbase::Model
174
+ attribute :name, :email, :body
175
+ end
176
+ EOC
177
+
178
+ comment = Comment.new
179
+ assert_respond_to comment, :name
180
+ assert_respond_to comment, :email
181
+ assert_respond_to comment, :body
182
+ end
183
+
184
+ def test_allows_arbitrary_ids
185
+ Post.create(:id => uniq_id, :title => 'Foo')
186
+ assert_equal 'Foo', Post.find(uniq_id).title
187
+ end
188
+
189
+ def test_returns_an_instance_of_post
190
+ Post.bucket.set(uniq_id, {:title => 'foo'})
191
+ assert Post.find(uniq_id).kind_of?(Post)
192
+ assert_equal uniq_id, Post.find(uniq_id).id
193
+ assert_equal 'foo', Post.find(uniq_id).title
194
+ end
195
+
196
+ def test_changes_its_attributes
197
+ post = Post.create(:title => 'Hello, world')
198
+ post.title = 'Good bye, world'
199
+ post.save.reload
200
+ assert_equal 'Good bye, world', post.title
201
+ end
202
+
203
+ def test_assings_a_new_id_to_each_record
204
+ post1 = Post.create
205
+ post2 = Post.create
206
+
207
+ refute post1.new?
208
+ refute post2.new?
209
+ refute_equal post1.id, post2.id
210
+ end
211
+
212
+ def test_deletes_an_existent_model
213
+ post = Post.create(:id => uniq_id)
214
+ assert post.delete
215
+ assert_raises Couchbase::Error::NotFound do
216
+ Post.bucket.get(uniq_id)
217
+ end
218
+ end
219
+
220
+ def test_fails_to_delete_model_without_id
221
+ post = Post.new(:title => 'Hello')
222
+ refute post.id
223
+ assert_raises Couchbase::Error::MissingId do
224
+ post.delete
225
+ end
226
+ end
227
+
228
+ def test_belongs_to_assoc
229
+ brewery = Brewery.create(:name => 'Anheuser-Busch')
230
+ assert_includes Beer.attributes.keys, :brewery_id
231
+ beer = Beer.create(:name => 'Budweiser', :brewery_id => brewery.id)
232
+ assert_respond_to beer, :brewery
233
+ assoc = beer.brewery
234
+ assert_instance_of Brewery, assoc
235
+ assert_equal 'Anheuser-Busch', assoc.name
236
+ end
237
+
238
+ def test_to_key
239
+ assert_equal ['the-id'], Post.new(:id => 'the-id').to_key
240
+ assert_equal ['the-key'], Post.new(:key => 'the-key').to_key
241
+ end
242
+
243
+ def test_to_param
244
+ assert_equal 'the-id', Post.new(:id => 'the-id').to_param
245
+ assert_equal 'the-key', Post.new(:key => ['the', 'key']).to_param
246
+ end
247
+
248
+ def test_as_json
249
+ require 'active_support/json/encoding'
250
+
251
+ response = {'id' => 'the-id'}
252
+ assert_equal response, Post.new(:id => 'the-id').as_json
253
+
254
+ response = {}
255
+ assert_equal response, Post.new(:id => 'the-id').as_json(:except => :id)
256
+ end
257
+
258
+ def test_validation
259
+ post = ValidPost.create(:title => 'Hello, World!')
260
+ assert post.valid?, 'post with title should be valid'
261
+ post.title = nil
262
+ refute post.save
263
+ assert_raises(Couchbase::Error::RecordInvalid) do
264
+ post.save!
265
+ end
266
+ refute ValidPost.create(:title => nil)
267
+ assert_raises(Couchbase::Error::RecordInvalid) do
268
+ ValidPost.create!(:title => nil)
269
+ end
270
+ end
271
+
272
+ def test_blob_documents
273
+ contents = File.read(__FILE__)
274
+ id = Attachment.create(:raw => contents).id
275
+ blob = Attachment.find(id)
276
+ assert_equal contents, blob.raw
277
+ end
278
+
279
+ def test_couchbase_ancestor
280
+ assert_equal Couchbase::Model, Comments.couchbase_ancestor
281
+ end
282
+
283
+ def test_returns_multiple_instances_of_post
284
+ Post.create(:id => uniq_id('first'), :title => 'foo')
285
+ Post.create(:id => uniq_id('second'), :title => 'bar')
286
+
287
+ results = Post.find([uniq_id('first'), uniq_id('second')])
288
+ assert results.kind_of?(Array)
289
+ assert results.size == 2
290
+ assert results.detect { |post| post.id == uniq_id('first') }.title == 'foo'
291
+ assert results.detect { |post| post.id == uniq_id('second') }.title == 'bar'
292
+ end
293
+
294
+ def test_returns_array_for_array_of_ids
295
+ Post.create(:id => uniq_id('first'), :title => 'foo')
296
+
297
+ results = Post.find([uniq_id('first')])
298
+ assert results.kind_of?(Array)
299
+ assert results.size == 1
300
+ assert results[0].title == 'foo'
301
+ end
302
+
303
+ def test_returns_array_for_array_of_ids_using_find_by_id
304
+ Post.create(:id => uniq_id('first'), :title => 'foo')
305
+
306
+ results = Post.find_by_id([uniq_id('first')])
307
+ assert results.kind_of?(Array)
308
+ assert results.size == 1
309
+ assert results[0].title == 'foo'
310
+ end
311
+ end
@@ -0,0 +1,76 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011, 2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require File.join(File.dirname(__FILE__), 'setup')
19
+
20
+ class Program < Couchbase::Model
21
+ attribute :title
22
+ attribute :genres, :default => []
23
+ end
24
+
25
+ class Movie < Program
26
+ attribute :mpaa_rating
27
+ attribute :runtime
28
+ end
29
+
30
+ class Series < Program
31
+ attribute :vchip_rating
32
+ end
33
+
34
+ class Episode < Series
35
+ attribute :runtime
36
+ end
37
+
38
+ class TestModelRailsIntegration < MiniTest::Unit::TestCase
39
+
40
+ def test_class_attributes_are_inheritable
41
+ program_attributes = [:title, :genres]
42
+ movie_attributes = [:mpaa_rating, :runtime]
43
+ series_attributes = [:vchip_rating]
44
+ episode_attributes = [:runtime]
45
+
46
+ assert_equal program_attributes, Program.attributes.keys
47
+ assert_equal program_attributes + movie_attributes, Movie.attributes.keys
48
+ assert_equal program_attributes + series_attributes, Series.attributes.keys
49
+ assert_equal program_attributes + series_attributes + episode_attributes, Episode.attributes.keys
50
+ end
51
+
52
+ def test_default_attributes_are_inheritable
53
+ assert_equal nil, Movie.attributes[:title]
54
+ assert_equal [], Movie.attributes[:genres]
55
+ end
56
+
57
+ def test_instance_attributes_are_inheritable
58
+ episode = Episode.new(:title => 'Family Guy', :genres => ['Comedy'], :vchip_rating => 'TVPG', :runtime => 30)
59
+
60
+ assert_equal [:title, :genres, :vchip_rating, :runtime], episode.attributes.keys
61
+ assert_equal 'Family Guy', episode.title
62
+ assert_equal ['Comedy'], episode.genres
63
+ assert_equal 30, episode.runtime
64
+ assert_equal 'TVPG', episode.vchip_rating
65
+ end
66
+
67
+ def test_class_attributes_from_subclasses_do_not_propogate_up_ancestor_chain
68
+ assert_equal [:title, :genres, :vchip_rating], Series.attributes.keys
69
+ end
70
+
71
+ def test_instance_attributes_from_subclasses_do_not_propogate_up_ancestor_chain
72
+ series = Series.new(:title => 'Family Guy', :genres => ['Comedy'], :vchip_rating => 'TVPG')
73
+ assert_equal [:title, :genres, :vchip_rating], series.attributes.keys
74
+ end
75
+
76
+ end